fix(ngcc): ensure reflection hosts can handle TS 3.9 IIFE wrapped classes (#36989)
In TS 3.9, ES2015 output can contain ES classes that are wrapped in an IIFE. So now ES2015 class declarations can look like one of: ``` class OuterClass1 {} ``` ``` let OuterClass = class InnerClass {}; ``` ``` var AliasClass; let OuterClass = AliasClass = class InnerClass {}; ``` ``` let OuterClass = (() => class InnerClass {}}; ``` ``` var AliasClass; let OuterClass = AliasClass = (() => class InnerClass {})(); ``` ``` let OuterClass = (() => { let AdjacentClass = class InnerClass {}; // ... static properties or decorators attached to `AdjacentClass` return AdjacentClass; })(); ``` ``` var AliasClass; let OuterClass = AliasClass = (() => { let AdjacentClass = class InnerClass {}; // ... static properties or decorators attached to `AdjacentClass` return AdjacentClass; })(); ``` The `Esm5ReflectionHost` already handles slightly different IIFE wrappers around function-based classes. This can be substantially reused when fixing `Esm2015ReflectionHost`, since there is a lot of commonality between the two. This commit moves code from the `Esm5ReflectionHost` into the `Esm2015ReflectionHost` and looks to share as much as possible between the two hosts. PR Close #36989
This commit is contained in:

committed by
Kara Erickson

parent
a2b8dc1cfb
commit
d7440c452a
@ -14,8 +14,8 @@ import {ClassMemberKind, ConcreteDeclaration, CtorParameter, Decorator, Downleve
|
||||
import {getDeclaration} from '../../../src/ngtsc/testing';
|
||||
import {loadFakeCore, loadTestFiles} from '../../../test/helpers';
|
||||
import {DelegatingReflectionHost} from '../../src/host/delegating_host';
|
||||
import {Esm2015ReflectionHost} from '../../src/host/esm2015_host';
|
||||
import {Esm5ReflectionHost, getIifeBody} from '../../src/host/esm5_host';
|
||||
import {Esm2015ReflectionHost, getIifeBody} from '../../src/host/esm2015_host';
|
||||
import {Esm5ReflectionHost} from '../../src/host/esm5_host';
|
||||
import {NgccReflectionHost} from '../../src/host/ngcc_host';
|
||||
import {BundleProgram} from '../../src/packages/bundle_program';
|
||||
import {MockLogger} from '../helpers/mock_logger';
|
||||
@ -2283,7 +2283,8 @@ runInEachFileSystem(() => {
|
||||
const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle));
|
||||
const outerNode = getDeclaration(
|
||||
bundle.program, SIMPLE_CLASS_FILE.name, 'EmptyClass', isNamedVariableDeclaration);
|
||||
const innerNode = getIifeBody(outerNode)!.statements.find(isNamedFunctionDeclaration)!;
|
||||
const innerNode = (getIifeBody(outerNode.initializer!) as ts.Block)
|
||||
.statements.find(isNamedFunctionDeclaration)!;
|
||||
const classSymbol = host.getClassSymbol(outerNode);
|
||||
|
||||
expect(classSymbol).toBeDefined();
|
||||
@ -2297,7 +2298,8 @@ runInEachFileSystem(() => {
|
||||
const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle));
|
||||
const outerNode = getDeclaration(
|
||||
bundle.program, SIMPLE_CLASS_FILE.name, 'EmptyClass', isNamedVariableDeclaration);
|
||||
const innerNode = getIifeBody(outerNode)!.statements.find(isNamedFunctionDeclaration)!;
|
||||
const innerNode = (getIifeBody(outerNode.initializer!) as ts.Block)
|
||||
.statements.find(isNamedFunctionDeclaration)!;
|
||||
const classSymbol = host.getClassSymbol(innerNode);
|
||||
|
||||
expect(classSymbol).toBeDefined();
|
||||
@ -2312,7 +2314,8 @@ runInEachFileSystem(() => {
|
||||
const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle));
|
||||
const outerNode = getDeclaration(
|
||||
bundle.program, SIMPLE_CLASS_FILE.name, 'EmptyClass', isNamedVariableDeclaration);
|
||||
const innerNode = getIifeBody(outerNode)!.statements.find(isNamedFunctionDeclaration)!;
|
||||
const innerNode = (getIifeBody(outerNode.initializer!) as ts.Block)
|
||||
.statements.find(isNamedFunctionDeclaration)!;
|
||||
|
||||
const innerSymbol = host.getClassSymbol(innerNode)!;
|
||||
const outerSymbol = host.getClassSymbol(outerNode)!;
|
||||
@ -2327,7 +2330,8 @@ runInEachFileSystem(() => {
|
||||
const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle));
|
||||
const outerNode = getDeclaration(
|
||||
bundle.program, SIMPLE_CLASS_FILE.name, 'NoParensClass', isNamedVariableDeclaration);
|
||||
const innerNode = getIifeBody(outerNode)!.statements.find(isNamedFunctionDeclaration)!;
|
||||
const innerNode = (getIifeBody(outerNode.initializer!) as ts.Block)
|
||||
.statements.find(isNamedFunctionDeclaration)!;
|
||||
const classSymbol = host.getClassSymbol(outerNode);
|
||||
|
||||
expect(classSymbol).toBeDefined();
|
||||
@ -2343,7 +2347,8 @@ runInEachFileSystem(() => {
|
||||
const outerNode = getDeclaration(
|
||||
bundle.program, SIMPLE_CLASS_FILE.name, 'InnerParensClass',
|
||||
isNamedVariableDeclaration);
|
||||
const innerNode = getIifeBody(outerNode)!.statements.find(isNamedFunctionDeclaration)!;
|
||||
const innerNode = (getIifeBody(outerNode.initializer!) as ts.Block)
|
||||
.statements.find(isNamedFunctionDeclaration)!;
|
||||
const classSymbol = host.getClassSymbol(outerNode);
|
||||
|
||||
expect(classSymbol).toBeDefined();
|
||||
@ -2403,7 +2408,8 @@ runInEachFileSystem(() => {
|
||||
const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle));
|
||||
const outerNode = getDeclaration(
|
||||
bundle.program, SIMPLE_CLASS_FILE.name, 'EmptyClass', ts.isVariableDeclaration);
|
||||
const innerNode = getIifeBody(outerNode)!.statements.find(isNamedFunctionDeclaration)!;
|
||||
const innerNode = (getIifeBody(outerNode.initializer!) as ts.Block)
|
||||
.statements.find(isNamedFunctionDeclaration)!;
|
||||
expect(host.isClass(innerNode)).toBe(true);
|
||||
});
|
||||
|
||||
|
Reference in New Issue
Block a user