fix(ivy): ngcc - insert new imports after existing ones (#30029)
Previously, ngcc would insert new imports at the beginning of the file, for convenience. This is problematic for imports that have side-effects, as the side-effects imposed by such imports may affect the behavior of subsequent imports. This commit teaches ngcc to insert imports after any existing imports. Special care has been taken to ensure inserted constants will still follow after the inserted imports. Resolves FW-1271 PR Close #30029
This commit is contained in:
@ -26,10 +26,13 @@ export class EsmRenderer extends Renderer {
|
||||
/**
|
||||
* Add the imports at the top of the file
|
||||
*/
|
||||
addImports(output: MagicString, imports: {specifier: string; qualifier: string;}[]): void {
|
||||
// The imports get inserted at the very top of the file.
|
||||
imports.forEach(
|
||||
i => { output.appendLeft(0, `import * as ${i.qualifier} from '${i.specifier}';\n`); });
|
||||
addImports(
|
||||
output: MagicString, imports: {specifier: string; qualifier: string;}[],
|
||||
sf: ts.SourceFile): void {
|
||||
const insertionPoint = findEndOfImports(sf);
|
||||
const renderedImports =
|
||||
imports.map(i => `import * as ${i.qualifier} from '${i.specifier}';\n`).join('');
|
||||
output.appendLeft(insertionPoint, renderedImports);
|
||||
}
|
||||
|
||||
addExports(output: MagicString, entryPointBasePath: string, exports: ExportInfo[]): void {
|
||||
@ -55,14 +58,11 @@ export class EsmRenderer extends Renderer {
|
||||
if (constants === '') {
|
||||
return;
|
||||
}
|
||||
const insertionPoint = file.statements.reduce((prev, stmt) => {
|
||||
if (ts.isImportDeclaration(stmt) || ts.isImportEqualsDeclaration(stmt) ||
|
||||
ts.isNamespaceImport(stmt)) {
|
||||
return stmt.getEnd();
|
||||
}
|
||||
return prev;
|
||||
}, 0);
|
||||
output.appendLeft(insertionPoint, '\n' + constants + '\n');
|
||||
const insertionPoint = findEndOfImports(file);
|
||||
|
||||
// Append the constants to the right of the insertion point, to ensure they get ordered after
|
||||
// added imports (those are appended left to the insertion point).
|
||||
output.appendRight(insertionPoint, '\n' + constants + '\n');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -115,6 +115,17 @@ export class EsmRenderer extends Renderer {
|
||||
}
|
||||
}
|
||||
|
||||
function findEndOfImports(sf: ts.SourceFile): number {
|
||||
for (const stmt of sf.statements) {
|
||||
if (!ts.isImportDeclaration(stmt) && !ts.isImportEqualsDeclaration(stmt) &&
|
||||
!ts.isNamespaceImport(stmt)) {
|
||||
return stmt.getStart();
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
function findStatement(node: ts.Node) {
|
||||
while (node) {
|
||||
if (ts.isExpressionStatement(node)) {
|
||||
|
@ -155,7 +155,9 @@ export abstract class Renderer {
|
||||
renderConstantPool(compiledFile.sourceFile, compiledFile.constantPool, importManager),
|
||||
compiledFile.sourceFile);
|
||||
|
||||
this.addImports(outputText, importManager.getAllImports(compiledFile.sourceFile.fileName));
|
||||
this.addImports(
|
||||
outputText, importManager.getAllImports(compiledFile.sourceFile.fileName),
|
||||
compiledFile.sourceFile);
|
||||
}
|
||||
|
||||
// Add exports to the entry-point file
|
||||
@ -185,7 +187,7 @@ export abstract class Renderer {
|
||||
});
|
||||
|
||||
this.addModuleWithProvidersParams(outputText, renderInfo.moduleWithProviders, importManager);
|
||||
this.addImports(outputText, importManager.getAllImports(dtsFile.fileName));
|
||||
this.addImports(outputText, importManager.getAllImports(dtsFile.fileName), dtsFile);
|
||||
|
||||
this.addExports(outputText, dtsFile.fileName, renderInfo.privateExports);
|
||||
|
||||
@ -246,8 +248,9 @@ export abstract class Renderer {
|
||||
|
||||
protected abstract addConstants(output: MagicString, constants: string, file: ts.SourceFile):
|
||||
void;
|
||||
protected abstract addImports(output: MagicString, imports: {specifier: string,
|
||||
qualifier: string}[]): void;
|
||||
protected abstract addImports(
|
||||
output: MagicString, imports: {specifier: string, qualifier: string}[],
|
||||
sf: ts.SourceFile): void;
|
||||
protected abstract addExports(
|
||||
output: MagicString, entryPointBasePath: string, exports: ExportInfo[]): void;
|
||||
protected abstract addDefinitions(
|
||||
|
Reference in New Issue
Block a user