fix(ngcc): ensure rendering formatters work with IIFE wrapped classes (#36989)
After the refactoring of the reflection hosts to accommodate ES2015 classes wrapped in IIFEs. The same treatment needs to be applied to the rendering formatters. PR Close #36989
This commit is contained in:

committed by
Kara Erickson

parent
d7440c452a
commit
c8ee390d23
@ -2489,7 +2489,7 @@ function isSynthesizedSuperCall(expression: ts.Expression): boolean {
|
||||
* Find the statement that contains the given node
|
||||
* @param node a node whose containing statement we wish to find
|
||||
*/
|
||||
function getContainingStatement(node: ts.Node): ts.Statement {
|
||||
export function getContainingStatement(node: ts.Node): ts.Statement {
|
||||
while (node.parent) {
|
||||
if (ts.isBlock(node.parent) || ts.isSourceFile(node.parent)) {
|
||||
break;
|
||||
|
@ -8,10 +8,12 @@
|
||||
import {Statement} from '@angular/compiler';
|
||||
import MagicString from 'magic-string';
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {NOOP_DEFAULT_IMPORT_RECORDER} from '../../../src/ngtsc/imports';
|
||||
import {ImportManager, translateStatement} from '../../../src/ngtsc/translator';
|
||||
import {CompiledClass} from '../analysis/types';
|
||||
import {getIifeBody} from '../host/esm5_host';
|
||||
import {getContainingStatement} from '../host/esm2015_host';
|
||||
|
||||
import {EsmRenderingFormatter} from './esm_rendering_formatter';
|
||||
|
||||
/**
|
||||
@ -20,11 +22,24 @@ import {EsmRenderingFormatter} from './esm_rendering_formatter';
|
||||
*/
|
||||
export class Esm5RenderingFormatter extends EsmRenderingFormatter {
|
||||
/**
|
||||
* Add the definitions inside the IIFE of each decorated class
|
||||
* Add the definitions, directly before the return statement, inside the IIFE of each decorated
|
||||
* class.
|
||||
*/
|
||||
addDefinitions(output: MagicString, compiledClass: CompiledClass, definitions: string): void {
|
||||
const iifeBody = getIifeBody(compiledClass.declaration);
|
||||
if (!iifeBody) {
|
||||
const classSymbol = this.host.getClassSymbol(compiledClass.declaration);
|
||||
if (!classSymbol) {
|
||||
throw new Error(
|
||||
`Compiled class "${compiledClass.name}" in "${
|
||||
compiledClass.declaration.getSourceFile()
|
||||
.fileName}" does not have a valid syntax.\n` +
|
||||
`Expected an ES5 IIFE wrapped function. But got:\n` +
|
||||
compiledClass.declaration.getText());
|
||||
}
|
||||
const declarationStatement =
|
||||
getContainingStatement(classSymbol.implementation.valueDeclaration);
|
||||
|
||||
const iifeBody = declarationStatement.parent;
|
||||
if (!iifeBody || !ts.isBlock(iifeBody)) {
|
||||
throw new Error(`Compiled class declaration is not inside an IIFE: ${compiledClass.name} in ${
|
||||
compiledClass.declaration.getSourceFile().fileName}`);
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ import {isDtsPath} from '../../../src/ngtsc/util/src/typescript';
|
||||
import {ModuleWithProvidersInfo} from '../analysis/module_with_providers_analyzer';
|
||||
import {ExportInfo} from '../analysis/private_declarations_analyzer';
|
||||
import {CompiledClass} from '../analysis/types';
|
||||
import {isAssignment} from '../host/esm2015_host';
|
||||
import {getContainingStatement, isAssignment} from '../host/esm2015_host';
|
||||
import {NgccReflectionHost, POST_R3_MARKER, PRE_R3_MARKER, SwitchableVariableDeclaration} from '../host/ngcc_host';
|
||||
|
||||
import {RedundantDecoratorMap, RenderingFormatter} from './rendering_formatter';
|
||||
@ -104,7 +104,8 @@ export class EsmRenderingFormatter implements RenderingFormatter {
|
||||
if (!classSymbol) {
|
||||
throw new Error(`Compiled class does not have a valid symbol: ${compiledClass.name}`);
|
||||
}
|
||||
const declarationStatement = getDeclarationStatement(classSymbol.declaration.valueDeclaration);
|
||||
const declarationStatement =
|
||||
getContainingStatement(classSymbol.implementation.valueDeclaration);
|
||||
const insertionPoint = declarationStatement.getEnd();
|
||||
output.appendLeft(insertionPoint, '\n' + definitions);
|
||||
}
|
||||
@ -277,17 +278,6 @@ export class EsmRenderingFormatter implements RenderingFormatter {
|
||||
}
|
||||
}
|
||||
|
||||
function getDeclarationStatement(node: ts.Node): ts.Statement {
|
||||
let statement = node;
|
||||
while (statement) {
|
||||
if (ts.isVariableStatement(statement) || ts.isClassDeclaration(statement)) {
|
||||
return statement;
|
||||
}
|
||||
statement = statement.parent;
|
||||
}
|
||||
throw new Error(`Class is not defined in a declaration statement: ${node.getText()}`);
|
||||
}
|
||||
|
||||
function findStatement(node: ts.Node): ts.Statement|undefined {
|
||||
while (node) {
|
||||
if (ts.isExpressionStatement(node) || ts.isReturnStatement(node)) {
|
||||
|
Reference in New Issue
Block a user