diff --git a/packages/compiler-cli/ngcc/src/host/esm5_host.ts b/packages/compiler-cli/ngcc/src/host/esm5_host.ts index 5af9c9f123..9cd7c758a8 100644 --- a/packages/compiler-cli/ngcc/src/host/esm5_host.ts +++ b/packages/compiler-cli/ngcc/src/host/esm5_host.ts @@ -382,6 +382,12 @@ export class Esm5ReflectionHost extends Esm2015ReflectionHost { * return _super.apply(this, tslib.__spread(arguments)) || this; * ``` * + * or, since TypeScript 4.2 it would be + * + * ``` + * return _super.apply(this, tslib.__spreadArray([], tslib.__read(arguments))) || this; + * ``` + * * Such constructs can be still considered as synthetic delegate constructors as they are * the product of a common TypeScript to ES5 synthetic constructor, just being downleveled * to ES5 using `tsc`. See: https://github.com/angular/angular/issues/38453. @@ -413,7 +419,10 @@ export class Esm5ReflectionHost extends Esm2015ReflectionHost { * ``` * var _this = _super.apply(this, tslib.__spread(arguments)) || this; * ``` - * + * or using the syntax emitted since TypeScript 4.2: + * ``` + * return _super.apply(this, tslib.__spreadArray([], tslib.__read(arguments))) || this; + * ``` * * @param statement a statement that may be a synthesized super call * @returns true if the statement looks like a synthesized super call @@ -447,6 +456,10 @@ export class Esm5ReflectionHost extends Esm2015ReflectionHost { * ``` * return _super.apply(this, tslib.__spread(arguments)) || this; * ``` + * or using the syntax emitted since TypeScript 4.2: + * ``` + * return _super.apply(this, tslib.__spreadArray([], tslib.__read(arguments))) || this; + * ``` * * @param statement a statement that may be a synthesized super call * @returns true if the statement looks like a synthesized super call @@ -473,6 +486,10 @@ export class Esm5ReflectionHost extends Esm2015ReflectionHost { * ``` * _super.apply(this, tslib.__spread(arguments)) || this; * ``` + * or using the syntax emitted since TypeScript 4.2: + * ``` + * return _super.apply(this, tslib.__spreadArray([], tslib.__read(arguments))) || this; + * ``` * * @param expression an expression that may represent a default super call * @returns true if the expression corresponds with the above form @@ -500,7 +517,8 @@ export class Esm5ReflectionHost extends Esm2015ReflectionHost { * This structure is generated by TypeScript when transforming ES2015 to ES5, see * https://github.com/Microsoft/TypeScript/blob/v3.2.2/src/compiler/transformers/es2015.ts#L1148-L1163 * - * Additionally, we also handle cases where `arguments` are wrapped by a TypeScript spread helper. + * Additionally, we also handle cases where `arguments` are wrapped by a TypeScript spread + * helper. * This can happen if ES2015 class output contain auto-generated constructors due to class * members. The ES2015 output will be using `super(...arguments)` to delegate to the superclass, * but once downleveled to ES5, the spread operator will be persisted through a TypeScript spread @@ -510,6 +528,12 @@ export class Esm5ReflectionHost extends Esm2015ReflectionHost { * _super.apply(this, __spread(arguments)) || this; * ``` * + * or, since TypeScript 4.2 it would be + * + * ``` + * _super.apply(this, tslib.__spreadArray([], tslib.__read(arguments))) || this; + * ``` + * * More details can be found in: https://github.com/angular/angular/issues/38453. * * @param expression an expression that may represent a default super call @@ -538,32 +562,79 @@ export class Esm5ReflectionHost extends Esm2015ReflectionHost { // The other scenario we intend to detect: The `arguments` variable might be wrapped with the // TypeScript spread helper (either through tslib or inlined). This can happen if an explicit // delegate constructor uses `super(...arguments)` in ES2015 and is downleveled to ES5 using - // `--downlevelIteration`. The output in such cases would not directly pass the function - // `arguments` to the `super` call, but wrap it in a TS spread helper. The output would match - // the following pattern: `super.apply(this, tslib.__spread(arguments))`. We check for such - // constructs below, but perform the detection of the call expression definition as last as - // that is the most expensive operation here. - if (!ts.isCallExpression(argumentsExpr) || argumentsExpr.arguments.length !== 1 || - !isArgumentsIdentifier(argumentsExpr.arguments[0])) { + // `--downlevelIteration`. + return this.isSpreadArgumentsExpression(argumentsExpr); + } + + /** + * Determines if the provided expression is one of the following call expressions: + * + * 1. `__spread(arguments)` + * 2. `__spreadArray([], __read(arguments))` + * + * The tslib helpers may have been emitted inline as in the above example, or they may be read + * from a namespace import. + */ + private isSpreadArgumentsExpression(expression: ts.Expression): boolean { + const call = this.extractKnownHelperCall(expression); + if (call === null) { return false; } - const argumentsCallExpr = argumentsExpr.expression; - let argumentsCallDeclaration: Declaration|null = null; + if (call.helper === KnownDeclaration.TsHelperSpread) { + // `__spread(arguments)` + return call.args.length === 1 && isArgumentsIdentifier(call.args[0]); + } else if (call.helper === KnownDeclaration.TsHelperSpreadArray) { + // `__spreadArray([], __read(arguments))` + if (call.args.length !== 2) { + return false; + } - // The `__spread` helper could be globally available, or accessed through a namespaced - // import. Hence we support a property access here as long as it resolves to the actual - // known TypeScript spread helper. - if (ts.isIdentifier(argumentsCallExpr)) { - argumentsCallDeclaration = this.getDeclarationOfIdentifier(argumentsCallExpr); - } else if ( - ts.isPropertyAccessExpression(argumentsCallExpr) && - ts.isIdentifier(argumentsCallExpr.name)) { - argumentsCallDeclaration = this.getDeclarationOfIdentifier(argumentsCallExpr.name); + const firstArg = call.args[0]; + if (!ts.isArrayLiteralExpression(firstArg) || firstArg.elements.length !== 0) { + return false; + } + + const secondArg = this.extractKnownHelperCall(call.args[1]); + if (secondArg === null || secondArg.helper !== KnownDeclaration.TsHelperRead) { + return false; + } + + return secondArg.args.length === 1 && isArgumentsIdentifier(secondArg.args[0]); + } else { + return false; + } + } + + /** + * Inspects the provided expression and determines if it corresponds with a known helper function + * as receiver expression. + */ + private extractKnownHelperCall(expression: ts.Expression): + {helper: KnownDeclaration, args: ts.NodeArray}|null { + if (!ts.isCallExpression(expression)) { + return null; } - return argumentsCallDeclaration !== null && - argumentsCallDeclaration.known === KnownDeclaration.TsHelperSpread; + const receiverExpr = expression.expression; + + // The helper could be globally available, or accessed through a namespaced import. Hence we + // support a property access here as long as it resolves to the actual known TypeScript helper. + let receiver: Declaration|null = null; + if (ts.isIdentifier(receiverExpr)) { + receiver = this.getDeclarationOfIdentifier(receiverExpr); + } else if (ts.isPropertyAccessExpression(receiverExpr) && ts.isIdentifier(receiverExpr.name)) { + receiver = this.getDeclarationOfIdentifier(receiverExpr.name); + } + + if (receiver === null || receiver.known === null) { + return null; + } + + return { + helper: receiver.known, + args: expression.arguments, + }; } } diff --git a/packages/compiler-cli/ngcc/test/host/commonjs_host_spec.ts b/packages/compiler-cli/ngcc/test/host/commonjs_host_spec.ts index 419fcf76d2..3143a8b15d 100644 --- a/packages/compiler-cli/ngcc/test/host/commonjs_host_spec.ts +++ b/packages/compiler-cli/ngcc/test/host/commonjs_host_spec.ts @@ -1530,11 +1530,15 @@ exports.MissingClass2 = MissingClass2; break; case 'inlined': fileHeader = - `var __spread = (this && this.__spread) || function (...args) { /* ... */ }`; + `var __spread = (this && this.__spread) || function (...args) { /* ... */ };\n` + + `var __spreadArray = (this && this.__spreadArray) || function (...args) { /* ... */ };\n` + + `var __read = (this && this.__read) || function (...args) { /* ... */ };\n`; break; case 'inlined_with_suffix': fileHeader = - `var __spread$1 = (this && this.__spread$1) || function (...args) { /* ... */ }`; + `var __spread$1 = (this && this.__spread$1) || function (...args) { /* ... */ };\n` + + `var __spreadArray$1 = (this && this.__spreadArray$1) || function (...args) { /* ... */ };\n` + + `var __read$2 = (this && this.__read$2) || function (...args) { /* ... */ };\n`; break; } const file = { @@ -1635,6 +1639,17 @@ exports.MissingClass2 = MissingClass2; expect(parameters).toBeNull(); }); + it('recognizes delegate super call using inline spreadArray helper', () => { + const parameters = getConstructorParameters( + ` + function TestClass() { + return _super.apply(this, __spreadArray([], __read(arguments))) || this; + }`, + 'inlined'); + + expect(parameters).toBeNull(); + }); + it('recognizes delegate super call using inline spread helper with suffix', () => { const parameters = getConstructorParameters( ` @@ -1646,6 +1661,17 @@ exports.MissingClass2 = MissingClass2; expect(parameters).toBeNull(); }); + it('recognizes delegate super call using inline spreadArray helper with suffix', () => { + const parameters = getConstructorParameters( + ` + function TestClass() { + return _super.apply(this, __spreadArray$1([], __read$2(arguments))) || this; + }`, + 'inlined_with_suffix'); + + expect(parameters).toBeNull(); + }); + it('recognizes delegate super call using imported spread helper', () => { const parameters = getConstructorParameters( ` @@ -1657,6 +1683,17 @@ exports.MissingClass2 = MissingClass2; expect(parameters).toBeNull(); }); + it('recognizes delegate super call using imported spreadArray helper', () => { + const parameters = getConstructorParameters( + ` + function TestClass() { + return _super.apply(this, tslib.__spreadArray([], tslib.__read(arguments))) || this; + }`, + 'imported'); + + expect(parameters).toBeNull(); + }); + describe('with class member assignment', () => { it('recognizes delegate super call using inline spread helper', () => { const parameters = getConstructorParameters( @@ -1671,6 +1708,19 @@ exports.MissingClass2 = MissingClass2; expect(parameters).toBeNull(); }); + it('recognizes delegate super call using inline spreadArray helper', () => { + const parameters = getConstructorParameters( + ` + function TestClass() { + var _this = _super.apply(this, __spreadArray([], __read(arguments))) || this; + _this.synthesizedProperty = null; + return _this; + }`, + 'inlined'); + + expect(parameters).toBeNull(); + }); + it('recognizes delegate super call using inline spread helper with suffix', () => { const parameters = getConstructorParameters( ` @@ -1684,6 +1734,19 @@ exports.MissingClass2 = MissingClass2; expect(parameters).toBeNull(); }); + it('recognizes delegate super call using inline spreadArray helper with suffix', () => { + const parameters = getConstructorParameters( + ` + function TestClass() { + var _this = _super.apply(this, __spreadArray$1([], __read$2(arguments))) || this; + _this.synthesizedProperty = null; + return _this; + }`, + 'inlined_with_suffix'); + + expect(parameters).toBeNull(); + }); + it('recognizes delegate super call using imported spread helper', () => { const parameters = getConstructorParameters( ` @@ -1696,6 +1759,19 @@ exports.MissingClass2 = MissingClass2; expect(parameters).toBeNull(); }); + + it('recognizes delegate super call using imported spreadArray helper', () => { + const parameters = getConstructorParameters( + ` + function TestClass() { + var _this = _super.apply(this, tslib.__spreadArray([], tslib.__read(arguments))) || this; + _this.synthesizedProperty = null; + return _this; + }`, + 'imported'); + + expect(parameters).toBeNull(); + }); }); it('handles the case where a unique name was generated for _super or _this', () => { diff --git a/packages/compiler-cli/ngcc/test/host/esm5_host_spec.ts b/packages/compiler-cli/ngcc/test/host/esm5_host_spec.ts index 4595d7db56..b6521969bf 100644 --- a/packages/compiler-cli/ngcc/test/host/esm5_host_spec.ts +++ b/packages/compiler-cli/ngcc/test/host/esm5_host_spec.ts @@ -1485,18 +1485,22 @@ runInEachFileSystem(() => { switch (mode) { case 'imported': - fileHeader = `import {__spread} from 'tslib';`; + fileHeader = `import {__spread, __spreadArray, __read} from 'tslib';`; break; case 'imported_namespace': fileHeader = `import * as tslib from 'tslib';`; break; case 'inlined': fileHeader = - `var __spread = (this && this.__spread) || function (...args) { /* ... */ }`; + `var __spread = (this && this.__spread) || function (...args) { /* ... */ };\n` + + `var __spreadArray = (this && this.__spreadArray) || function (...args) { /* ... */ };\n` + + `var __read = (this && this.__read) || function (...args) { /* ... */ };\n`; break; case 'inlined_with_suffix': fileHeader = - `var __spread$1 = (this && this.__spread$1) || function (...args) { /* ... */ }`; + `var __spread$1 = (this && this.__spread$1) || function (...args) { /* ... */ };\n` + + `var __spreadArray$1 = (this && this.__spreadArray$1) || function (...args) { /* ... */ };\n` + + `var __read$2 = (this && this.__read$2) || function (...args) { /* ... */ };\n`; break; } @@ -1595,6 +1599,17 @@ runInEachFileSystem(() => { expect(parameters).toBeNull(); }); + it('recognizes delegate super call using inline spreadArray helper', () => { + const parameters = getConstructorParameters( + ` + function TestClass() { + return _super.apply(this, __spreadArray([], __read(arguments))) || this; + }`, + 'inlined'); + + expect(parameters).toBeNull(); + }); + it('recognizes delegate super call using inline spread helper with suffix', () => { const parameters = getConstructorParameters( ` @@ -1606,6 +1621,17 @@ runInEachFileSystem(() => { expect(parameters).toBeNull(); }); + it('recognizes delegate super call using inline spreadArray helper with suffix', () => { + const parameters = getConstructorParameters( + ` + function TestClass() { + return _super.apply(this, __spreadArray$1([], __read$2(arguments))) || this; + }`, + 'inlined_with_suffix'); + + expect(parameters).toBeNull(); + }); + it('recognizes delegate super call using imported spread helper', () => { const parameters = getConstructorParameters( ` @@ -1617,6 +1643,17 @@ runInEachFileSystem(() => { expect(parameters).toBeNull(); }); + it('recognizes delegate super call using imported spreadArray helper', () => { + const parameters = getConstructorParameters( + ` + function TestClass() { + return _super.apply(this, __spreadArray([], __read(arguments))) || this; + }`, + 'imported'); + + expect(parameters).toBeNull(); + }); + it('recognizes delegate super call using namespace imported spread helper', () => { const parameters = getConstructorParameters( ` @@ -1628,6 +1665,17 @@ runInEachFileSystem(() => { expect(parameters).toBeNull(); }); + it('recognizes delegate super call using namespace imported spreadArray helper', () => { + const parameters = getConstructorParameters( + ` + function TestClass() { + return _super.apply(this, tslib.__spreadArray([], tslib.__read(arguments))) || this; + }`, + 'imported_namespace'); + + expect(parameters).toBeNull(); + }); + describe('with class member assignment', () => { it('recognizes delegate super call using inline spread helper', () => { const parameters = getConstructorParameters( @@ -1642,6 +1690,19 @@ runInEachFileSystem(() => { expect(parameters).toBeNull(); }); + it('recognizes delegate super call using inline spreadArray helper', () => { + const parameters = getConstructorParameters( + ` + function TestClass() { + var _this = _super.apply(this, __spreadArray([], __read(arguments))) || this; + _this.synthesizedProperty = null; + return _this; + }`, + 'inlined'); + + expect(parameters).toBeNull(); + }); + it('recognizes delegate super call using inline spread helper with suffix', () => { const parameters = getConstructorParameters( ` @@ -1655,6 +1716,19 @@ runInEachFileSystem(() => { expect(parameters).toBeNull(); }); + it('recognizes delegate super call using inline spreadArray helper with suffix', () => { + const parameters = getConstructorParameters( + ` + function TestClass() { + var _this = _super.apply(this, __spreadArray$1([], __read$2(arguments))) || this; + _this.synthesizedProperty = null; + return _this; + }`, + 'inlined_with_suffix'); + + expect(parameters).toBeNull(); + }); + it('recognizes delegate super call using imported spread helper', () => { const parameters = getConstructorParameters( ` @@ -1668,6 +1742,19 @@ runInEachFileSystem(() => { expect(parameters).toBeNull(); }); + it('recognizes delegate super call using imported spreadArray helper', () => { + const parameters = getConstructorParameters( + ` + function TestClass() { + var _this = _super.apply(this, __spreadArray([], __read(arguments))) || this; + _this.synthesizedProperty = null; + return _this; + }`, + 'imported'); + + expect(parameters).toBeNull(); + }); + it('recognizes delegate super call using namespace imported spread helper', () => { const parameters = getConstructorParameters( ` @@ -1680,6 +1767,19 @@ runInEachFileSystem(() => { expect(parameters).toBeNull(); }); + + it('recognizes delegate super call using namespace imported spreadArray helper', () => { + const parameters = getConstructorParameters( + ` + function TestClass() { + var _this = _super.apply(this, tslib.__spreadArray([], tslib.__read(arguments))) || this; + _this.synthesizedProperty = null; + return _this; + }`, + 'imported_namespace'); + + expect(parameters).toBeNull(); + }); }); it('handles the case where a unique name was generated for _super or _this', () => { diff --git a/packages/compiler-cli/ngcc/test/host/umd_host_spec.ts b/packages/compiler-cli/ngcc/test/host/umd_host_spec.ts index 359219cbdf..b7114b3bc0 100644 --- a/packages/compiler-cli/ngcc/test/host/umd_host_spec.ts +++ b/packages/compiler-cli/ngcc/test/host/umd_host_spec.ts @@ -1784,6 +1784,8 @@ runInEachFileSystem(() => { }(this, (function (exports) { 'use strict'; var __spread = (this && this.__spread) || function (...args) { /* ... */ } + var __spreadArray = (this && this.__spreadArray) || function (...args) { /* ... */ } + var __read = (this && this.__read) || function (...args) { /* ... */ } `; break; case 'inlined_with_suffix': @@ -1795,6 +1797,8 @@ runInEachFileSystem(() => { }(this, (function (exports) { 'use strict'; var __spread$1 = (this && this.__spread$1) || function (...args) { /* ... */ } + var __spreadArray$1 = (this && this.__spreadArray$1) || function (...args) { /* ... */ } + var __read$2 = (this && this.__read$2) || function (...args) { /* ... */ } `; break; } @@ -1897,6 +1901,17 @@ runInEachFileSystem(() => { expect(parameters).toBeNull(); }); + it('recognizes delegate super call using inline spreadArray helper', () => { + const parameters = getConstructorParameters( + ` + function TestClass() { + return _super.apply(this, __spreadArray([], __read(arguments))) || this; + }`, + 'inlined'); + + expect(parameters).toBeNull(); + }); + it('recognizes delegate super call using inline spread helper with suffix', () => { const parameters = getConstructorParameters( ` @@ -1908,6 +1923,17 @@ runInEachFileSystem(() => { expect(parameters).toBeNull(); }); + it('recognizes delegate super call using inline spreadArray helper with suffix', () => { + const parameters = getConstructorParameters( + ` + function TestClass() { + return _super.apply(this, __spreadArray$1([], __read$2(arguments))) || this; + }`, + 'inlined_with_suffix'); + + expect(parameters).toBeNull(); + }); + it('recognizes delegate super call using imported spread helper', () => { const parameters = getConstructorParameters( ` @@ -1919,6 +1945,17 @@ runInEachFileSystem(() => { expect(parameters).toBeNull(); }); + it('recognizes delegate super call using imported spreadArray helper', () => { + const parameters = getConstructorParameters( + ` + function TestClass() { + return _super.apply(this, tslib_1.__spreadArray([], tslib.__read(arguments))) || this; + }`, + 'imported'); + + expect(parameters).toBeNull(); + }); + describe('with class member assignment', () => { it('recognizes delegate super call using inline spread helper', () => { const parameters = getConstructorParameters( @@ -1933,6 +1970,19 @@ runInEachFileSystem(() => { expect(parameters).toBeNull(); }); + it('recognizes delegate super call using inline spreadArray helper', () => { + const parameters = getConstructorParameters( + ` + function TestClass() { + var _this = _super.apply(this, __spreadArray([], __read(arguments))) || this; + _this.synthesizedProperty = null; + return _this; + }`, + 'inlined'); + + expect(parameters).toBeNull(); + }); + it('recognizes delegate super call using inline spread helper with suffix', () => { const parameters = getConstructorParameters( ` @@ -1946,6 +1996,19 @@ runInEachFileSystem(() => { expect(parameters).toBeNull(); }); + it('recognizes delegate super call using inline spreadArray helper with suffix', () => { + const parameters = getConstructorParameters( + ` + function TestClass() { + var _this = _super.apply(this, __spreadArray$1([], __read$2(arguments))) || this; + _this.synthesizedProperty = null; + return _this; + }`, + 'inlined_with_suffix'); + + expect(parameters).toBeNull(); + }); + it('recognizes delegate super call using imported spread helper', () => { const parameters = getConstructorParameters( ` @@ -1958,6 +2021,19 @@ runInEachFileSystem(() => { expect(parameters).toBeNull(); }); + + it('recognizes delegate super call using imported spreadArray helper', () => { + const parameters = getConstructorParameters( + ` + function TestClass() { + var _this = _super.apply(this, tslib_1.__spreadArray([], tslib.__read(arguments))) || this; + _this.synthesizedProperty = null; + return _this; + }`, + 'imported'); + + expect(parameters).toBeNull(); + }); }); it('handles the case where a unique name was generated for _super or _this', () => { diff --git a/packages/compiler-cli/ngcc/test/integration/ngcc_spec.ts b/packages/compiler-cli/ngcc/test/integration/ngcc_spec.ts index ee3e863ea7..be13353b9d 100644 --- a/packages/compiler-cli/ngcc/test/integration/ngcc_spec.ts +++ b/packages/compiler-cli/ngcc/test/integration/ngcc_spec.ts @@ -348,6 +348,84 @@ runInEachFileSystem(() => { }); }); + it(`should be able to detect synthesized constructors in ES5 with downlevelIteration enabled (imported helpers)`, + () => { + setupAngularCoreEsm5(); + compileIntoApf( + 'test-package', { + '/index.ts': ` + import {Injectable} from '@angular/core'; + + @Injectable() + export class Base {} + + @Injectable() + export class SubClass extends Base { + constructor() { + // Note: mimic the situation where TS is first emitted into ES2015, resulting + // in the spread super call below, and then downleveled into ES5 using the + // "downlevelIteration" option. + super(...arguments); + this.foo = 'bar'; + } + } + `, + }, + {importHelpers: true, noEmitHelpers: true, downlevelIteration: true}); + + mainNgcc({ + basePath: '/node_modules', + targetEntryPointPath: 'test-package', + propertiesToConsider: ['esm5'], + }); + + const jsContents = fs.readFile(_(`/node_modules/test-package/esm5/src/index.js`)); + // Verify that the ES5 bundle does contain the expected downleveling syntax. + expect(jsContents).toContain('__spreadArray([], __read(arguments))'); + expect(jsContents) + .toContain( + 'var ɵSubClass_BaseFactory = /*@__PURE__*/ ɵngcc0.ɵɵgetInheritedFactory(SubClass);'); + }); + + it(`should be able to detect synthesized constructors in ES5 with downlevelIteration enabled (emitted helpers)`, + () => { + setupAngularCoreEsm5(); + compileIntoApf( + 'test-package', { + '/index.ts': ` + import {Injectable} from '@angular/core'; + + @Injectable() + export class Base {} + + @Injectable() + export class SubClass extends Base { + constructor() { + // Note: mimic the situation where TS is first emitted into ES2015, resulting + // in the spread super call below, and then downleveled into ES5 using the + // "downlevelIteration" option. + super(...arguments); + this.foo = 'bar'; + } + } + `, + }, + {importHelpers: false, noEmitHelpers: false, downlevelIteration: true}); + + mainNgcc({ + basePath: '/node_modules', + targetEntryPointPath: 'test-package', + propertiesToConsider: ['esm5'], + }); + + const jsContents = fs.readFile(_(`/node_modules/test-package/esm5/src/index.js`)); + // Verify that the ES5 bundle does contain the expected downleveling syntax. + expect(jsContents).toContain('__spreadArray([], __read(arguments))'); + expect(jsContents) + .toContain( + 'var ɵSubClass_BaseFactory = /*@__PURE__*/ ɵngcc0.ɵɵgetInheritedFactory(SubClass);'); + }); + it('should not add `const` in ES5 generated code', () => { setupAngularCoreEsm5(); compileIntoFlatEs5Package('test-package', {