@angular/core 20.0.0-next.8 → 20.0.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/{api.d-KjtSQajV.d.ts → api.d-CRxC7NlU.d.ts} +28 -43
- package/{chrome_dev_tools_performance.d-qv7drdAl.d.ts → chrome_dev_tools_performance.d-B0FzTuRf.d.ts} +7 -1
- package/{discovery.d-vJaEafe4.d.ts → discovery.d-CBxzK1ay.d.ts} +30 -6
- package/event_dispatcher.d-DlbccpYq.d.ts +1 -1
- package/fesm2022/attribute-BWp59EjE.mjs +1 -1
- package/fesm2022/core.mjs +80 -166
- package/fesm2022/core.mjs.map +1 -1
- package/fesm2022/{debug_node-DEfPCixm.mjs → debug_node-3mmnD06K.mjs} +138 -54
- package/fesm2022/debug_node-3mmnD06K.mjs.map +1 -0
- package/fesm2022/primitives/di.mjs +1 -1
- package/fesm2022/primitives/event-dispatch.mjs +2 -2
- package/fesm2022/primitives/event-dispatch.mjs.map +1 -1
- package/fesm2022/primitives/signals.mjs +7 -5
- package/fesm2022/primitives/signals.mjs.map +1 -1
- package/fesm2022/{resource-DhKtse7l.mjs → resource-nrAenwIA.mjs} +31 -76
- package/fesm2022/resource-nrAenwIA.mjs.map +1 -0
- package/fesm2022/{root_effect_scheduler-BZMWiScf.mjs → root_effect_scheduler-B_EWGyLU.mjs} +20 -12
- package/fesm2022/root_effect_scheduler-B_EWGyLU.mjs.map +1 -0
- package/fesm2022/rxjs-interop.mjs +16 -11
- package/fesm2022/rxjs-interop.mjs.map +1 -1
- package/fesm2022/{signal-B6pMq7KS.mjs → signal-ePSl6jXn.mjs} +14 -4
- package/fesm2022/{signal-B6pMq7KS.mjs.map → signal-ePSl6jXn.mjs.map} +1 -1
- package/fesm2022/testing.mjs +61 -63
- package/fesm2022/testing.mjs.map +1 -1
- package/fesm2022/{untracked-Bz5WMeU1.mjs → untracked-2ouAFbCz.mjs} +4 -4
- package/fesm2022/untracked-2ouAFbCz.mjs.map +1 -0
- package/fesm2022/weak_ref-BaIq-pgY.mjs +1 -1
- package/graph.d-BcIOep_B.d.ts +1 -1
- package/index.d.ts +154 -136
- package/package.json +3 -3
- package/primitives/di/index.d.ts +1 -1
- package/primitives/event-dispatch/index.d.ts +1 -1
- package/primitives/signals/index.d.ts +3 -3
- package/rxjs-interop/index.d.ts +11 -11
- package/schematics/bundles/{apply_import_manager-CaG-_cEq.js → apply_import_manager-Coc7Hewu.js} +3 -3
- package/schematics/bundles/{change_tracker-ISzWfEHN.js → change_tracker-CDJPOAni.js} +3 -3
- package/schematics/bundles/{checker-DV96LHWz.js → checker-BAl7CJ0l.js} +386 -122
- package/schematics/bundles/cleanup-unused-imports.js +6 -6
- package/schematics/bundles/{compiler-BEZ6sUQS.js → compiler-BSv6JWRF.js} +58 -65
- package/schematics/bundles/compiler_host-CAfDJO3W.js +1 -1
- package/schematics/bundles/control-flow-migration.js +2 -2
- package/schematics/bundles/document-core.js +6 -6
- package/schematics/bundles/imports-CIX-JgAN.js +1 -1
- package/schematics/bundles/{index-6wv04ZFQ.js → index-CnKffIJ6.js} +6 -5
- package/schematics/bundles/{index-B1R5GL-k.js → index-CxuDmkeg.js} +421 -317
- package/schematics/bundles/inject-flags.js +6 -6
- package/schematics/bundles/inject-migration.js +4 -4
- package/schematics/bundles/leading_space-D9nQ8UQC.js +1 -1
- package/schematics/bundles/{migrate_ts_type_references-Dh9TZgTr.js → migrate_ts_type_references-DE1AlxIs.js} +6 -6
- package/schematics/bundles/ng_decorators-DznZ5jMl.js +1 -1
- package/schematics/bundles/nodes-B16H9JUd.js +1 -1
- package/schematics/bundles/output-migration.js +7 -7
- package/schematics/bundles/{project_paths-B-Nevd-p.js → project_paths-Bl-H7Vlb.js} +4 -4
- package/schematics/bundles/project_tsconfig_paths-CDVxT6Ov.js +1 -1
- package/schematics/bundles/property_name-BBwFuqMe.js +1 -1
- package/schematics/bundles/route-lazy-loading.js +4 -4
- package/schematics/bundles/self-closing-tags-migration.js +5 -5
- package/schematics/bundles/signal-input-migration.js +8 -8
- package/schematics/bundles/signal-queries-migration.js +8 -8
- package/schematics/bundles/signals.js +8 -8
- package/schematics/bundles/standalone-migration.js +5 -5
- package/schematics/bundles/symbol-VPWguRxr.js +1 -1
- package/schematics/bundles/test-bed-get.js +5 -5
- package/{signal.d-E0e5nW1p.d.ts → signal.d-D6VJ67xi.d.ts} +8 -2
- package/testing/index.d.ts +12 -24
- package/weak_ref.d-eGOEP9S1.d.ts +1 -1
- package/fesm2022/debug_node-DEfPCixm.mjs.map +0 -1
- package/fesm2022/resource-DhKtse7l.mjs.map +0 -1
- package/fesm2022/root_effect_scheduler-BZMWiScf.mjs.map +0 -1
- package/fesm2022/untracked-Bz5WMeU1.mjs.map +0 -1
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
/**
|
|
3
|
-
* @license Angular v20.0.0-
|
|
3
|
+
* @license Angular v20.0.0-rc.0
|
|
4
4
|
* (c) 2010-2025 Google LLC. https://angular.io/
|
|
5
5
|
* License: MIT
|
|
6
6
|
*/
|
|
7
7
|
'use strict';
|
|
8
8
|
|
|
9
|
-
var compiler = require('./compiler-
|
|
9
|
+
var compiler = require('./compiler-BSv6JWRF.js');
|
|
10
10
|
var ts = require('typescript');
|
|
11
11
|
var p = require('path');
|
|
12
|
-
var checker = require('./checker-
|
|
12
|
+
var checker = require('./checker-BAl7CJ0l.js');
|
|
13
13
|
require('os');
|
|
14
14
|
|
|
15
15
|
function _interopNamespaceDefault(e) {
|
|
@@ -892,7 +892,7 @@ const MINIMUM_PARTIAL_LINKER_DEFER_SUPPORT_VERSION = '18.0.0';
|
|
|
892
892
|
function compileDeclareClassMetadata(metadata) {
|
|
893
893
|
const definitionMap = new compiler.DefinitionMap();
|
|
894
894
|
definitionMap.set('minVersion', compiler.literal(MINIMUM_PARTIAL_LINKER_VERSION$5));
|
|
895
|
-
definitionMap.set('version', compiler.literal('20.0.0-
|
|
895
|
+
definitionMap.set('version', compiler.literal('20.0.0-rc.0'));
|
|
896
896
|
definitionMap.set('ngImport', compiler.importExpr(compiler.Identifiers.core));
|
|
897
897
|
definitionMap.set('type', metadata.type);
|
|
898
898
|
definitionMap.set('decorators', metadata.decorators);
|
|
@@ -910,7 +910,7 @@ function compileComponentDeclareClassMetadata(metadata, dependencies) {
|
|
|
910
910
|
callbackReturnDefinitionMap.set('ctorParameters', metadata.ctorParameters ?? compiler.literal(null));
|
|
911
911
|
callbackReturnDefinitionMap.set('propDecorators', metadata.propDecorators ?? compiler.literal(null));
|
|
912
912
|
definitionMap.set('minVersion', compiler.literal(MINIMUM_PARTIAL_LINKER_DEFER_SUPPORT_VERSION));
|
|
913
|
-
definitionMap.set('version', compiler.literal('20.0.0-
|
|
913
|
+
definitionMap.set('version', compiler.literal('20.0.0-rc.0'));
|
|
914
914
|
definitionMap.set('ngImport', compiler.importExpr(compiler.Identifiers.core));
|
|
915
915
|
definitionMap.set('type', metadata.type);
|
|
916
916
|
definitionMap.set('resolveDeferredDeps', compileComponentMetadataAsyncResolver(dependencies));
|
|
@@ -1005,7 +1005,7 @@ function createDirectiveDefinitionMap(meta) {
|
|
|
1005
1005
|
const definitionMap = new compiler.DefinitionMap();
|
|
1006
1006
|
const minVersion = getMinimumVersionForPartialOutput(meta);
|
|
1007
1007
|
definitionMap.set('minVersion', compiler.literal(minVersion));
|
|
1008
|
-
definitionMap.set('version', compiler.literal('20.0.0-
|
|
1008
|
+
definitionMap.set('version', compiler.literal('20.0.0-rc.0'));
|
|
1009
1009
|
// e.g. `type: MyDirective`
|
|
1010
1010
|
definitionMap.set('type', meta.type.value);
|
|
1011
1011
|
if (meta.isStandalone !== undefined) {
|
|
@@ -1421,7 +1421,7 @@ const MINIMUM_PARTIAL_LINKER_VERSION$4 = '12.0.0';
|
|
|
1421
1421
|
function compileDeclareFactoryFunction(meta) {
|
|
1422
1422
|
const definitionMap = new compiler.DefinitionMap();
|
|
1423
1423
|
definitionMap.set('minVersion', compiler.literal(MINIMUM_PARTIAL_LINKER_VERSION$4));
|
|
1424
|
-
definitionMap.set('version', compiler.literal('20.0.0-
|
|
1424
|
+
definitionMap.set('version', compiler.literal('20.0.0-rc.0'));
|
|
1425
1425
|
definitionMap.set('ngImport', compiler.importExpr(compiler.Identifiers.core));
|
|
1426
1426
|
definitionMap.set('type', meta.type.value);
|
|
1427
1427
|
definitionMap.set('deps', compileDependencies(meta.deps));
|
|
@@ -1456,7 +1456,7 @@ function compileDeclareInjectableFromMetadata(meta) {
|
|
|
1456
1456
|
function createInjectableDefinitionMap(meta) {
|
|
1457
1457
|
const definitionMap = new compiler.DefinitionMap();
|
|
1458
1458
|
definitionMap.set('minVersion', compiler.literal(MINIMUM_PARTIAL_LINKER_VERSION$3));
|
|
1459
|
-
definitionMap.set('version', compiler.literal('20.0.0-
|
|
1459
|
+
definitionMap.set('version', compiler.literal('20.0.0-rc.0'));
|
|
1460
1460
|
definitionMap.set('ngImport', compiler.importExpr(compiler.Identifiers.core));
|
|
1461
1461
|
definitionMap.set('type', meta.type.value);
|
|
1462
1462
|
// Only generate providedIn property if it has a non-null value
|
|
@@ -1507,7 +1507,7 @@ function compileDeclareInjectorFromMetadata(meta) {
|
|
|
1507
1507
|
function createInjectorDefinitionMap(meta) {
|
|
1508
1508
|
const definitionMap = new compiler.DefinitionMap();
|
|
1509
1509
|
definitionMap.set('minVersion', compiler.literal(MINIMUM_PARTIAL_LINKER_VERSION$2));
|
|
1510
|
-
definitionMap.set('version', compiler.literal('20.0.0-
|
|
1510
|
+
definitionMap.set('version', compiler.literal('20.0.0-rc.0'));
|
|
1511
1511
|
definitionMap.set('ngImport', compiler.importExpr(compiler.Identifiers.core));
|
|
1512
1512
|
definitionMap.set('type', meta.type.value);
|
|
1513
1513
|
definitionMap.set('providers', meta.providers);
|
|
@@ -1540,7 +1540,7 @@ function createNgModuleDefinitionMap(meta) {
|
|
|
1540
1540
|
throw new Error('Invalid path! Local compilation mode should not get into the partial compilation path');
|
|
1541
1541
|
}
|
|
1542
1542
|
definitionMap.set('minVersion', compiler.literal(MINIMUM_PARTIAL_LINKER_VERSION$1));
|
|
1543
|
-
definitionMap.set('version', compiler.literal('20.0.0-
|
|
1543
|
+
definitionMap.set('version', compiler.literal('20.0.0-rc.0'));
|
|
1544
1544
|
definitionMap.set('ngImport', compiler.importExpr(compiler.Identifiers.core));
|
|
1545
1545
|
definitionMap.set('type', meta.type.value);
|
|
1546
1546
|
// We only generate the keys in the metadata if the arrays contain values.
|
|
@@ -1591,7 +1591,7 @@ function compileDeclarePipeFromMetadata(meta) {
|
|
|
1591
1591
|
function createPipeDefinitionMap(meta) {
|
|
1592
1592
|
const definitionMap = new compiler.DefinitionMap();
|
|
1593
1593
|
definitionMap.set('minVersion', compiler.literal(MINIMUM_PARTIAL_LINKER_VERSION));
|
|
1594
|
-
definitionMap.set('version', compiler.literal('20.0.0-
|
|
1594
|
+
definitionMap.set('version', compiler.literal('20.0.0-rc.0'));
|
|
1595
1595
|
definitionMap.set('ngImport', compiler.importExpr(compiler.Identifiers.core));
|
|
1596
1596
|
// e.g. `type: MyPipe`
|
|
1597
1597
|
definitionMap.set('type', meta.type.value);
|
|
@@ -7917,6 +7917,7 @@ function parseExtractedTemplate(template, sourceStr, sourceParseRange, escapedSt
|
|
|
7917
7917
|
escapedString,
|
|
7918
7918
|
enableBlockSyntax: options.enableBlockSyntax,
|
|
7919
7919
|
enableLetSyntax: options.enableLetSyntax,
|
|
7920
|
+
enableSelectorless: options.enableSelectorless,
|
|
7920
7921
|
};
|
|
7921
7922
|
const parsedTemplate = compiler.parseTemplate(sourceStr, sourceMapUrl ?? '', {
|
|
7922
7923
|
...commonParseOptions,
|
|
@@ -8880,7 +8881,8 @@ class ComponentDecoratorHandler {
|
|
|
8880
8881
|
enableHmr;
|
|
8881
8882
|
implicitStandaloneValue;
|
|
8882
8883
|
typeCheckHostBindings;
|
|
8883
|
-
|
|
8884
|
+
enableSelectorless;
|
|
8885
|
+
constructor(reflector, evaluator, metaRegistry, metaReader, scopeReader, compilerHost, scopeRegistry, typeCheckScopeRegistry, resourceRegistry, isCore, strictCtorDeps, resourceLoader, rootDirs, defaultPreserveWhitespaces, i18nUseExternalIds, enableI18nLegacyMessageIdFormat, usePoisonedData, i18nNormalizeLineEndingsInICUs, moduleResolver, cycleAnalyzer, cycleHandlingStrategy, refEmitter, referencesRegistry, depTracker, injectableRegistry, semanticDepGraphUpdater, annotateForClosureCompiler, perf, hostDirectivesResolver, importTracker, includeClassMetadata, compilationMode, deferredSymbolTracker, forbidOrphanRendering, enableBlockSyntax, enableLetSyntax, externalRuntimeStyles, localCompilationExtraImportsTracker, jitDeclarationRegistry, i18nPreserveSignificantWhitespace, strictStandalone, enableHmr, implicitStandaloneValue, typeCheckHostBindings, enableSelectorless) {
|
|
8884
8886
|
this.reflector = reflector;
|
|
8885
8887
|
this.evaluator = evaluator;
|
|
8886
8888
|
this.metaRegistry = metaRegistry;
|
|
@@ -8925,12 +8927,14 @@ class ComponentDecoratorHandler {
|
|
|
8925
8927
|
this.enableHmr = enableHmr;
|
|
8926
8928
|
this.implicitStandaloneValue = implicitStandaloneValue;
|
|
8927
8929
|
this.typeCheckHostBindings = typeCheckHostBindings;
|
|
8930
|
+
this.enableSelectorless = enableSelectorless;
|
|
8928
8931
|
this.extractTemplateOptions = {
|
|
8929
8932
|
enableI18nLegacyMessageIdFormat: this.enableI18nLegacyMessageIdFormat,
|
|
8930
8933
|
i18nNormalizeLineEndingsInICUs: this.i18nNormalizeLineEndingsInICUs,
|
|
8931
8934
|
usePoisonedData: this.usePoisonedData,
|
|
8932
8935
|
enableBlockSyntax: this.enableBlockSyntax,
|
|
8933
8936
|
enableLetSyntax: this.enableLetSyntax,
|
|
8937
|
+
enableSelectorless: this.enableSelectorless,
|
|
8934
8938
|
preserveSignificantWhitespace: this.i18nPreserveSignificantWhitespace,
|
|
8935
8939
|
};
|
|
8936
8940
|
// Dependencies can't be deferred during HMR, because the HMR update module can't have
|
|
@@ -9199,6 +9203,7 @@ class ComponentDecoratorHandler {
|
|
|
9199
9203
|
usePoisonedData: this.usePoisonedData,
|
|
9200
9204
|
enableBlockSyntax: this.enableBlockSyntax,
|
|
9201
9205
|
enableLetSyntax: this.enableLetSyntax,
|
|
9206
|
+
enableSelectorless: this.enableSelectorless,
|
|
9202
9207
|
preserveSignificantWhitespace: this.i18nPreserveSignificantWhitespace,
|
|
9203
9208
|
}, this.compilationMode);
|
|
9204
9209
|
if (this.compilationMode === checker.CompilationMode.LOCAL &&
|
|
@@ -9580,168 +9585,16 @@ class ComponentDecoratorHandler {
|
|
|
9580
9585
|
return {};
|
|
9581
9586
|
}
|
|
9582
9587
|
const scope = this.scopeReader.getScopeForComponent(node);
|
|
9583
|
-
if (scope
|
|
9584
|
-
//
|
|
9585
|
-
//
|
|
9586
|
-
|
|
9587
|
-
|
|
9588
|
-
|
|
9589
|
-
|
|
9590
|
-
|
|
9591
|
-
// module file sets the directives/pipes on the ɵcmp of the component, without
|
|
9592
|
-
// requiring new imports (but also in a way that breaks tree shaking).
|
|
9593
|
-
//
|
|
9594
|
-
// Determining this is challenging, because the TemplateDefinitionBuilder is responsible for
|
|
9595
|
-
// matching directives and pipes in the template; however, that doesn't run until the actual
|
|
9596
|
-
// compile() step. It's not possible to run template compilation sooner as it requires the
|
|
9597
|
-
// ConstantPool for the overall file being compiled (which isn't available until the
|
|
9598
|
-
// transform step).
|
|
9599
|
-
//
|
|
9600
|
-
// Instead, directives/pipes are matched independently here, using the R3TargetBinder. This
|
|
9601
|
-
// is an alternative implementation of template matching which is used for template
|
|
9602
|
-
// type-checking and will eventually replace matching in the TemplateDefinitionBuilder.
|
|
9603
|
-
const isModuleScope = scope.kind === checker.ComponentScopeKind.NgModule;
|
|
9604
|
-
// Dependencies coming from the regular `imports` field.
|
|
9605
|
-
const dependencies = isModuleScope ? scope.compilation.dependencies : scope.dependencies;
|
|
9606
|
-
// Dependencies from the `@Component.deferredImports` field.
|
|
9607
|
-
const explicitlyDeferredDependencies = getExplicitlyDeferredDeps(scope);
|
|
9608
|
-
// Mark the component is an NgModule-based component with its NgModule in a different file
|
|
9609
|
-
// then mark this file for extra import generation
|
|
9610
|
-
if (isModuleScope && context.fileName !== checker.getSourceFile(scope.ngModule).fileName) {
|
|
9611
|
-
this.localCompilationExtraImportsTracker?.markFileForExtraImportGeneration(context);
|
|
9612
|
-
}
|
|
9613
|
-
// Make sure that `@Component.imports` and `@Component.deferredImports` do not have
|
|
9614
|
-
// the same dependencies.
|
|
9615
|
-
if (metadata.isStandalone &&
|
|
9616
|
-
analysis.rawDeferredImports !== null &&
|
|
9617
|
-
explicitlyDeferredDependencies.length > 0) {
|
|
9618
|
-
const diagnostic = validateNoImportOverlap(dependencies, explicitlyDeferredDependencies, analysis.rawDeferredImports);
|
|
9619
|
-
if (diagnostic !== null) {
|
|
9620
|
-
diagnostics.push(diagnostic);
|
|
9621
|
-
}
|
|
9622
|
-
}
|
|
9623
|
-
// Set up the R3TargetBinder.
|
|
9624
|
-
const binder = createTargetBinder(dependencies);
|
|
9625
|
-
let allDependencies = dependencies;
|
|
9626
|
-
let deferBlockBinder = binder;
|
|
9627
|
-
// If there are any explicitly deferred dependencies (via `@Component.deferredImports`),
|
|
9628
|
-
// re-compute the list of dependencies and create a new binder for defer blocks. This
|
|
9629
|
-
// is because we have deferred dependencies that are not in the standard imports list
|
|
9630
|
-
// and need to be referenced later when determining what dependencies need to be in a
|
|
9631
|
-
// defer function / instruction call. Otherwise they end up treated as a standard
|
|
9632
|
-
// import, which is wrong.
|
|
9633
|
-
if (explicitlyDeferredDependencies.length > 0) {
|
|
9634
|
-
allDependencies = [...explicitlyDeferredDependencies, ...dependencies];
|
|
9635
|
-
deferBlockBinder = createTargetBinder(allDependencies);
|
|
9636
|
-
}
|
|
9637
|
-
// Set up the pipes map that is later used to determine which dependencies are used in
|
|
9638
|
-
// the template.
|
|
9639
|
-
const pipes = extractPipes(allDependencies);
|
|
9640
|
-
// Next, the component template AST is bound using the R3TargetBinder. This produces a
|
|
9641
|
-
// BoundTarget, which is similar to a ts.TypeChecker.
|
|
9642
|
-
const bound = binder.bind({ template: metadata.template.nodes });
|
|
9643
|
-
// Find all defer blocks used in the template and for each block
|
|
9644
|
-
// bind its own scope.
|
|
9645
|
-
const deferBlocks = new Map();
|
|
9646
|
-
for (const deferBlock of bound.getDeferBlocks()) {
|
|
9647
|
-
deferBlocks.set(deferBlock, deferBlockBinder.bind({ template: deferBlock.children }));
|
|
9648
|
-
}
|
|
9649
|
-
// Register all Directives and Pipes used at the top level (outside
|
|
9650
|
-
// of any defer blocks), which would be eagerly referenced.
|
|
9651
|
-
const eagerlyUsed = new Set();
|
|
9652
|
-
if (this.enableHmr) {
|
|
9653
|
-
// In HMR we need to preserve all the dependencies, because they have to remain consistent
|
|
9654
|
-
// with the initially-generated code no matter what the template looks like.
|
|
9655
|
-
for (const dep of dependencies) {
|
|
9656
|
-
if (dep.ref.node !== node) {
|
|
9657
|
-
eagerlyUsed.add(dep.ref.node);
|
|
9658
|
-
}
|
|
9659
|
-
else {
|
|
9660
|
-
const used = bound.getEagerlyUsedDirectives();
|
|
9661
|
-
if (used.some((current) => current.ref.node === node)) {
|
|
9662
|
-
eagerlyUsed.add(node);
|
|
9663
|
-
}
|
|
9664
|
-
}
|
|
9665
|
-
}
|
|
9666
|
-
}
|
|
9667
|
-
else {
|
|
9668
|
-
for (const dir of bound.getEagerlyUsedDirectives()) {
|
|
9669
|
-
eagerlyUsed.add(dir.ref.node);
|
|
9670
|
-
}
|
|
9671
|
-
for (const name of bound.getEagerlyUsedPipes()) {
|
|
9672
|
-
if (!pipes.has(name)) {
|
|
9673
|
-
continue;
|
|
9674
|
-
}
|
|
9675
|
-
eagerlyUsed.add(pipes.get(name).ref.node);
|
|
9676
|
-
}
|
|
9677
|
-
}
|
|
9678
|
-
// Set of Directives and Pipes used across the entire template,
|
|
9679
|
-
// including all defer blocks.
|
|
9680
|
-
const wholeTemplateUsed = new Set(eagerlyUsed);
|
|
9681
|
-
for (const bound of deferBlocks.values()) {
|
|
9682
|
-
for (const dir of bound.getUsedDirectives()) {
|
|
9683
|
-
wholeTemplateUsed.add(dir.ref.node);
|
|
9684
|
-
}
|
|
9685
|
-
for (const name of bound.getUsedPipes()) {
|
|
9686
|
-
if (!pipes.has(name)) {
|
|
9687
|
-
continue;
|
|
9688
|
-
}
|
|
9689
|
-
wholeTemplateUsed.add(pipes.get(name).ref.node);
|
|
9690
|
-
}
|
|
9691
|
-
}
|
|
9692
|
-
const declarations = new Map();
|
|
9693
|
-
// Transform the dependencies list, filtering out unused dependencies.
|
|
9694
|
-
for (const dep of allDependencies) {
|
|
9695
|
-
// Only emit references to each dependency once.
|
|
9696
|
-
if (declarations.has(dep.ref.node)) {
|
|
9697
|
-
continue;
|
|
9698
|
-
}
|
|
9699
|
-
switch (dep.kind) {
|
|
9700
|
-
case checker.MetaKind.Directive:
|
|
9701
|
-
if (!wholeTemplateUsed.has(dep.ref.node) || dep.matchSource !== checker.MatchSource.Selector) {
|
|
9702
|
-
continue;
|
|
9703
|
-
}
|
|
9704
|
-
const dirType = this.refEmitter.emit(dep.ref, context);
|
|
9705
|
-
checker.assertSuccessfulReferenceEmit(dirType, node.name, dep.isComponent ? 'component' : 'directive');
|
|
9706
|
-
declarations.set(dep.ref.node, {
|
|
9707
|
-
kind: compiler.R3TemplateDependencyKind.Directive,
|
|
9708
|
-
ref: dep.ref,
|
|
9709
|
-
type: dirType.expression,
|
|
9710
|
-
importedFile: dirType.importedFile,
|
|
9711
|
-
selector: dep.selector,
|
|
9712
|
-
inputs: dep.inputs.propertyNames,
|
|
9713
|
-
outputs: dep.outputs.propertyNames,
|
|
9714
|
-
exportAs: dep.exportAs,
|
|
9715
|
-
isComponent: dep.isComponent,
|
|
9716
|
-
});
|
|
9717
|
-
break;
|
|
9718
|
-
case checker.MetaKind.Pipe:
|
|
9719
|
-
if (!wholeTemplateUsed.has(dep.ref.node)) {
|
|
9720
|
-
continue;
|
|
9721
|
-
}
|
|
9722
|
-
const pipeType = this.refEmitter.emit(dep.ref, context);
|
|
9723
|
-
checker.assertSuccessfulReferenceEmit(pipeType, node.name, 'pipe');
|
|
9724
|
-
declarations.set(dep.ref.node, {
|
|
9725
|
-
kind: compiler.R3TemplateDependencyKind.Pipe,
|
|
9726
|
-
type: pipeType.expression,
|
|
9727
|
-
name: dep.name,
|
|
9728
|
-
ref: dep.ref,
|
|
9729
|
-
importedFile: pipeType.importedFile,
|
|
9730
|
-
});
|
|
9731
|
-
break;
|
|
9732
|
-
case checker.MetaKind.NgModule:
|
|
9733
|
-
const ngModuleType = this.refEmitter.emit(dep.ref, context);
|
|
9734
|
-
checker.assertSuccessfulReferenceEmit(ngModuleType, node.name, 'NgModule');
|
|
9735
|
-
declarations.set(dep.ref.node, {
|
|
9736
|
-
kind: compiler.R3TemplateDependencyKind.NgModule,
|
|
9737
|
-
type: ngModuleType.expression,
|
|
9738
|
-
importedFile: ngModuleType.importedFile,
|
|
9739
|
-
});
|
|
9740
|
-
break;
|
|
9741
|
-
}
|
|
9742
|
-
}
|
|
9743
|
-
const getSemanticReference = (decl) => this.semanticDepGraphUpdater.getSemanticReference(decl.ref.node, decl.type);
|
|
9588
|
+
if (scope === null) {
|
|
9589
|
+
// If there is no scope, we can still use the binder to retrieve *some* information about the
|
|
9590
|
+
// deferred blocks.
|
|
9591
|
+
data.deferPerBlockDependencies = this.locateDeferBlocksWithoutScope(metadata.template);
|
|
9592
|
+
}
|
|
9593
|
+
else {
|
|
9594
|
+
const { eagerlyUsed, deferBlocks, allDependencies, wholeTemplateUsed } = this.resolveComponentDependencies(node, context, analysis, scope, metadata, diagnostics);
|
|
9595
|
+
const declarations = this.componentDependenciesToDeclarations(node, context, allDependencies, wholeTemplateUsed);
|
|
9744
9596
|
if (this.semanticDepGraphUpdater !== null) {
|
|
9597
|
+
const getSemanticReference = (decl) => this.semanticDepGraphUpdater.getSemanticReference(decl.ref.node, decl.type);
|
|
9745
9598
|
symbol.usedDirectives = Array.from(declarations.values())
|
|
9746
9599
|
.filter(isUsedDirective)
|
|
9747
9600
|
.map(getSemanticReference);
|
|
@@ -9749,142 +9602,17 @@ class ComponentDecoratorHandler {
|
|
|
9749
9602
|
.filter(isUsedPipe)
|
|
9750
9603
|
.map(getSemanticReference);
|
|
9751
9604
|
}
|
|
9752
|
-
const eagerDeclarations = Array.from(declarations.values()).filter((decl) => decl.kind === compiler.R3TemplateDependencyKind.NgModule || eagerlyUsed.has(decl.ref.node));
|
|
9753
9605
|
// Process information related to defer blocks
|
|
9754
9606
|
if (this.compilationMode !== checker.CompilationMode.LOCAL) {
|
|
9755
9607
|
this.resolveDeferBlocks(node, deferBlocks, declarations, data, analysis, eagerlyUsed);
|
|
9756
9608
|
}
|
|
9757
|
-
|
|
9758
|
-
const cyclesFromPipes = new Map();
|
|
9759
|
-
// Scan through the directives/pipes actually used in the template and check whether any
|
|
9760
|
-
// import which needs to be generated would create a cycle. This check is skipped for
|
|
9761
|
-
// standalone components as the dependencies of a standalone component have already been
|
|
9762
|
-
// imported directly by the user, so Angular won't introduce any imports that aren't already
|
|
9763
|
-
// in the user's program.
|
|
9764
|
-
if (!metadata.isStandalone) {
|
|
9765
|
-
for (const usedDep of eagerDeclarations) {
|
|
9766
|
-
const cycle = this._checkForCyclicImport(usedDep.importedFile, usedDep.type, context);
|
|
9767
|
-
if (cycle !== null) {
|
|
9768
|
-
switch (usedDep.kind) {
|
|
9769
|
-
case compiler.R3TemplateDependencyKind.Directive:
|
|
9770
|
-
cyclesFromDirectives.set(usedDep, cycle);
|
|
9771
|
-
break;
|
|
9772
|
-
case compiler.R3TemplateDependencyKind.Pipe:
|
|
9773
|
-
cyclesFromPipes.set(usedDep, cycle);
|
|
9774
|
-
break;
|
|
9775
|
-
}
|
|
9776
|
-
}
|
|
9777
|
-
}
|
|
9778
|
-
}
|
|
9779
|
-
// Check whether any usages of standalone components in imports requires the dependencies
|
|
9780
|
-
// array to be wrapped in a closure. This check is technically a heuristic as there's no
|
|
9781
|
-
// direct way to check whether a `Reference` came from a `forwardRef`. Instead, we check if
|
|
9782
|
-
// the reference is `synthetic`, implying it came from _any_ foreign function resolver,
|
|
9783
|
-
// including the `forwardRef` resolver.
|
|
9784
|
-
const standaloneImportMayBeForwardDeclared = analysis.resolvedImports !== null && analysis.resolvedImports.some((ref) => ref.synthetic);
|
|
9785
|
-
const cycleDetected = cyclesFromDirectives.size !== 0 || cyclesFromPipes.size !== 0;
|
|
9786
|
-
if (!cycleDetected) {
|
|
9787
|
-
// No cycle was detected. Record the imports that need to be created in the cycle detector
|
|
9788
|
-
// so that future cyclic import checks consider their production.
|
|
9789
|
-
for (const { type, importedFile } of eagerDeclarations) {
|
|
9790
|
-
this.maybeRecordSyntheticImport(importedFile, type, context);
|
|
9791
|
-
}
|
|
9792
|
-
// Check whether the dependencies arrays in ɵcmp need to be wrapped in a closure.
|
|
9793
|
-
// This is required if any dependency reference is to a declaration in the same file
|
|
9794
|
-
// but declared after this component.
|
|
9795
|
-
const declarationIsForwardDeclared = eagerDeclarations.some((decl) => checker.isExpressionForwardReference(decl.type, node.name, context));
|
|
9796
|
-
if (this.compilationMode !== checker.CompilationMode.LOCAL &&
|
|
9797
|
-
(declarationIsForwardDeclared || standaloneImportMayBeForwardDeclared)) {
|
|
9798
|
-
data.declarationListEmitMode = 1 /* DeclarationListEmitMode.Closure */;
|
|
9799
|
-
}
|
|
9800
|
-
data.declarations = eagerDeclarations;
|
|
9801
|
-
// Register extra local imports.
|
|
9802
|
-
if (this.compilationMode === checker.CompilationMode.LOCAL &&
|
|
9803
|
-
this.localCompilationExtraImportsTracker !== null) {
|
|
9804
|
-
// In global compilation mode `eagerDeclarations` contains "all" the component
|
|
9805
|
-
// dependencies, whose import statements will be added to the file. In local compilation
|
|
9806
|
-
// mode `eagerDeclarations` only includes the "local" dependencies, meaning those that are
|
|
9807
|
-
// declared inside this compilation unit.Here the import info of these local dependencies
|
|
9808
|
-
// are added to the tracker so that we can generate extra imports representing these local
|
|
9809
|
-
// dependencies. For non-local dependencies we use another technique of adding some
|
|
9810
|
-
// best-guess extra imports globally to all files using
|
|
9811
|
-
// `localCompilationExtraImportsTracker.addGlobalImportFromIdentifier`.
|
|
9812
|
-
for (const { type } of eagerDeclarations) {
|
|
9813
|
-
if (type instanceof compiler.ExternalExpr && type.value.moduleName) {
|
|
9814
|
-
this.localCompilationExtraImportsTracker.addImportForFile(context, type.value.moduleName);
|
|
9815
|
-
}
|
|
9816
|
-
}
|
|
9817
|
-
}
|
|
9818
|
-
}
|
|
9819
|
-
else {
|
|
9820
|
-
if (this.cycleHandlingStrategy === 0 /* CycleHandlingStrategy.UseRemoteScoping */) {
|
|
9821
|
-
// Declaring the directiveDefs/pipeDefs arrays directly would require imports that would
|
|
9822
|
-
// create a cycle. Instead, mark this component as requiring remote scoping, so that the
|
|
9823
|
-
// NgModule file will take care of setting the directives for the component.
|
|
9824
|
-
this.scopeRegistry.setComponentRemoteScope(node, eagerDeclarations.filter(isUsedDirective).map((dir) => dir.ref), eagerDeclarations.filter(isUsedPipe).map((pipe) => pipe.ref));
|
|
9825
|
-
symbol.isRemotelyScoped = true;
|
|
9826
|
-
// If a semantic graph is being tracked, record the fact that this component is remotely
|
|
9827
|
-
// scoped with the declaring NgModule symbol as the NgModule's emit becomes dependent on
|
|
9828
|
-
// the directive/pipe usages of this component.
|
|
9829
|
-
if (this.semanticDepGraphUpdater !== null &&
|
|
9830
|
-
scope.kind === checker.ComponentScopeKind.NgModule &&
|
|
9831
|
-
scope.ngModule !== null) {
|
|
9832
|
-
const moduleSymbol = this.semanticDepGraphUpdater.getSymbol(scope.ngModule);
|
|
9833
|
-
if (!(moduleSymbol instanceof NgModuleSymbol)) {
|
|
9834
|
-
throw new Error(`AssertionError: Expected ${scope.ngModule.name} to be an NgModuleSymbol.`);
|
|
9835
|
-
}
|
|
9836
|
-
moduleSymbol.addRemotelyScopedComponent(symbol, symbol.usedDirectives, symbol.usedPipes);
|
|
9837
|
-
}
|
|
9838
|
-
}
|
|
9839
|
-
else {
|
|
9840
|
-
// We are not able to handle this cycle so throw an error.
|
|
9841
|
-
const relatedMessages = [];
|
|
9842
|
-
for (const [dir, cycle] of cyclesFromDirectives) {
|
|
9843
|
-
relatedMessages.push(makeCyclicImportInfo(dir.ref, dir.isComponent ? 'component' : 'directive', cycle));
|
|
9844
|
-
}
|
|
9845
|
-
for (const [pipe, cycle] of cyclesFromPipes) {
|
|
9846
|
-
relatedMessages.push(makeCyclicImportInfo(pipe.ref, 'pipe', cycle));
|
|
9847
|
-
}
|
|
9848
|
-
throw new checker.FatalDiagnosticError(checker.ErrorCode.IMPORT_CYCLE_DETECTED, node, 'One or more import cycles would need to be created to compile this component, ' +
|
|
9849
|
-
'which is not supported by the current compiler configuration.', relatedMessages);
|
|
9850
|
-
}
|
|
9851
|
-
}
|
|
9852
|
-
}
|
|
9853
|
-
else {
|
|
9854
|
-
// If there is no scope, we can still use the binder to retrieve *some* information about the
|
|
9855
|
-
// deferred blocks.
|
|
9856
|
-
data.deferPerBlockDependencies = this.locateDeferBlocksWithoutScope(metadata.template);
|
|
9609
|
+
this.handleDependencyCycles(node, context, scope, data, analysis, metadata, declarations, eagerlyUsed, symbol);
|
|
9857
9610
|
}
|
|
9858
9611
|
// Run diagnostics only in global mode.
|
|
9859
9612
|
if (this.compilationMode !== checker.CompilationMode.LOCAL) {
|
|
9860
|
-
|
|
9861
|
-
if (
|
|
9862
|
-
|
|
9863
|
-
diagnostics.push(...importDiagnostics);
|
|
9864
|
-
}
|
|
9865
|
-
if (analysis.resolvedDeferredImports !== null && analysis.rawDeferredImports !== null) {
|
|
9866
|
-
const importDiagnostics = validateStandaloneImports(analysis.resolvedDeferredImports, analysis.rawDeferredImports, this.metaReader, this.scopeReader, true /* isDeferredImport */);
|
|
9867
|
-
diagnostics.push(...importDiagnostics);
|
|
9868
|
-
}
|
|
9869
|
-
if (analysis.providersRequiringFactory !== null &&
|
|
9870
|
-
analysis.meta.providers instanceof compiler.WrappedNodeExpr) {
|
|
9871
|
-
const providerDiagnostics = checker.getProviderDiagnostics(analysis.providersRequiringFactory, analysis.meta.providers.node, this.injectableRegistry);
|
|
9872
|
-
diagnostics.push(...providerDiagnostics);
|
|
9873
|
-
}
|
|
9874
|
-
if (analysis.viewProvidersRequiringFactory !== null &&
|
|
9875
|
-
analysis.meta.viewProviders instanceof compiler.WrappedNodeExpr) {
|
|
9876
|
-
const viewProviderDiagnostics = checker.getProviderDiagnostics(analysis.viewProvidersRequiringFactory, analysis.meta.viewProviders.node, this.injectableRegistry);
|
|
9877
|
-
diagnostics.push(...viewProviderDiagnostics);
|
|
9878
|
-
}
|
|
9879
|
-
const directiveDiagnostics = checker.getDirectiveDiagnostics(node, this.injectableRegistry, this.evaluator, this.reflector, this.scopeRegistry, this.strictCtorDeps, 'Component');
|
|
9880
|
-
if (directiveDiagnostics !== null) {
|
|
9881
|
-
diagnostics.push(...directiveDiagnostics);
|
|
9882
|
-
}
|
|
9883
|
-
const hostDirectivesDiagnostics = analysis.hostDirectives && analysis.rawHostDirectives
|
|
9884
|
-
? checker.validateHostDirectives(analysis.rawHostDirectives, analysis.hostDirectives, this.metaReader)
|
|
9885
|
-
: null;
|
|
9886
|
-
if (hostDirectivesDiagnostics !== null) {
|
|
9887
|
-
diagnostics.push(...hostDirectivesDiagnostics);
|
|
9613
|
+
const nonLocalDiagnostics = this.getNonLocalDiagnostics(node, analysis);
|
|
9614
|
+
if (nonLocalDiagnostics !== null) {
|
|
9615
|
+
diagnostics.push(...nonLocalDiagnostics);
|
|
9888
9616
|
}
|
|
9889
9617
|
}
|
|
9890
9618
|
if (diagnostics.length > 0) {
|
|
@@ -10059,13 +9787,328 @@ class ComponentDecoratorHandler {
|
|
|
10059
9787
|
? null
|
|
10060
9788
|
: getHmrUpdateDeclaration(res, pool.statements, hmrMeta, node);
|
|
10061
9789
|
}
|
|
9790
|
+
/**
|
|
9791
|
+
* Determines the dependencies of a component and
|
|
9792
|
+
* categorizes them based on how they were introduced.
|
|
9793
|
+
*/
|
|
9794
|
+
resolveComponentDependencies(node, context, analysis, scope, metadata, diagnostics) {
|
|
9795
|
+
// Replace the empty components and directives from the analyze() step with a fully expanded
|
|
9796
|
+
// scope. This is possible now because during resolve() the whole compilation unit has been
|
|
9797
|
+
// fully analyzed.
|
|
9798
|
+
//
|
|
9799
|
+
// First it needs to be determined if actually importing the directives/pipes used in the
|
|
9800
|
+
// template would create a cycle. Currently ngtsc refuses to generate cycles, so an option
|
|
9801
|
+
// known as "remote scoping" is used if a cycle would be created. In remote scoping, the
|
|
9802
|
+
// module file sets the directives/pipes on the ɵcmp of the component, without
|
|
9803
|
+
// requiring new imports (but also in a way that breaks tree shaking).
|
|
9804
|
+
//
|
|
9805
|
+
// Determining this is challenging, because the TemplateDefinitionBuilder is responsible for
|
|
9806
|
+
// matching directives and pipes in the template; however, that doesn't run until the actual
|
|
9807
|
+
// compile() step. It's not possible to run template compilation sooner as it requires the
|
|
9808
|
+
// ConstantPool for the overall file being compiled (which isn't available until the
|
|
9809
|
+
// transform step).
|
|
9810
|
+
//
|
|
9811
|
+
// Instead, directives/pipes are matched independently here, using the R3TargetBinder. This
|
|
9812
|
+
// is an alternative implementation of template matching which is used for template
|
|
9813
|
+
// type-checking and will eventually replace matching in the TemplateDefinitionBuilder.
|
|
9814
|
+
const isModuleScope = scope.kind === checker.ComponentScopeKind.NgModule;
|
|
9815
|
+
// Dependencies coming from the regular `imports` field.
|
|
9816
|
+
const dependencies = isModuleScope ? scope.compilation.dependencies : scope.dependencies;
|
|
9817
|
+
// Dependencies from the `@Component.deferredImports` field.
|
|
9818
|
+
const explicitlyDeferredDependencies = getExplicitlyDeferredDeps(scope);
|
|
9819
|
+
// Mark the component is an NgModule-based component with its NgModule in a different file
|
|
9820
|
+
// then mark this file for extra import generation
|
|
9821
|
+
if (isModuleScope && context.fileName !== checker.getSourceFile(scope.ngModule).fileName) {
|
|
9822
|
+
this.localCompilationExtraImportsTracker?.markFileForExtraImportGeneration(context);
|
|
9823
|
+
}
|
|
9824
|
+
// Make sure that `@Component.imports` and `@Component.deferredImports` do not have
|
|
9825
|
+
// the same dependencies.
|
|
9826
|
+
if (metadata.isStandalone &&
|
|
9827
|
+
analysis.rawDeferredImports !== null &&
|
|
9828
|
+
explicitlyDeferredDependencies.length > 0) {
|
|
9829
|
+
const diagnostic = validateNoImportOverlap(dependencies, explicitlyDeferredDependencies, analysis.rawDeferredImports);
|
|
9830
|
+
if (diagnostic !== null) {
|
|
9831
|
+
diagnostics.push(diagnostic);
|
|
9832
|
+
}
|
|
9833
|
+
}
|
|
9834
|
+
// Set up the R3TargetBinder.
|
|
9835
|
+
const binder = createTargetBinder(dependencies);
|
|
9836
|
+
let allDependencies = dependencies;
|
|
9837
|
+
let deferBlockBinder = binder;
|
|
9838
|
+
// If there are any explicitly deferred dependencies (via `@Component.deferredImports`),
|
|
9839
|
+
// re-compute the list of dependencies and create a new binder for defer blocks. This
|
|
9840
|
+
// is because we have deferred dependencies that are not in the standard imports list
|
|
9841
|
+
// and need to be referenced later when determining what dependencies need to be in a
|
|
9842
|
+
// defer function / instruction call. Otherwise they end up treated as a standard
|
|
9843
|
+
// import, which is wrong.
|
|
9844
|
+
if (explicitlyDeferredDependencies.length > 0) {
|
|
9845
|
+
allDependencies = [...explicitlyDeferredDependencies, ...dependencies];
|
|
9846
|
+
deferBlockBinder = createTargetBinder(allDependencies);
|
|
9847
|
+
}
|
|
9848
|
+
// Set up the pipes map that is later used to determine which dependencies are used in
|
|
9849
|
+
// the template.
|
|
9850
|
+
const pipes = extractPipes(allDependencies);
|
|
9851
|
+
// Next, the component template AST is bound using the R3TargetBinder. This produces a
|
|
9852
|
+
// BoundTarget, which is similar to a ts.TypeChecker.
|
|
9853
|
+
const bound = binder.bind({ template: metadata.template.nodes });
|
|
9854
|
+
// Find all defer blocks used in the template and for each block
|
|
9855
|
+
// bind its own scope.
|
|
9856
|
+
const deferBlocks = new Map();
|
|
9857
|
+
for (const deferBlock of bound.getDeferBlocks()) {
|
|
9858
|
+
deferBlocks.set(deferBlock, deferBlockBinder.bind({ template: deferBlock.children }));
|
|
9859
|
+
}
|
|
9860
|
+
// Register all Directives and Pipes used at the top level (outside
|
|
9861
|
+
// of any defer blocks), which would be eagerly referenced.
|
|
9862
|
+
const eagerlyUsed = new Set();
|
|
9863
|
+
if (this.enableHmr) {
|
|
9864
|
+
// In HMR we need to preserve all the dependencies, because they have to remain consistent
|
|
9865
|
+
// with the initially-generated code no matter what the template looks like.
|
|
9866
|
+
for (const dep of dependencies) {
|
|
9867
|
+
if (dep.ref.node !== node) {
|
|
9868
|
+
eagerlyUsed.add(dep.ref.node);
|
|
9869
|
+
}
|
|
9870
|
+
else {
|
|
9871
|
+
const used = bound.getEagerlyUsedDirectives();
|
|
9872
|
+
if (used.some((current) => current.ref.node === node)) {
|
|
9873
|
+
eagerlyUsed.add(node);
|
|
9874
|
+
}
|
|
9875
|
+
}
|
|
9876
|
+
}
|
|
9877
|
+
}
|
|
9878
|
+
else {
|
|
9879
|
+
for (const dir of bound.getEagerlyUsedDirectives()) {
|
|
9880
|
+
eagerlyUsed.add(dir.ref.node);
|
|
9881
|
+
}
|
|
9882
|
+
for (const name of bound.getEagerlyUsedPipes()) {
|
|
9883
|
+
if (pipes.has(name)) {
|
|
9884
|
+
eagerlyUsed.add(pipes.get(name).ref.node);
|
|
9885
|
+
}
|
|
9886
|
+
}
|
|
9887
|
+
}
|
|
9888
|
+
// Set of Directives and Pipes used across the entire template,
|
|
9889
|
+
// including all defer blocks.
|
|
9890
|
+
const wholeTemplateUsed = new Set(eagerlyUsed);
|
|
9891
|
+
for (const bound of deferBlocks.values()) {
|
|
9892
|
+
for (const dir of bound.getUsedDirectives()) {
|
|
9893
|
+
wholeTemplateUsed.add(dir.ref.node);
|
|
9894
|
+
}
|
|
9895
|
+
for (const name of bound.getUsedPipes()) {
|
|
9896
|
+
if (!pipes.has(name)) {
|
|
9897
|
+
continue;
|
|
9898
|
+
}
|
|
9899
|
+
wholeTemplateUsed.add(pipes.get(name).ref.node);
|
|
9900
|
+
}
|
|
9901
|
+
}
|
|
9902
|
+
return { allDependencies, eagerlyUsed, wholeTemplateUsed, deferBlocks };
|
|
9903
|
+
}
|
|
9904
|
+
/**
|
|
9905
|
+
* Converts component dependencies into declarations by
|
|
9906
|
+
* resolving their metadata and deduplicating them.
|
|
9907
|
+
*/
|
|
9908
|
+
componentDependenciesToDeclarations(node, context, allDependencies, wholeTemplateUsed) {
|
|
9909
|
+
const declarations = new Map();
|
|
9910
|
+
// Transform the dependencies list, filtering out unused dependencies.
|
|
9911
|
+
for (const dep of allDependencies) {
|
|
9912
|
+
// Only emit references to each dependency once.
|
|
9913
|
+
if (declarations.has(dep.ref.node)) {
|
|
9914
|
+
continue;
|
|
9915
|
+
}
|
|
9916
|
+
switch (dep.kind) {
|
|
9917
|
+
case checker.MetaKind.Directive:
|
|
9918
|
+
if (!wholeTemplateUsed.has(dep.ref.node) || dep.matchSource !== checker.MatchSource.Selector) {
|
|
9919
|
+
continue;
|
|
9920
|
+
}
|
|
9921
|
+
const dirType = this.refEmitter.emit(dep.ref, context);
|
|
9922
|
+
checker.assertSuccessfulReferenceEmit(dirType, node.name, dep.isComponent ? 'component' : 'directive');
|
|
9923
|
+
declarations.set(dep.ref.node, {
|
|
9924
|
+
kind: compiler.R3TemplateDependencyKind.Directive,
|
|
9925
|
+
ref: dep.ref,
|
|
9926
|
+
type: dirType.expression,
|
|
9927
|
+
importedFile: dirType.importedFile,
|
|
9928
|
+
selector: dep.selector,
|
|
9929
|
+
inputs: dep.inputs.propertyNames,
|
|
9930
|
+
outputs: dep.outputs.propertyNames,
|
|
9931
|
+
exportAs: dep.exportAs,
|
|
9932
|
+
isComponent: dep.isComponent,
|
|
9933
|
+
});
|
|
9934
|
+
break;
|
|
9935
|
+
case checker.MetaKind.Pipe:
|
|
9936
|
+
if (!wholeTemplateUsed.has(dep.ref.node)) {
|
|
9937
|
+
continue;
|
|
9938
|
+
}
|
|
9939
|
+
const pipeType = this.refEmitter.emit(dep.ref, context);
|
|
9940
|
+
checker.assertSuccessfulReferenceEmit(pipeType, node.name, 'pipe');
|
|
9941
|
+
declarations.set(dep.ref.node, {
|
|
9942
|
+
kind: compiler.R3TemplateDependencyKind.Pipe,
|
|
9943
|
+
type: pipeType.expression,
|
|
9944
|
+
name: dep.name,
|
|
9945
|
+
ref: dep.ref,
|
|
9946
|
+
importedFile: pipeType.importedFile,
|
|
9947
|
+
});
|
|
9948
|
+
break;
|
|
9949
|
+
case checker.MetaKind.NgModule:
|
|
9950
|
+
const ngModuleType = this.refEmitter.emit(dep.ref, context);
|
|
9951
|
+
checker.assertSuccessfulReferenceEmit(ngModuleType, node.name, 'NgModule');
|
|
9952
|
+
declarations.set(dep.ref.node, {
|
|
9953
|
+
kind: compiler.R3TemplateDependencyKind.NgModule,
|
|
9954
|
+
type: ngModuleType.expression,
|
|
9955
|
+
importedFile: ngModuleType.importedFile,
|
|
9956
|
+
});
|
|
9957
|
+
break;
|
|
9958
|
+
}
|
|
9959
|
+
}
|
|
9960
|
+
return declarations;
|
|
9961
|
+
}
|
|
9962
|
+
/** Handles any cycles in the dependencies of a component. */
|
|
9963
|
+
handleDependencyCycles(node, context, scope, data, analysis, metadata, declarations, eagerlyUsed, symbol) {
|
|
9964
|
+
const eagerDeclarations = Array.from(declarations.values()).filter((decl) => {
|
|
9965
|
+
return decl.kind === compiler.R3TemplateDependencyKind.NgModule || eagerlyUsed.has(decl.ref.node);
|
|
9966
|
+
});
|
|
9967
|
+
const cyclesFromDirectives = new Map();
|
|
9968
|
+
const cyclesFromPipes = new Map();
|
|
9969
|
+
// Scan through the directives/pipes actually used in the template and check whether any
|
|
9970
|
+
// import which needs to be generated would create a cycle. This check is skipped for
|
|
9971
|
+
// standalone components as the dependencies of a standalone component have already been
|
|
9972
|
+
// imported directly by the user, so Angular won't introduce any imports that aren't already
|
|
9973
|
+
// in the user's program.
|
|
9974
|
+
if (!metadata.isStandalone) {
|
|
9975
|
+
for (const usedDep of eagerDeclarations) {
|
|
9976
|
+
const cycle = this._checkForCyclicImport(usedDep.importedFile, usedDep.type, context);
|
|
9977
|
+
if (cycle !== null) {
|
|
9978
|
+
switch (usedDep.kind) {
|
|
9979
|
+
case compiler.R3TemplateDependencyKind.Directive:
|
|
9980
|
+
cyclesFromDirectives.set(usedDep, cycle);
|
|
9981
|
+
break;
|
|
9982
|
+
case compiler.R3TemplateDependencyKind.Pipe:
|
|
9983
|
+
cyclesFromPipes.set(usedDep, cycle);
|
|
9984
|
+
break;
|
|
9985
|
+
}
|
|
9986
|
+
}
|
|
9987
|
+
}
|
|
9988
|
+
}
|
|
9989
|
+
// Check whether any usages of standalone components in imports requires the dependencies
|
|
9990
|
+
// array to be wrapped in a closure. This check is technically a heuristic as there's no
|
|
9991
|
+
// direct way to check whether a `Reference` came from a `forwardRef`. Instead, we check if
|
|
9992
|
+
// the reference is `synthetic`, implying it came from _any_ foreign function resolver,
|
|
9993
|
+
// including the `forwardRef` resolver.
|
|
9994
|
+
const standaloneImportMayBeForwardDeclared = analysis.resolvedImports !== null && analysis.resolvedImports.some((ref) => ref.synthetic);
|
|
9995
|
+
const cycleDetected = cyclesFromDirectives.size !== 0 || cyclesFromPipes.size !== 0;
|
|
9996
|
+
if (!cycleDetected) {
|
|
9997
|
+
// No cycle was detected. Record the imports that need to be created in the cycle detector
|
|
9998
|
+
// so that future cyclic import checks consider their production.
|
|
9999
|
+
for (const { type, importedFile } of eagerDeclarations) {
|
|
10000
|
+
this.maybeRecordSyntheticImport(importedFile, type, context);
|
|
10001
|
+
}
|
|
10002
|
+
// Check whether the dependencies arrays in ɵcmp need to be wrapped in a closure.
|
|
10003
|
+
// This is required if any dependency reference is to a declaration in the same file
|
|
10004
|
+
// but declared after this component.
|
|
10005
|
+
const declarationIsForwardDeclared = eagerDeclarations.some((decl) => checker.isExpressionForwardReference(decl.type, node.name, context));
|
|
10006
|
+
if (this.compilationMode !== checker.CompilationMode.LOCAL &&
|
|
10007
|
+
(declarationIsForwardDeclared || standaloneImportMayBeForwardDeclared)) {
|
|
10008
|
+
data.declarationListEmitMode = 1 /* DeclarationListEmitMode.Closure */;
|
|
10009
|
+
}
|
|
10010
|
+
data.declarations = eagerDeclarations;
|
|
10011
|
+
// Register extra local imports.
|
|
10012
|
+
if (this.compilationMode === checker.CompilationMode.LOCAL &&
|
|
10013
|
+
this.localCompilationExtraImportsTracker !== null) {
|
|
10014
|
+
// In global compilation mode `eagerDeclarations` contains "all" the component
|
|
10015
|
+
// dependencies, whose import statements will be added to the file. In local compilation
|
|
10016
|
+
// mode `eagerDeclarations` only includes the "local" dependencies, meaning those that are
|
|
10017
|
+
// declared inside this compilation unit.Here the import info of these local dependencies
|
|
10018
|
+
// are added to the tracker so that we can generate extra imports representing these local
|
|
10019
|
+
// dependencies. For non-local dependencies we use another technique of adding some
|
|
10020
|
+
// best-guess extra imports globally to all files using
|
|
10021
|
+
// `localCompilationExtraImportsTracker.addGlobalImportFromIdentifier`.
|
|
10022
|
+
for (const { type } of eagerDeclarations) {
|
|
10023
|
+
if (type instanceof compiler.ExternalExpr && type.value.moduleName) {
|
|
10024
|
+
this.localCompilationExtraImportsTracker.addImportForFile(context, type.value.moduleName);
|
|
10025
|
+
}
|
|
10026
|
+
}
|
|
10027
|
+
}
|
|
10028
|
+
}
|
|
10029
|
+
else if (this.cycleHandlingStrategy === 0 /* CycleHandlingStrategy.UseRemoteScoping */) {
|
|
10030
|
+
// Declaring the directiveDefs/pipeDefs arrays directly would require imports that would
|
|
10031
|
+
// create a cycle. Instead, mark this component as requiring remote scoping, so that the
|
|
10032
|
+
// NgModule file will take care of setting the directives for the component.
|
|
10033
|
+
this.scopeRegistry.setComponentRemoteScope(node, eagerDeclarations.filter(isUsedDirective).map((dir) => dir.ref), eagerDeclarations.filter(isUsedPipe).map((pipe) => pipe.ref));
|
|
10034
|
+
symbol.isRemotelyScoped = true;
|
|
10035
|
+
// If a semantic graph is being tracked, record the fact that this component is remotely
|
|
10036
|
+
// scoped with the declaring NgModule symbol as the NgModule's emit becomes dependent on
|
|
10037
|
+
// the directive/pipe usages of this component.
|
|
10038
|
+
if (this.semanticDepGraphUpdater !== null &&
|
|
10039
|
+
scope.kind === checker.ComponentScopeKind.NgModule &&
|
|
10040
|
+
scope.ngModule !== null) {
|
|
10041
|
+
const moduleSymbol = this.semanticDepGraphUpdater.getSymbol(scope.ngModule);
|
|
10042
|
+
if (!(moduleSymbol instanceof NgModuleSymbol)) {
|
|
10043
|
+
throw new Error(`AssertionError: Expected ${scope.ngModule.name} to be an NgModuleSymbol.`);
|
|
10044
|
+
}
|
|
10045
|
+
moduleSymbol.addRemotelyScopedComponent(symbol, symbol.usedDirectives, symbol.usedPipes);
|
|
10046
|
+
}
|
|
10047
|
+
}
|
|
10048
|
+
else {
|
|
10049
|
+
// We are not able to handle this cycle so throw an error.
|
|
10050
|
+
const relatedMessages = [];
|
|
10051
|
+
for (const [dir, cycle] of cyclesFromDirectives) {
|
|
10052
|
+
relatedMessages.push(makeCyclicImportInfo(dir.ref, dir.isComponent ? 'component' : 'directive', cycle));
|
|
10053
|
+
}
|
|
10054
|
+
for (const [pipe, cycle] of cyclesFromPipes) {
|
|
10055
|
+
relatedMessages.push(makeCyclicImportInfo(pipe.ref, 'pipe', cycle));
|
|
10056
|
+
}
|
|
10057
|
+
throw new checker.FatalDiagnosticError(checker.ErrorCode.IMPORT_CYCLE_DETECTED, node, 'One or more import cycles would need to be created to compile this component, ' +
|
|
10058
|
+
'which is not supported by the current compiler configuration.', relatedMessages);
|
|
10059
|
+
}
|
|
10060
|
+
}
|
|
10061
|
+
/** Produces diagnostics that require more than local information. */
|
|
10062
|
+
getNonLocalDiagnostics(node, analysis) {
|
|
10063
|
+
// We shouldn't be able to hit this, but add an assertion just in case the call site changes.
|
|
10064
|
+
if (this.compilationMode === checker.CompilationMode.LOCAL) {
|
|
10065
|
+
throw new Error('Method cannot be called in local compilation mode.');
|
|
10066
|
+
}
|
|
10067
|
+
let diagnostics = null;
|
|
10068
|
+
// Validate `@Component.imports` and `@Component.deferredImports` fields.
|
|
10069
|
+
if (analysis.resolvedImports !== null && analysis.rawImports !== null) {
|
|
10070
|
+
const importDiagnostics = validateStandaloneImports(analysis.resolvedImports, analysis.rawImports, this.metaReader, this.scopeReader, false /* isDeferredImport */);
|
|
10071
|
+
diagnostics ??= [];
|
|
10072
|
+
diagnostics.push(...importDiagnostics);
|
|
10073
|
+
}
|
|
10074
|
+
if (analysis.resolvedDeferredImports !== null && analysis.rawDeferredImports !== null) {
|
|
10075
|
+
const importDiagnostics = validateStandaloneImports(analysis.resolvedDeferredImports, analysis.rawDeferredImports, this.metaReader, this.scopeReader, true /* isDeferredImport */);
|
|
10076
|
+
diagnostics ??= [];
|
|
10077
|
+
diagnostics.push(...importDiagnostics);
|
|
10078
|
+
}
|
|
10079
|
+
if (analysis.providersRequiringFactory !== null &&
|
|
10080
|
+
analysis.meta.providers instanceof compiler.WrappedNodeExpr) {
|
|
10081
|
+
const providerDiagnostics = checker.getProviderDiagnostics(analysis.providersRequiringFactory, analysis.meta.providers.node, this.injectableRegistry);
|
|
10082
|
+
diagnostics ??= [];
|
|
10083
|
+
diagnostics.push(...providerDiagnostics);
|
|
10084
|
+
}
|
|
10085
|
+
if (analysis.viewProvidersRequiringFactory !== null &&
|
|
10086
|
+
analysis.meta.viewProviders instanceof compiler.WrappedNodeExpr) {
|
|
10087
|
+
const viewProviderDiagnostics = checker.getProviderDiagnostics(analysis.viewProvidersRequiringFactory, analysis.meta.viewProviders.node, this.injectableRegistry);
|
|
10088
|
+
diagnostics ??= [];
|
|
10089
|
+
diagnostics.push(...viewProviderDiagnostics);
|
|
10090
|
+
}
|
|
10091
|
+
const directiveDiagnostics = checker.getDirectiveDiagnostics(node, this.injectableRegistry, this.evaluator, this.reflector, this.scopeRegistry, this.strictCtorDeps, 'Component');
|
|
10092
|
+
if (directiveDiagnostics !== null) {
|
|
10093
|
+
diagnostics ??= [];
|
|
10094
|
+
diagnostics.push(...directiveDiagnostics);
|
|
10095
|
+
}
|
|
10096
|
+
const hostDirectivesDiagnostics = analysis.hostDirectives && analysis.rawHostDirectives
|
|
10097
|
+
? checker.validateHostDirectives(analysis.rawHostDirectives, analysis.hostDirectives, this.metaReader)
|
|
10098
|
+
: null;
|
|
10099
|
+
if (hostDirectivesDiagnostics !== null) {
|
|
10100
|
+
diagnostics ??= [];
|
|
10101
|
+
diagnostics.push(...hostDirectivesDiagnostics);
|
|
10102
|
+
}
|
|
10103
|
+
return diagnostics;
|
|
10104
|
+
}
|
|
10062
10105
|
/**
|
|
10063
10106
|
* Locates defer blocks in case scope information is not available.
|
|
10064
10107
|
* For example, this happens in the local compilation mode.
|
|
10065
10108
|
*/
|
|
10066
10109
|
locateDeferBlocksWithoutScope(template) {
|
|
10067
10110
|
const deferBlocks = new Map();
|
|
10068
|
-
const directivelessBinder = new compiler.R3TargetBinder(
|
|
10111
|
+
const directivelessBinder = new compiler.R3TargetBinder(null);
|
|
10069
10112
|
const bound = directivelessBinder.bind({ template: template.nodes });
|
|
10070
10113
|
const deferredBlocks = bound.getDeferBlocks();
|
|
10071
10114
|
for (const block of deferredBlocks) {
|
|
@@ -10875,7 +10918,7 @@ class PipeDecoratorHandler {
|
|
|
10875
10918
|
* @description
|
|
10876
10919
|
* Entry point for all public APIs of the compiler-cli package.
|
|
10877
10920
|
*/
|
|
10878
|
-
new compiler.Version('20.0.0-
|
|
10921
|
+
new compiler.Version('20.0.0-rc.0');
|
|
10879
10922
|
|
|
10880
10923
|
/**
|
|
10881
10924
|
* Whether a given decorator should be treated as an Angular decorator.
|
|
@@ -14901,7 +14944,10 @@ function isSignalSymbol(symbol) {
|
|
|
14901
14944
|
const fileName = decl.getSourceFile().fileName;
|
|
14902
14945
|
return ((ts.isInterfaceDeclaration(decl) || ts.isTypeAliasDeclaration(decl)) &&
|
|
14903
14946
|
SIGNAL_FNS.has(decl.name.text) &&
|
|
14904
|
-
(fileName.includes('@angular/core') ||
|
|
14947
|
+
(fileName.includes('@angular/core') ||
|
|
14948
|
+
fileName.includes('angular2/rc/packages/core') ||
|
|
14949
|
+
fileName.includes('bin/packages/core')) // for local usage in some tests
|
|
14950
|
+
);
|
|
14905
14951
|
}));
|
|
14906
14952
|
}
|
|
14907
14953
|
|
|
@@ -15152,7 +15198,7 @@ function buildDiagnosticForSignal(ctx, node, component) {
|
|
|
15152
15198
|
}
|
|
15153
15199
|
return [];
|
|
15154
15200
|
}
|
|
15155
|
-
const factory$
|
|
15201
|
+
const factory$d = {
|
|
15156
15202
|
code: checker.ErrorCode.INTERPOLATED_SIGNAL_NOT_INVOKED,
|
|
15157
15203
|
name: checker.ExtendedTemplateDiagnosticName.INTERPOLATED_SIGNAL_NOT_INVOKED,
|
|
15158
15204
|
create: () => new InterpolatedSignalCheck(),
|
|
@@ -15178,7 +15224,7 @@ class InvalidBananaInBoxCheck extends TemplateCheckWithVisitor {
|
|
|
15178
15224
|
return [diagnostic];
|
|
15179
15225
|
}
|
|
15180
15226
|
}
|
|
15181
|
-
const factory$
|
|
15227
|
+
const factory$c = {
|
|
15182
15228
|
code: checker.ErrorCode.INVALID_BANANA_IN_BOX,
|
|
15183
15229
|
name: checker.ExtendedTemplateDiagnosticName.INVALID_BANANA_IN_BOX,
|
|
15184
15230
|
create: () => new InvalidBananaInBoxCheck(),
|
|
@@ -15193,7 +15239,7 @@ const factory$b = {
|
|
|
15193
15239
|
* are used as structural directives and a warning would be generated. Once the
|
|
15194
15240
|
* `CommonModule` is included, the `ngSwitch` would also be covered.
|
|
15195
15241
|
*/
|
|
15196
|
-
const KNOWN_CONTROL_FLOW_DIRECTIVES = new Map([
|
|
15242
|
+
const KNOWN_CONTROL_FLOW_DIRECTIVES$1 = new Map([
|
|
15197
15243
|
['ngIf', { directive: 'NgIf', builtIn: '@if' }],
|
|
15198
15244
|
['ngFor', { directive: 'NgFor', builtIn: '@for' }],
|
|
15199
15245
|
['ngSwitchCase', { directive: 'NgSwitchCase', builtIn: '@switch with @case' }],
|
|
@@ -15221,7 +15267,7 @@ class MissingControlFlowDirectiveCheck extends TemplateCheckWithVisitor {
|
|
|
15221
15267
|
visitNode(ctx, component, node) {
|
|
15222
15268
|
if (!(node instanceof compiler.Template))
|
|
15223
15269
|
return [];
|
|
15224
|
-
const controlFlowAttr = node.templateAttrs.find((attr) => KNOWN_CONTROL_FLOW_DIRECTIVES.has(attr.name));
|
|
15270
|
+
const controlFlowAttr = node.templateAttrs.find((attr) => KNOWN_CONTROL_FLOW_DIRECTIVES$1.has(attr.name));
|
|
15225
15271
|
if (!controlFlowAttr)
|
|
15226
15272
|
return [];
|
|
15227
15273
|
const symbol = ctx.templateTypeChecker.getSymbolOfNode(node, component);
|
|
@@ -15229,7 +15275,7 @@ class MissingControlFlowDirectiveCheck extends TemplateCheckWithVisitor {
|
|
|
15229
15275
|
return [];
|
|
15230
15276
|
}
|
|
15231
15277
|
const sourceSpan = controlFlowAttr.keySpan || controlFlowAttr.sourceSpan;
|
|
15232
|
-
const directiveAndBuiltIn = KNOWN_CONTROL_FLOW_DIRECTIVES.get(controlFlowAttr.name);
|
|
15278
|
+
const directiveAndBuiltIn = KNOWN_CONTROL_FLOW_DIRECTIVES$1.get(controlFlowAttr.name);
|
|
15233
15279
|
const errorMessage = `The \`*${controlFlowAttr.name}\` directive was used in the template, ` +
|
|
15234
15280
|
`but neither the \`${directiveAndBuiltIn?.directive}\` directive nor the \`CommonModule\` was imported. ` +
|
|
15235
15281
|
`Use Angular's built-in control flow ${directiveAndBuiltIn?.builtIn} or ` +
|
|
@@ -15239,7 +15285,7 @@ class MissingControlFlowDirectiveCheck extends TemplateCheckWithVisitor {
|
|
|
15239
15285
|
return [diagnostic];
|
|
15240
15286
|
}
|
|
15241
15287
|
}
|
|
15242
|
-
const factory$
|
|
15288
|
+
const factory$b = {
|
|
15243
15289
|
code: checker.ErrorCode.MISSING_CONTROL_FLOW_DIRECTIVE,
|
|
15244
15290
|
name: checker.ExtendedTemplateDiagnosticName.MISSING_CONTROL_FLOW_DIRECTIVE,
|
|
15245
15291
|
create: (options) => {
|
|
@@ -15272,12 +15318,67 @@ class MissingNgForOfLetCheck extends TemplateCheckWithVisitor {
|
|
|
15272
15318
|
return [diagnostic];
|
|
15273
15319
|
}
|
|
15274
15320
|
}
|
|
15275
|
-
const factory$
|
|
15321
|
+
const factory$a = {
|
|
15276
15322
|
code: checker.ErrorCode.MISSING_NGFOROF_LET,
|
|
15277
15323
|
name: checker.ExtendedTemplateDiagnosticName.MISSING_NGFOROF_LET,
|
|
15278
15324
|
create: () => new MissingNgForOfLetCheck(),
|
|
15279
15325
|
};
|
|
15280
15326
|
|
|
15327
|
+
/**
|
|
15328
|
+
* The list of known control flow directives present in the `CommonModule`.
|
|
15329
|
+
*
|
|
15330
|
+
* If these control flow directives are missing they will be reported by a separate diagnostic.
|
|
15331
|
+
*/
|
|
15332
|
+
const KNOWN_CONTROL_FLOW_DIRECTIVES = new Set([
|
|
15333
|
+
'ngIf',
|
|
15334
|
+
'ngFor',
|
|
15335
|
+
'ngForOf',
|
|
15336
|
+
'ngForTrackBy',
|
|
15337
|
+
'ngSwitchCase',
|
|
15338
|
+
'ngSwitchDefault',
|
|
15339
|
+
]);
|
|
15340
|
+
/**
|
|
15341
|
+
* Ensures that there are no structural directives (something like *select or *featureFlag)
|
|
15342
|
+
* used in a template of a *standalone* component without importing the directive. Returns
|
|
15343
|
+
* diagnostics in case such a directive is detected.
|
|
15344
|
+
*
|
|
15345
|
+
* Note: this check only handles the cases when structural directive syntax is used (e.g. `*featureFlag`).
|
|
15346
|
+
* Regular binding syntax (e.g. `[featureFlag]`) is handled separately in type checker and treated as a
|
|
15347
|
+
* hard error instead of a warning.
|
|
15348
|
+
*/
|
|
15349
|
+
class MissingStructuralDirectiveCheck extends TemplateCheckWithVisitor {
|
|
15350
|
+
code = checker.ErrorCode.MISSING_STRUCTURAL_DIRECTIVE;
|
|
15351
|
+
run(ctx, component, template) {
|
|
15352
|
+
const componentMetadata = ctx.templateTypeChecker.getDirectiveMetadata(component);
|
|
15353
|
+
// Avoid running this check for non-standalone components.
|
|
15354
|
+
if (!componentMetadata || !componentMetadata.isStandalone) {
|
|
15355
|
+
return [];
|
|
15356
|
+
}
|
|
15357
|
+
return super.run(ctx, component, template);
|
|
15358
|
+
}
|
|
15359
|
+
visitNode(ctx, component, node) {
|
|
15360
|
+
if (!(node instanceof compiler.Template))
|
|
15361
|
+
return [];
|
|
15362
|
+
const customStructuralDirective = node.templateAttrs.find((attr) => !KNOWN_CONTROL_FLOW_DIRECTIVES.has(attr.name));
|
|
15363
|
+
if (!customStructuralDirective)
|
|
15364
|
+
return [];
|
|
15365
|
+
const symbol = ctx.templateTypeChecker.getSymbolOfNode(node, component);
|
|
15366
|
+
if (symbol?.directives.length) {
|
|
15367
|
+
return [];
|
|
15368
|
+
}
|
|
15369
|
+
const sourceSpan = customStructuralDirective.keySpan || customStructuralDirective.sourceSpan;
|
|
15370
|
+
const errorMessage = `A structural directive \`${customStructuralDirective.name}\` was used in the template ` +
|
|
15371
|
+
`without a corresponding import in the component. ` +
|
|
15372
|
+
`Make sure that the directive is included in the \`@Component.imports\` array of this component.`;
|
|
15373
|
+
return [ctx.makeTemplateDiagnostic(sourceSpan, errorMessage)];
|
|
15374
|
+
}
|
|
15375
|
+
}
|
|
15376
|
+
const factory$9 = {
|
|
15377
|
+
code: checker.ErrorCode.MISSING_STRUCTURAL_DIRECTIVE,
|
|
15378
|
+
name: checker.ExtendedTemplateDiagnosticName.MISSING_STRUCTURAL_DIRECTIVE,
|
|
15379
|
+
create: () => new MissingStructuralDirectiveCheck(),
|
|
15380
|
+
};
|
|
15381
|
+
|
|
15281
15382
|
/**
|
|
15282
15383
|
* Ensures the left side of a nullish coalescing operation is nullable.
|
|
15283
15384
|
* Returns diagnostics for the cases where the operator is useless.
|
|
@@ -15751,14 +15852,15 @@ function assertNever(value) {
|
|
|
15751
15852
|
}
|
|
15752
15853
|
|
|
15753
15854
|
const ALL_DIAGNOSTIC_FACTORIES = [
|
|
15754
|
-
factory$
|
|
15855
|
+
factory$c,
|
|
15755
15856
|
factory$8,
|
|
15756
15857
|
factory$7,
|
|
15757
|
-
factory$
|
|
15858
|
+
factory$b,
|
|
15758
15859
|
factory$4,
|
|
15860
|
+
factory$a,
|
|
15759
15861
|
factory$9,
|
|
15760
15862
|
factory$5,
|
|
15761
|
-
factory$
|
|
15863
|
+
factory$d,
|
|
15762
15864
|
factory$3,
|
|
15763
15865
|
factory$1,
|
|
15764
15866
|
factory$6,
|
|
@@ -18811,7 +18913,7 @@ var semver = /*@__PURE__*/getDefaultExportFromCjs(semverExports);
|
|
|
18811
18913
|
* @param minVersion Minimum required version for the feature.
|
|
18812
18914
|
*/
|
|
18813
18915
|
function coreVersionSupportsFeature(coreVersion, minVersion) {
|
|
18814
|
-
// A version of `20.0.0-
|
|
18916
|
+
// A version of `20.0.0-rc.0` usually means that core is at head so it supports
|
|
18815
18917
|
// all features. Use string interpolation prevent the placeholder from being replaced
|
|
18816
18918
|
// with the current version during build time.
|
|
18817
18919
|
if (coreVersion === `0.0.0-${'PLACEHOLDER'}`) {
|
|
@@ -18926,6 +19028,7 @@ class NgCompiler {
|
|
|
18926
19028
|
angularCoreVersion;
|
|
18927
19029
|
enableHmr;
|
|
18928
19030
|
implicitStandaloneValue;
|
|
19031
|
+
enableSelectorless;
|
|
18929
19032
|
/**
|
|
18930
19033
|
* `NgCompiler` can be reused for multiple compilations (for resource-only changes), and each
|
|
18931
19034
|
* new compilation uses a fresh `PerfRecorder`. Thus, classes created with a lifespan of the
|
|
@@ -18970,6 +19073,7 @@ class NgCompiler {
|
|
|
18970
19073
|
// TODO(crisbeto): remove this flag and base `enableBlockSyntax` on the `angularCoreVersion`.
|
|
18971
19074
|
this.enableBlockSyntax = options['_enableBlockSyntax'] ?? true;
|
|
18972
19075
|
this.enableLetSyntax = options['_enableLetSyntax'] ?? true;
|
|
19076
|
+
this.enableSelectorless = options['_enableSelectorless'] ?? false;
|
|
18973
19077
|
// Standalone by default is enabled since v19. We need to toggle it here,
|
|
18974
19078
|
// because the language service extension may be running with the latest
|
|
18975
19079
|
// version of the compiler against an older version of Angular.
|
|
@@ -19750,7 +19854,7 @@ class NgCompiler {
|
|
|
19750
19854
|
const jitDeclarationRegistry = new JitDeclarationRegistry();
|
|
19751
19855
|
// Set up the IvyCompilation, which manages state for the Ivy transformer.
|
|
19752
19856
|
const handlers = [
|
|
19753
|
-
new ComponentDecoratorHandler(reflector, evaluator, metaRegistry, metaReader, scopeReader, this.adapter, ngModuleScopeRegistry, typeCheckScopeRegistry, resourceRegistry, isCore, strictCtorDeps, this.resourceManager, this.adapter.rootDirs, this.options.preserveWhitespaces || false, this.options.i18nUseExternalIds !== false, this.options.enableI18nLegacyMessageIdFormat !== false, this.usePoisonedData, this.options.i18nNormalizeLineEndingsInICUs === true, this.moduleResolver, this.cycleAnalyzer, cycleHandlingStrategy, refEmitter, referencesRegistry, this.incrementalCompilation.depGraph, injectableRegistry, semanticDepGraphUpdater, this.closureCompilerEnabled, this.delegatingPerfRecorder, hostDirectivesResolver, importTracker, supportTestBed, compilationMode, deferredSymbolsTracker, !!this.options.forbidOrphanComponents, this.enableBlockSyntax, this.enableLetSyntax, externalRuntimeStyles, localCompilationExtraImportsTracker, jitDeclarationRegistry, this.options.i18nPreserveWhitespaceForLegacyExtraction ?? true, !!this.options.strictStandalone, this.enableHmr, this.implicitStandaloneValue, typeCheckHostBindings),
|
|
19857
|
+
new ComponentDecoratorHandler(reflector, evaluator, metaRegistry, metaReader, scopeReader, this.adapter, ngModuleScopeRegistry, typeCheckScopeRegistry, resourceRegistry, isCore, strictCtorDeps, this.resourceManager, this.adapter.rootDirs, this.options.preserveWhitespaces || false, this.options.i18nUseExternalIds !== false, this.options.enableI18nLegacyMessageIdFormat !== false, this.usePoisonedData, this.options.i18nNormalizeLineEndingsInICUs === true, this.moduleResolver, this.cycleAnalyzer, cycleHandlingStrategy, refEmitter, referencesRegistry, this.incrementalCompilation.depGraph, injectableRegistry, semanticDepGraphUpdater, this.closureCompilerEnabled, this.delegatingPerfRecorder, hostDirectivesResolver, importTracker, supportTestBed, compilationMode, deferredSymbolsTracker, !!this.options.forbidOrphanComponents, this.enableBlockSyntax, this.enableLetSyntax, externalRuntimeStyles, localCompilationExtraImportsTracker, jitDeclarationRegistry, this.options.i18nPreserveWhitespaceForLegacyExtraction ?? true, !!this.options.strictStandalone, this.enableHmr, this.implicitStandaloneValue, typeCheckHostBindings, this.enableSelectorless),
|
|
19754
19858
|
// TODO(alxhub): understand why the cast here is necessary (something to do with `null`
|
|
19755
19859
|
// not being assignable to `unknown` when wrapped in `Readonly`).
|
|
19756
19860
|
new DirectiveDecoratorHandler(reflector, evaluator, metaRegistry, ngModuleScopeRegistry, metaReader, injectableRegistry, refEmitter, referencesRegistry, isCore, strictCtorDeps, semanticDepGraphUpdater, this.closureCompilerEnabled, this.delegatingPerfRecorder, importTracker, supportTestBed, typeCheckScopeRegistry, compilationMode, jitDeclarationRegistry, resourceRegistry, !!this.options.strictStandalone, this.implicitStandaloneValue, this.usePoisonedData, typeCheckHostBindings),
|