Skip to content

Commit

Permalink
fix(@ngtools/webpack): import as results in the alias being undefin…
Browse files Browse the repository at this point in the history
…ed with Typescript 3.2

When using the `specifier.propertyName` with `typeChecker.getSymbolAtLocation` it will return a more detailed symbol then we originally have in the `usedSymbols` set.

We should probably use `symbol.id` to actually check if the symbols are the same, however the `id` is not exposed in the Symbol interface.

Using `node.name` will return the same symbol that we have stored in the set.

Fixes #13212
  • Loading branch information
Alan Agius authored and mgechev committed Dec 19, 2018
1 parent ad9dd1f commit 8bded93
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 1 deletion.
109 changes: 109 additions & 0 deletions packages/angular_devkit/build_angular/test/browser/aot_spec_large.ts
Expand Up @@ -30,4 +30,113 @@ describe('Browser Builder AOT', () => {
}),
).toPromise().then(done, done.fail);
});

it('works with aliased imports', (done) => {
const overrides = { aot: true };

host.writeMultipleFiles({
'src/app/app.component.ts': `import { Component } from '@angular/core';
import { from as fromPromise } from 'rxjs';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'app-component';
constructor() {
console.log(fromPromise(Promise.resolve('test')));
}
}`,
});

runTargetSpec(host, browserTargetSpec, overrides).pipe(
tap((buildEvent) => expect(buildEvent.success).toBe(true)),
tap(() => {
const fileName = join(outputPath, 'main.js');
const content = virtualFs.fileBufferToString(host.scopedSync().read(normalize(fileName)));
// if the aliased import was dropped this won't be rewired to a webpack module.
expect(content).toMatch(/rxjs__WEBPACK_IMPORTED_.+[\"from\"]/);
expect(content).not.toContain('fromPromise');
}),
).toPromise().then(done, done.fail);
});

it('works with aliased imports from an exported object literal', (done) => {
const overrides = { aot: true };

host.writeMultipleFiles({
'src/foo.ts': `
import { from as fromPromise } from 'rxjs';
export { fromPromise };
`,
'src/app/app.component.ts': `
import { Component } from '@angular/core';
import { fromPromise } from '../foo';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'app-component';
constructor() {
console.log(fromPromise(Promise.resolve('test')));
}
}`,
});

runTargetSpec(host, browserTargetSpec, overrides).pipe(
tap((buildEvent) => expect(buildEvent.success).toBe(true)),
tap(() => {
const fileName = join(outputPath, 'main.js');
const content = virtualFs.fileBufferToString(host.scopedSync().read(normalize(fileName)));
// if the aliased import was dropped this won't be rewired to a webpack module.
expect(content).toMatch(/rxjs__WEBPACK_IMPORTED_.+[\"from\"]/);
expect(content).toMatch(/rxjs__WEBPACK_IMPORTED_.+[\"fromPromise\"]/);
}),
).toPromise().then(done, done.fail);
});

it('works with aliased imports from an alias export', (done) => {
const overrides = { aot: true };

host.writeMultipleFiles({
'src/foo.ts': `
export { from as fromPromise } from 'rxjs';
`,
'src/app/app.component.ts': `
import { Component } from '@angular/core';
import { fromPromise } from '../foo';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'app-component';
constructor() {
console.log(fromPromise(Promise.resolve('test')));
}
}`,
});

runTargetSpec(host, browserTargetSpec, overrides).pipe(
tap((buildEvent) => expect(buildEvent.success).toBe(true)),
tap(() => {
const fileName = join(outputPath, 'main.js');
const content = virtualFs.fileBufferToString(host.scopedSync().read(normalize(fileName)));
// if the aliased import was dropped this won't be rewired to a webpack module.
expect(content).toMatch(/rxjs__WEBPACK_IMPORTED_.+[\"from\"]/);
expect(content).toMatch(/rxjs__WEBPACK_IMPORTED_.+[\"fromPromise\"]/);
}),
).toPromise().then(done, done.fail);
});

});
2 changes: 1 addition & 1 deletion packages/ngtools/webpack/src/transformers/elide_imports.ts
Expand Up @@ -100,7 +100,7 @@ export function elideImports(
// "import { XYZ, ... } from 'abc';"
const specifierOps = [];
for (const specifier of node.importClause.namedBindings.elements) {
if (isUnused(specifier.propertyName || specifier.name)) {
if (isUnused(specifier.name)) {
specifierOps.push(new RemoveNodeOperation(sourceFile, specifier));
}
}
Expand Down

0 comments on commit 8bded93

Please sign in to comment.