Skip to content

Commit

Permalink
fix(compiler-cli): use correct symbol name for default imported symbo…
Browse files Browse the repository at this point in the history
…ls in defer blocks

This commit addresses a problem with PR angular#53695 that introduced support for default imports,
where the actual dynamic import used in the defer loading function continued to use the
symbol name, instead of `.default` for the dynamic import. This issue went unnoticed in the
testcase because a proper instance was being generated for the `ɵsetClassMetadataAsync` function,
but not the generated dependency loader function.

Fixes angular#54491
  • Loading branch information
JoostK committed Feb 18, 2024
1 parent d9a1a7d commit f97e3a1
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1275,9 +1275,10 @@ export class ComponentDecoratorHandler implements
if (importDecl !== null && this.deferredSymbolTracker.canDefer(importDecl)) {
deferBlockDep.isDeferrable = true;
deferBlockDep.importPath = (importDecl.moduleSpecifier as ts.StringLiteral).text;
deferBlockDep.isDefaultImport = isDefaultImport(importDecl);
deferrableTypes.set(deferBlockDep.symbolName, {
importPath: deferBlockDep.importPath,
isDefaultImport: isDefaultImport(importDecl),
isDefaultImport: deferBlockDep.isDefaultImport,
});
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,22 @@
}
]
},
{
"description": "should generate a deferred block with default imports",
"inputFiles": ["defer_default_deps.ts", "defer_default_deps_ext.ts"],
"compilationModeFilter": ["full compile"],
"expectations": [
{
"files": [
{
"expected": "defer_default_deps_template.js",
"generated": "defer_default_deps.js"
}
],
"failureMessage": "Incorrect template"
}
]
},
{
"description": "should generate a lazy deferred block with empty and placeholder",
"inputFiles": ["lazy_with_blocks.ts"],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import {Component} from '@angular/core';

import CmpA from './defer_default_deps_ext';

@Component({
selector: 'local-dep',
standalone: true,
template: 'Local dependency',
})
export class LocalDep {
}

@Component({
selector: 'test-cmp',
standalone: true,
imports: [CmpA, LocalDep],
template: `
@defer {
<cmp-a />
<local-dep />
}
`,
})
export class TestCmp {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import {Component} from '@angular/core';

@Component({standalone: true, selector: 'cmp-a', template: 'CmpA!'})
export default class CmpA {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
const $TestCmp_Defer_1_DepsFn$ = () => [import("./defer_default_deps_ext").then(m => m.default), LocalDep];

function TestCmp_Defer_0_Template(rf, ctx) {
if (rf & 1) {
i0.ɵɵelement(0, "cmp-a")(1, "local-dep");
}
}

export class LocalDep {
}


function TestCmp_Template(rf, ctx) { if (rf & 1) {
i0.ɵɵtemplate(0, TestCmp_Defer_0_Template, 2, 0);
i0.ɵɵdefer(1, 0, $TestCmp_Defer_1_DepsFn$);
i0.ɵɵdeferOnIdle();
} }
7 changes: 6 additions & 1 deletion packages/compiler-cli/test/ngtsc/ngtsc_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9602,7 +9602,12 @@ function allTests(os: string) {
const jsContents = env.getContents('test.js');

expect(jsContents).toContain('ɵɵdefer(1, 0, TestCmp_Defer_1_DepsFn)');
expect(jsContents).toContain('() => [import("./cmp-a").then(m => m.default)]');
expect(jsContents)
.toContain(
'const TestCmp_Defer_1_DepsFn = () => [import("./cmp-a").then(m => m.default), LocalDep];');
expect(jsContents)
.toContain(
'i0.ɵsetClassMetadataAsync(TestCmp, () => [import("./cmp-a").then(m => m.default)]');

// The `CmpA` symbol wasn't referenced elsewhere, so it can be defer-loaded
// via dynamic imports and an original import can be removed.
Expand Down

0 comments on commit f97e3a1

Please sign in to comment.