@angular/core 20.0.0-next.2 → 20.0.0-next.4
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/event_dispatcher.d-pVP0-wST.d.ts +345 -0
- package/fesm2022/core.mjs +614 -428
- package/fesm2022/core.mjs.map +1 -1
- package/fesm2022/injector-BlLwZ2sr.mjs +24 -0
- package/fesm2022/injector-BlLwZ2sr.mjs.map +1 -0
- package/fesm2022/primitives/di.mjs +5 -18
- package/fesm2022/primitives/di.mjs.map +1 -1
- package/fesm2022/primitives/event-dispatch.mjs +1 -1
- package/fesm2022/primitives/signals.mjs +4 -589
- package/fesm2022/primitives/signals.mjs.map +1 -1
- package/fesm2022/rxjs-interop.mjs +1 -8
- package/fesm2022/rxjs-interop.mjs.map +1 -1
- package/fesm2022/testing.mjs +2 -10
- package/fesm2022/testing.mjs.map +1 -1
- package/fesm2022/untracked-DkcXpNb_.mjs +620 -0
- package/fesm2022/untracked-DkcXpNb_.mjs.map +1 -0
- package/index.d.ts +7589 -7510
- package/{navigation_types.d-u4EOrrdZ.d.ts → navigation_types.d-DgDrF5rp.d.ts} +2 -2
- package/package.json +2 -2
- package/primitives/di/index.d.ts +25 -10
- package/primitives/event-dispatch/index.d.ts +5 -340
- package/primitives/signals/index.d.ts +5 -208
- package/rxjs-interop/index.d.ts +1 -10
- package/schematics/bundles/{apply_import_manager-CyRT0UvU.js → apply_import_manager-CeNv8GIG.js} +6 -6
- package/schematics/bundles/{checker-DF8ZaFW5.js → checker-k591b6WQ.js} +856 -180
- package/schematics/bundles/cleanup-unused-imports.js +42 -69
- package/schematics/bundles/{compiler_host-Da636uJ8.js → compiler_host-DwM3ugW3.js} +2 -2
- package/schematics/bundles/control-flow-migration.js +34 -13
- package/schematics/bundles/imports-CIX-JgAN.js +1 -1
- package/schematics/bundles/{program-BZk27Ndu.js → index-B4OAlHh8.js} +2234 -2097
- package/schematics/bundles/{index-DnkWgagp.js → index-BhELUmYx.js} +11 -11
- package/schematics/bundles/inject-flags.js +18 -52
- package/schematics/bundles/inject-migration.js +3 -3
- package/schematics/bundles/leading_space-D9nQ8UQC.js +1 -1
- package/schematics/bundles/{migrate_ts_type_references-DtkOnnv0.js → migrate_ts_type_references-Be0TNYen.js} +20 -20
- package/schematics/bundles/ng_decorators-DznZ5jMl.js +1 -1
- package/schematics/bundles/nodes-B16H9JUd.js +1 -1
- package/schematics/bundles/output-migration.js +62 -90
- 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 +3 -3
- package/schematics/bundles/{project_paths-Jtbi76Bs.js → run_in_devkit-CkvEksWP.js} +262 -197
- package/schematics/bundles/self-closing-tags-migration.js +41 -71
- package/schematics/bundles/signal-input-migration.js +69 -97
- package/schematics/bundles/signal-queries-migration.js +80 -108
- package/schematics/bundles/signals.js +11 -11
- package/schematics/bundles/standalone-migration.js +8 -22
- package/schematics/bundles/symbol-VPWguRxr.js +25 -0
- package/schematics/bundles/test-bed-get.js +98 -0
- package/schematics/migrations.json +5 -0
- package/testing/index.d.ts +2 -4
- package/weak_ref.d-BZ7gyRag.d.ts +216 -0
- package/fesm2022/weak_ref-DrMdAIDh.mjs +0 -12
- package/fesm2022/weak_ref-DrMdAIDh.mjs.map +0 -1
- package/schematics/bundles/index-vGJcp5M7.js +0 -30
- package/weak_ref.d-ttyj86RV.d.ts +0 -9
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
/**
|
|
3
|
-
* @license Angular v20.0.0-next.
|
|
3
|
+
* @license Angular v20.0.0-next.4
|
|
4
4
|
* (c) 2010-2025 Google LLC. https://angular.io/
|
|
5
5
|
* License: MIT
|
|
6
6
|
*/
|
|
@@ -2773,6 +2773,11 @@ class Identifiers {
|
|
|
2773
2773
|
name: 'ɵɵdeferEnableTimerScheduling',
|
|
2774
2774
|
moduleName: CORE,
|
|
2775
2775
|
};
|
|
2776
|
+
static conditionalCreate = { name: 'ɵɵconditionalCreate', moduleName: CORE };
|
|
2777
|
+
static conditionalBranchCreate = {
|
|
2778
|
+
name: 'ɵɵconditionalBranchCreate',
|
|
2779
|
+
moduleName: CORE,
|
|
2780
|
+
};
|
|
2776
2781
|
static conditional = { name: 'ɵɵconditional', moduleName: CORE };
|
|
2777
2782
|
static repeater = { name: 'ɵɵrepeater', moduleName: CORE };
|
|
2778
2783
|
static repeaterCreate = { name: 'ɵɵrepeaterCreate', moduleName: CORE };
|
|
@@ -5350,6 +5355,28 @@ let Icu$1 = class Icu {
|
|
|
5350
5355
|
return visitor.visitIcu(this);
|
|
5351
5356
|
}
|
|
5352
5357
|
};
|
|
5358
|
+
/**
|
|
5359
|
+
* AST node that represents the host element of a directive.
|
|
5360
|
+
* This node is used only for type checking purposes and cannot be produced from a user's template.
|
|
5361
|
+
*/
|
|
5362
|
+
class HostElement {
|
|
5363
|
+
tagNames;
|
|
5364
|
+
bindings;
|
|
5365
|
+
listeners;
|
|
5366
|
+
sourceSpan;
|
|
5367
|
+
constructor(tagNames, bindings, listeners, sourceSpan) {
|
|
5368
|
+
this.tagNames = tagNames;
|
|
5369
|
+
this.bindings = bindings;
|
|
5370
|
+
this.listeners = listeners;
|
|
5371
|
+
this.sourceSpan = sourceSpan;
|
|
5372
|
+
if (tagNames.length === 0) {
|
|
5373
|
+
throw new Error('HostElement must have at least one tag name.');
|
|
5374
|
+
}
|
|
5375
|
+
}
|
|
5376
|
+
visit() {
|
|
5377
|
+
throw new Error(`HostElement cannot be visited`);
|
|
5378
|
+
}
|
|
5379
|
+
}
|
|
5353
5380
|
let RecursiveVisitor$1 = class RecursiveVisitor {
|
|
5354
5381
|
visitElement(element) {
|
|
5355
5382
|
visitAll$1(this, element.attributes);
|
|
@@ -8581,167 +8608,175 @@ var OpKind;
|
|
|
8581
8608
|
* node.
|
|
8582
8609
|
*/
|
|
8583
8610
|
OpKind[OpKind["DisableBindings"] = 10] = "DisableBindings";
|
|
8611
|
+
/**
|
|
8612
|
+
* Create a conditional creation instruction op.
|
|
8613
|
+
*/
|
|
8614
|
+
OpKind[OpKind["ConditionalCreate"] = 11] = "ConditionalCreate";
|
|
8615
|
+
/**
|
|
8616
|
+
* Create a conditional branch creation instruction op.
|
|
8617
|
+
*/
|
|
8618
|
+
OpKind[OpKind["ConditionalBranchCreate"] = 12] = "ConditionalBranchCreate";
|
|
8584
8619
|
/**
|
|
8585
8620
|
* An op to conditionally render a template.
|
|
8586
8621
|
*/
|
|
8587
|
-
OpKind[OpKind["Conditional"] =
|
|
8622
|
+
OpKind[OpKind["Conditional"] = 13] = "Conditional";
|
|
8588
8623
|
/**
|
|
8589
8624
|
* An operation to re-enable binding, after it was previously disabled.
|
|
8590
8625
|
*/
|
|
8591
|
-
OpKind[OpKind["EnableBindings"] =
|
|
8626
|
+
OpKind[OpKind["EnableBindings"] = 14] = "EnableBindings";
|
|
8592
8627
|
/**
|
|
8593
8628
|
* An operation to render a text node.
|
|
8594
8629
|
*/
|
|
8595
|
-
OpKind[OpKind["Text"] =
|
|
8630
|
+
OpKind[OpKind["Text"] = 15] = "Text";
|
|
8596
8631
|
/**
|
|
8597
8632
|
* An operation declaring an event listener for an element.
|
|
8598
8633
|
*/
|
|
8599
|
-
OpKind[OpKind["Listener"] =
|
|
8634
|
+
OpKind[OpKind["Listener"] = 16] = "Listener";
|
|
8600
8635
|
/**
|
|
8601
8636
|
* An operation to interpolate text into a text node.
|
|
8602
8637
|
*/
|
|
8603
|
-
OpKind[OpKind["InterpolateText"] =
|
|
8638
|
+
OpKind[OpKind["InterpolateText"] = 17] = "InterpolateText";
|
|
8604
8639
|
/**
|
|
8605
8640
|
* An intermediate binding op, that has not yet been processed into an individual property,
|
|
8606
8641
|
* attribute, style, etc.
|
|
8607
8642
|
*/
|
|
8608
|
-
OpKind[OpKind["Binding"] =
|
|
8643
|
+
OpKind[OpKind["Binding"] = 18] = "Binding";
|
|
8609
8644
|
/**
|
|
8610
8645
|
* An operation to bind an expression to a property of an element.
|
|
8611
8646
|
*/
|
|
8612
|
-
OpKind[OpKind["Property"] =
|
|
8647
|
+
OpKind[OpKind["Property"] = 19] = "Property";
|
|
8613
8648
|
/**
|
|
8614
8649
|
* An operation to bind an expression to a style property of an element.
|
|
8615
8650
|
*/
|
|
8616
|
-
OpKind[OpKind["StyleProp"] =
|
|
8651
|
+
OpKind[OpKind["StyleProp"] = 20] = "StyleProp";
|
|
8617
8652
|
/**
|
|
8618
8653
|
* An operation to bind an expression to a class property of an element.
|
|
8619
8654
|
*/
|
|
8620
|
-
OpKind[OpKind["ClassProp"] =
|
|
8655
|
+
OpKind[OpKind["ClassProp"] = 21] = "ClassProp";
|
|
8621
8656
|
/**
|
|
8622
8657
|
* An operation to bind an expression to the styles of an element.
|
|
8623
8658
|
*/
|
|
8624
|
-
OpKind[OpKind["StyleMap"] =
|
|
8659
|
+
OpKind[OpKind["StyleMap"] = 22] = "StyleMap";
|
|
8625
8660
|
/**
|
|
8626
8661
|
* An operation to bind an expression to the classes of an element.
|
|
8627
8662
|
*/
|
|
8628
|
-
OpKind[OpKind["ClassMap"] =
|
|
8663
|
+
OpKind[OpKind["ClassMap"] = 23] = "ClassMap";
|
|
8629
8664
|
/**
|
|
8630
8665
|
* An operation to advance the runtime's implicit slot context during the update phase of a view.
|
|
8631
8666
|
*/
|
|
8632
|
-
OpKind[OpKind["Advance"] =
|
|
8667
|
+
OpKind[OpKind["Advance"] = 24] = "Advance";
|
|
8633
8668
|
/**
|
|
8634
8669
|
* An operation to instantiate a pipe.
|
|
8635
8670
|
*/
|
|
8636
|
-
OpKind[OpKind["Pipe"] =
|
|
8671
|
+
OpKind[OpKind["Pipe"] = 25] = "Pipe";
|
|
8637
8672
|
/**
|
|
8638
8673
|
* An operation to associate an attribute with an element.
|
|
8639
8674
|
*/
|
|
8640
|
-
OpKind[OpKind["Attribute"] =
|
|
8675
|
+
OpKind[OpKind["Attribute"] = 26] = "Attribute";
|
|
8641
8676
|
/**
|
|
8642
8677
|
* An attribute that has been extracted for inclusion in the consts array.
|
|
8643
8678
|
*/
|
|
8644
|
-
OpKind[OpKind["ExtractedAttribute"] =
|
|
8679
|
+
OpKind[OpKind["ExtractedAttribute"] = 27] = "ExtractedAttribute";
|
|
8645
8680
|
/**
|
|
8646
8681
|
* An operation that configures a `@defer` block.
|
|
8647
8682
|
*/
|
|
8648
|
-
OpKind[OpKind["Defer"] =
|
|
8683
|
+
OpKind[OpKind["Defer"] = 28] = "Defer";
|
|
8649
8684
|
/**
|
|
8650
8685
|
* An operation that controls when a `@defer` loads.
|
|
8651
8686
|
*/
|
|
8652
|
-
OpKind[OpKind["DeferOn"] =
|
|
8687
|
+
OpKind[OpKind["DeferOn"] = 29] = "DeferOn";
|
|
8653
8688
|
/**
|
|
8654
8689
|
* An operation that controls when a `@defer` loads, using a custom expression as the condition.
|
|
8655
8690
|
*/
|
|
8656
|
-
OpKind[OpKind["DeferWhen"] =
|
|
8691
|
+
OpKind[OpKind["DeferWhen"] = 30] = "DeferWhen";
|
|
8657
8692
|
/**
|
|
8658
8693
|
* An i18n message that has been extracted for inclusion in the consts array.
|
|
8659
8694
|
*/
|
|
8660
|
-
OpKind[OpKind["I18nMessage"] =
|
|
8695
|
+
OpKind[OpKind["I18nMessage"] = 31] = "I18nMessage";
|
|
8661
8696
|
/**
|
|
8662
8697
|
* A host binding property.
|
|
8663
8698
|
*/
|
|
8664
|
-
OpKind[OpKind["HostProperty"] =
|
|
8699
|
+
OpKind[OpKind["HostProperty"] = 32] = "HostProperty";
|
|
8665
8700
|
/**
|
|
8666
8701
|
* A namespace change, which causes the subsequent elements to be processed as either HTML or SVG.
|
|
8667
8702
|
*/
|
|
8668
|
-
OpKind[OpKind["Namespace"] =
|
|
8703
|
+
OpKind[OpKind["Namespace"] = 33] = "Namespace";
|
|
8669
8704
|
/**
|
|
8670
8705
|
* Configure a content projeciton definition for the view.
|
|
8671
8706
|
*/
|
|
8672
|
-
OpKind[OpKind["ProjectionDef"] =
|
|
8707
|
+
OpKind[OpKind["ProjectionDef"] = 34] = "ProjectionDef";
|
|
8673
8708
|
/**
|
|
8674
8709
|
* Create a content projection slot.
|
|
8675
8710
|
*/
|
|
8676
|
-
OpKind[OpKind["Projection"] =
|
|
8711
|
+
OpKind[OpKind["Projection"] = 35] = "Projection";
|
|
8677
8712
|
/**
|
|
8678
8713
|
* Create a repeater creation instruction op.
|
|
8679
8714
|
*/
|
|
8680
|
-
OpKind[OpKind["RepeaterCreate"] =
|
|
8715
|
+
OpKind[OpKind["RepeaterCreate"] = 36] = "RepeaterCreate";
|
|
8681
8716
|
/**
|
|
8682
8717
|
* An update up for a repeater.
|
|
8683
8718
|
*/
|
|
8684
|
-
OpKind[OpKind["Repeater"] =
|
|
8719
|
+
OpKind[OpKind["Repeater"] = 37] = "Repeater";
|
|
8685
8720
|
/**
|
|
8686
8721
|
* An operation to bind an expression to the property side of a two-way binding.
|
|
8687
8722
|
*/
|
|
8688
|
-
OpKind[OpKind["TwoWayProperty"] =
|
|
8723
|
+
OpKind[OpKind["TwoWayProperty"] = 38] = "TwoWayProperty";
|
|
8689
8724
|
/**
|
|
8690
8725
|
* An operation declaring the event side of a two-way binding.
|
|
8691
8726
|
*/
|
|
8692
|
-
OpKind[OpKind["TwoWayListener"] =
|
|
8727
|
+
OpKind[OpKind["TwoWayListener"] = 39] = "TwoWayListener";
|
|
8693
8728
|
/**
|
|
8694
8729
|
* A creation-time operation that initializes the slot for a `@let` declaration.
|
|
8695
8730
|
*/
|
|
8696
|
-
OpKind[OpKind["DeclareLet"] =
|
|
8731
|
+
OpKind[OpKind["DeclareLet"] = 40] = "DeclareLet";
|
|
8697
8732
|
/**
|
|
8698
8733
|
* An update-time operation that stores the current value of a `@let` declaration.
|
|
8699
8734
|
*/
|
|
8700
|
-
OpKind[OpKind["StoreLet"] =
|
|
8735
|
+
OpKind[OpKind["StoreLet"] = 41] = "StoreLet";
|
|
8701
8736
|
/**
|
|
8702
8737
|
* The start of an i18n block.
|
|
8703
8738
|
*/
|
|
8704
|
-
OpKind[OpKind["I18nStart"] =
|
|
8739
|
+
OpKind[OpKind["I18nStart"] = 42] = "I18nStart";
|
|
8705
8740
|
/**
|
|
8706
8741
|
* A self-closing i18n on a single element.
|
|
8707
8742
|
*/
|
|
8708
|
-
OpKind[OpKind["I18n"] =
|
|
8743
|
+
OpKind[OpKind["I18n"] = 43] = "I18n";
|
|
8709
8744
|
/**
|
|
8710
8745
|
* The end of an i18n block.
|
|
8711
8746
|
*/
|
|
8712
|
-
OpKind[OpKind["I18nEnd"] =
|
|
8747
|
+
OpKind[OpKind["I18nEnd"] = 44] = "I18nEnd";
|
|
8713
8748
|
/**
|
|
8714
8749
|
* An expression in an i18n message.
|
|
8715
8750
|
*/
|
|
8716
|
-
OpKind[OpKind["I18nExpression"] =
|
|
8751
|
+
OpKind[OpKind["I18nExpression"] = 45] = "I18nExpression";
|
|
8717
8752
|
/**
|
|
8718
8753
|
* An instruction that applies a set of i18n expressions.
|
|
8719
8754
|
*/
|
|
8720
|
-
OpKind[OpKind["I18nApply"] =
|
|
8755
|
+
OpKind[OpKind["I18nApply"] = 46] = "I18nApply";
|
|
8721
8756
|
/**
|
|
8722
8757
|
* An instruction to create an ICU expression.
|
|
8723
8758
|
*/
|
|
8724
|
-
OpKind[OpKind["IcuStart"] =
|
|
8759
|
+
OpKind[OpKind["IcuStart"] = 47] = "IcuStart";
|
|
8725
8760
|
/**
|
|
8726
8761
|
* An instruction to update an ICU expression.
|
|
8727
8762
|
*/
|
|
8728
|
-
OpKind[OpKind["IcuEnd"] =
|
|
8763
|
+
OpKind[OpKind["IcuEnd"] = 48] = "IcuEnd";
|
|
8729
8764
|
/**
|
|
8730
8765
|
* An instruction representing a placeholder in an ICU expression.
|
|
8731
8766
|
*/
|
|
8732
|
-
OpKind[OpKind["IcuPlaceholder"] =
|
|
8767
|
+
OpKind[OpKind["IcuPlaceholder"] = 49] = "IcuPlaceholder";
|
|
8733
8768
|
/**
|
|
8734
8769
|
* An i18n context containing information needed to generate an i18n message.
|
|
8735
8770
|
*/
|
|
8736
|
-
OpKind[OpKind["I18nContext"] =
|
|
8771
|
+
OpKind[OpKind["I18nContext"] = 50] = "I18nContext";
|
|
8737
8772
|
/**
|
|
8738
8773
|
* A creation op that corresponds to i18n attributes on an element.
|
|
8739
8774
|
*/
|
|
8740
|
-
OpKind[OpKind["I18nAttributes"] =
|
|
8775
|
+
OpKind[OpKind["I18nAttributes"] = 51] = "I18nAttributes";
|
|
8741
8776
|
/**
|
|
8742
8777
|
* Creation op that attaches the location at which an element was defined in a template to it.
|
|
8743
8778
|
*/
|
|
8744
|
-
OpKind[OpKind["SourceLocation"] =
|
|
8779
|
+
OpKind[OpKind["SourceLocation"] = 52] = "SourceLocation";
|
|
8745
8780
|
})(OpKind || (OpKind = {}));
|
|
8746
8781
|
/**
|
|
8747
8782
|
* Distinguishes different kinds of IR expressions.
|
|
@@ -10291,6 +10326,8 @@ function transformExpressionsInOp(op, transform, flags) {
|
|
|
10291
10326
|
case OpKind.IcuPlaceholder:
|
|
10292
10327
|
case OpKind.DeclareLet:
|
|
10293
10328
|
case OpKind.SourceLocation:
|
|
10329
|
+
case OpKind.ConditionalCreate:
|
|
10330
|
+
case OpKind.ConditionalBranchCreate:
|
|
10294
10331
|
// These operations contain no expressions.
|
|
10295
10332
|
break;
|
|
10296
10333
|
default:
|
|
@@ -10706,6 +10743,8 @@ const elementContainerOpKinds = new Set([
|
|
|
10706
10743
|
OpKind.ContainerStart,
|
|
10707
10744
|
OpKind.Template,
|
|
10708
10745
|
OpKind.RepeaterCreate,
|
|
10746
|
+
OpKind.ConditionalCreate,
|
|
10747
|
+
OpKind.ConditionalBranchCreate,
|
|
10709
10748
|
]);
|
|
10710
10749
|
/**
|
|
10711
10750
|
* Checks whether the given operation represents the creation of an element or container.
|
|
@@ -10757,6 +10796,48 @@ function createTemplateOp(xref, templateKind, tag, functionNameSuffix, namespace
|
|
|
10757
10796
|
...NEW_OP,
|
|
10758
10797
|
};
|
|
10759
10798
|
}
|
|
10799
|
+
function createConditionalCreateOp(xref, templateKind, tag, functionNameSuffix, namespace, i18nPlaceholder, startSourceSpan, wholeSourceSpan) {
|
|
10800
|
+
return {
|
|
10801
|
+
kind: OpKind.ConditionalCreate,
|
|
10802
|
+
xref,
|
|
10803
|
+
templateKind,
|
|
10804
|
+
attributes: null,
|
|
10805
|
+
tag,
|
|
10806
|
+
handle: new SlotHandle(),
|
|
10807
|
+
functionNameSuffix,
|
|
10808
|
+
decls: null,
|
|
10809
|
+
vars: null,
|
|
10810
|
+
localRefs: [],
|
|
10811
|
+
nonBindable: false,
|
|
10812
|
+
namespace,
|
|
10813
|
+
i18nPlaceholder,
|
|
10814
|
+
startSourceSpan,
|
|
10815
|
+
wholeSourceSpan,
|
|
10816
|
+
...TRAIT_CONSUMES_SLOT,
|
|
10817
|
+
...NEW_OP,
|
|
10818
|
+
};
|
|
10819
|
+
}
|
|
10820
|
+
function createConditionalBranchCreateOp(xref, templateKind, tag, functionNameSuffix, namespace, i18nPlaceholder, startSourceSpan, wholeSourceSpan) {
|
|
10821
|
+
return {
|
|
10822
|
+
kind: OpKind.ConditionalBranchCreate,
|
|
10823
|
+
xref,
|
|
10824
|
+
templateKind,
|
|
10825
|
+
attributes: null,
|
|
10826
|
+
tag,
|
|
10827
|
+
handle: new SlotHandle(),
|
|
10828
|
+
functionNameSuffix,
|
|
10829
|
+
decls: null,
|
|
10830
|
+
vars: null,
|
|
10831
|
+
localRefs: [],
|
|
10832
|
+
nonBindable: false,
|
|
10833
|
+
namespace,
|
|
10834
|
+
i18nPlaceholder,
|
|
10835
|
+
startSourceSpan,
|
|
10836
|
+
wholeSourceSpan,
|
|
10837
|
+
...TRAIT_CONSUMES_SLOT,
|
|
10838
|
+
...NEW_OP,
|
|
10839
|
+
};
|
|
10840
|
+
}
|
|
10760
10841
|
function createRepeaterCreateOp(primaryView, emptyView, tag, track, varNames, emptyTag, i18nPlaceholder, emptyI18nPlaceholder, startSourceSpan, wholeSourceSpan) {
|
|
10761
10842
|
return {
|
|
10762
10843
|
kind: OpKind.RepeaterCreate,
|
|
@@ -11704,36 +11785,38 @@ function specializeBindings(job) {
|
|
|
11704
11785
|
}
|
|
11705
11786
|
}
|
|
11706
11787
|
|
|
11707
|
-
const
|
|
11708
|
-
Identifiers.attribute,
|
|
11709
|
-
Identifiers.classProp,
|
|
11710
|
-
Identifiers.element,
|
|
11711
|
-
Identifiers.elementContainer,
|
|
11712
|
-
Identifiers.elementContainerEnd,
|
|
11713
|
-
Identifiers.elementContainerStart,
|
|
11714
|
-
Identifiers.elementEnd,
|
|
11715
|
-
Identifiers.elementStart,
|
|
11716
|
-
Identifiers.hostProperty,
|
|
11717
|
-
Identifiers.i18nExp,
|
|
11718
|
-
Identifiers.listener,
|
|
11719
|
-
Identifiers.listener,
|
|
11720
|
-
Identifiers.property,
|
|
11721
|
-
Identifiers.styleProp,
|
|
11722
|
-
Identifiers.stylePropInterpolate1,
|
|
11723
|
-
Identifiers.stylePropInterpolate2,
|
|
11724
|
-
Identifiers.stylePropInterpolate3,
|
|
11725
|
-
Identifiers.stylePropInterpolate4,
|
|
11726
|
-
Identifiers.stylePropInterpolate5,
|
|
11727
|
-
Identifiers.stylePropInterpolate6,
|
|
11728
|
-
Identifiers.stylePropInterpolate7,
|
|
11729
|
-
Identifiers.stylePropInterpolate8,
|
|
11730
|
-
Identifiers.stylePropInterpolateV,
|
|
11731
|
-
Identifiers.syntheticHostListener,
|
|
11732
|
-
Identifiers.syntheticHostProperty,
|
|
11733
|
-
Identifiers.templateCreate,
|
|
11734
|
-
Identifiers.twoWayProperty,
|
|
11735
|
-
Identifiers.twoWayListener,
|
|
11736
|
-
Identifiers.declareLet,
|
|
11788
|
+
const CHAIN_COMPATIBILITY = new Map([
|
|
11789
|
+
[Identifiers.attribute, Identifiers.attribute],
|
|
11790
|
+
[Identifiers.classProp, Identifiers.classProp],
|
|
11791
|
+
[Identifiers.element, Identifiers.element],
|
|
11792
|
+
[Identifiers.elementContainer, Identifiers.elementContainer],
|
|
11793
|
+
[Identifiers.elementContainerEnd, Identifiers.elementContainerEnd],
|
|
11794
|
+
[Identifiers.elementContainerStart, Identifiers.elementContainerStart],
|
|
11795
|
+
[Identifiers.elementEnd, Identifiers.elementEnd],
|
|
11796
|
+
[Identifiers.elementStart, Identifiers.elementStart],
|
|
11797
|
+
[Identifiers.hostProperty, Identifiers.hostProperty],
|
|
11798
|
+
[Identifiers.i18nExp, Identifiers.i18nExp],
|
|
11799
|
+
[Identifiers.listener, Identifiers.listener],
|
|
11800
|
+
[Identifiers.listener, Identifiers.listener],
|
|
11801
|
+
[Identifiers.property, Identifiers.property],
|
|
11802
|
+
[Identifiers.styleProp, Identifiers.styleProp],
|
|
11803
|
+
[Identifiers.stylePropInterpolate1, Identifiers.stylePropInterpolate1],
|
|
11804
|
+
[Identifiers.stylePropInterpolate2, Identifiers.stylePropInterpolate2],
|
|
11805
|
+
[Identifiers.stylePropInterpolate3, Identifiers.stylePropInterpolate3],
|
|
11806
|
+
[Identifiers.stylePropInterpolate4, Identifiers.stylePropInterpolate4],
|
|
11807
|
+
[Identifiers.stylePropInterpolate5, Identifiers.stylePropInterpolate5],
|
|
11808
|
+
[Identifiers.stylePropInterpolate6, Identifiers.stylePropInterpolate6],
|
|
11809
|
+
[Identifiers.stylePropInterpolate7, Identifiers.stylePropInterpolate7],
|
|
11810
|
+
[Identifiers.stylePropInterpolate8, Identifiers.stylePropInterpolate8],
|
|
11811
|
+
[Identifiers.stylePropInterpolateV, Identifiers.stylePropInterpolateV],
|
|
11812
|
+
[Identifiers.syntheticHostListener, Identifiers.syntheticHostListener],
|
|
11813
|
+
[Identifiers.syntheticHostProperty, Identifiers.syntheticHostProperty],
|
|
11814
|
+
[Identifiers.templateCreate, Identifiers.templateCreate],
|
|
11815
|
+
[Identifiers.twoWayProperty, Identifiers.twoWayProperty],
|
|
11816
|
+
[Identifiers.twoWayListener, Identifiers.twoWayListener],
|
|
11817
|
+
[Identifiers.declareLet, Identifiers.declareLet],
|
|
11818
|
+
[Identifiers.conditionalCreate, Identifiers.conditionalBranchCreate],
|
|
11819
|
+
[Identifiers.conditionalBranchCreate, Identifiers.conditionalBranchCreate],
|
|
11737
11820
|
]);
|
|
11738
11821
|
/**
|
|
11739
11822
|
* Chaining results in repeated call expressions, causing a deep AST of receiver expressions. To prevent running out of
|
|
@@ -11779,14 +11862,16 @@ function chainOperationsInList(opList) {
|
|
|
11779
11862
|
continue;
|
|
11780
11863
|
}
|
|
11781
11864
|
const instruction = op.statement.expr.fn.value;
|
|
11782
|
-
if (!
|
|
11865
|
+
if (!CHAIN_COMPATIBILITY.has(instruction)) {
|
|
11783
11866
|
// This instruction isn't chainable.
|
|
11784
11867
|
chain = null;
|
|
11785
11868
|
continue;
|
|
11786
11869
|
}
|
|
11787
11870
|
// This instruction can be chained. It can either be added on to the previous chain (if
|
|
11788
11871
|
// compatible) or it can be the start of a new chain.
|
|
11789
|
-
if (chain !== null &&
|
|
11872
|
+
if (chain !== null &&
|
|
11873
|
+
CHAIN_COMPATIBILITY.get(chain.instruction) === instruction &&
|
|
11874
|
+
chain.length < MAX_CHAIN_LENGTH) {
|
|
11790
11875
|
// This instruction can be added onto the previous chain.
|
|
11791
11876
|
const expression = chain.expression.callFn(op.statement.expr.args, op.statement.expr.sourceSpan, op.statement.expr.pure);
|
|
11792
11877
|
chain.expression = expression;
|
|
@@ -13014,6 +13099,8 @@ function recursivelyProcessView(view, parentScope) {
|
|
|
13014
13099
|
const scope = getScopeForView(view, parentScope);
|
|
13015
13100
|
for (const op of view.create) {
|
|
13016
13101
|
switch (op.kind) {
|
|
13102
|
+
case OpKind.ConditionalCreate:
|
|
13103
|
+
case OpKind.ConditionalBranchCreate:
|
|
13017
13104
|
case OpKind.Template:
|
|
13018
13105
|
// Descend into child embedded views.
|
|
13019
13106
|
recursivelyProcessView(view.job.views.get(op.xref), scope);
|
|
@@ -13071,6 +13158,8 @@ function getScopeForView(view, parent) {
|
|
|
13071
13158
|
for (const op of view.create) {
|
|
13072
13159
|
switch (op.kind) {
|
|
13073
13160
|
case OpKind.ElementStart:
|
|
13161
|
+
case OpKind.ConditionalCreate:
|
|
13162
|
+
case OpKind.ConditionalBranchCreate:
|
|
13074
13163
|
case OpKind.Template:
|
|
13075
13164
|
if (!Array.isArray(op.localRefs)) {
|
|
13076
13165
|
throw new Error(`AssertionError: expected localRefs to be an array`);
|
|
@@ -21601,6 +21690,8 @@ function liftLocalRefs(job) {
|
|
|
21601
21690
|
for (const op of unit.create) {
|
|
21602
21691
|
switch (op.kind) {
|
|
21603
21692
|
case OpKind.ElementStart:
|
|
21693
|
+
case OpKind.ConditionalCreate:
|
|
21694
|
+
case OpKind.ConditionalBranchCreate:
|
|
21604
21695
|
case OpKind.Template:
|
|
21605
21696
|
if (!Array.isArray(op.localRefs)) {
|
|
21606
21697
|
throw new Error(`AssertionError: expected localRefs to be an array still`);
|
|
@@ -21743,7 +21834,9 @@ function parseExtractedStyles(job) {
|
|
|
21743
21834
|
isStringLiteral(op.expression)) {
|
|
21744
21835
|
const target = elements.get(op.target);
|
|
21745
21836
|
if (target !== undefined &&
|
|
21746
|
-
target.kind === OpKind.Template
|
|
21837
|
+
(target.kind === OpKind.Template ||
|
|
21838
|
+
target.kind === OpKind.ConditionalCreate ||
|
|
21839
|
+
target.kind === OpKind.ConditionalBranchCreate) &&
|
|
21747
21840
|
target.templateKind === TemplateKind.Structural) {
|
|
21748
21841
|
// TemplateDefinitionBuilder will not apply class and style bindings to structural
|
|
21749
21842
|
// directives; instead, it will leave them as attributes.
|
|
@@ -21858,6 +21951,8 @@ function addNamesToView(unit, baseName, state, compatibility) {
|
|
|
21858
21951
|
addNamesToView(fallbackView, `${baseName}_ProjectionFallback_${op.handle.slot}`, state, compatibility);
|
|
21859
21952
|
}
|
|
21860
21953
|
break;
|
|
21954
|
+
case OpKind.ConditionalCreate:
|
|
21955
|
+
case OpKind.ConditionalBranchCreate:
|
|
21861
21956
|
case OpKind.Template:
|
|
21862
21957
|
if (!(unit instanceof ViewCompilationUnit)) {
|
|
21863
21958
|
throw new Error(`AssertionError: must be compiling a component`);
|
|
@@ -22343,6 +22438,8 @@ function propagateI18nBlocksToTemplates(unit, subTemplateIndex) {
|
|
|
22343
22438
|
}
|
|
22344
22439
|
i18nBlock = null;
|
|
22345
22440
|
break;
|
|
22441
|
+
case OpKind.ConditionalCreate:
|
|
22442
|
+
case OpKind.ConditionalBranchCreate:
|
|
22346
22443
|
case OpKind.Template:
|
|
22347
22444
|
subTemplateIndex = propagateI18nBlocksForView(unit.job.views.get(op.xref), i18nBlock, op.i18nPlaceholder, subTemplateIndex);
|
|
22348
22445
|
break;
|
|
@@ -22548,7 +22645,6 @@ function enableBindings() {
|
|
|
22548
22645
|
function listener(name, handlerFn, eventTargetResolver, syntheticHost, sourceSpan) {
|
|
22549
22646
|
const args = [literal$1(name), handlerFn];
|
|
22550
22647
|
if (eventTargetResolver !== null) {
|
|
22551
|
-
args.push(literal$1(false)); // `useCapture` flag, defaults to `false`
|
|
22552
22648
|
args.push(importExpr(eventTargetResolver));
|
|
22553
22649
|
}
|
|
22554
22650
|
return call(syntheticHost ? Identifiers.syntheticHostListener : Identifiers.listener, args, sourceSpan);
|
|
@@ -22708,6 +22804,42 @@ function i18nStart(slot, constIndex, subTemplateIndex, sourceSpan) {
|
|
|
22708
22804
|
}
|
|
22709
22805
|
return call(Identifiers.i18nStart, args, sourceSpan);
|
|
22710
22806
|
}
|
|
22807
|
+
function conditionalCreate(slot, templateFnRef, decls, vars, tag, constIndex, localRefs, sourceSpan) {
|
|
22808
|
+
const args = [
|
|
22809
|
+
literal$1(slot),
|
|
22810
|
+
templateFnRef,
|
|
22811
|
+
literal$1(decls),
|
|
22812
|
+
literal$1(vars),
|
|
22813
|
+
literal$1(tag),
|
|
22814
|
+
literal$1(constIndex),
|
|
22815
|
+
];
|
|
22816
|
+
if (localRefs !== null) {
|
|
22817
|
+
args.push(literal$1(localRefs));
|
|
22818
|
+
args.push(importExpr(Identifiers.templateRefExtractor));
|
|
22819
|
+
}
|
|
22820
|
+
while (args[args.length - 1].isEquivalent(NULL_EXPR)) {
|
|
22821
|
+
args.pop();
|
|
22822
|
+
}
|
|
22823
|
+
return call(Identifiers.conditionalCreate, args, sourceSpan);
|
|
22824
|
+
}
|
|
22825
|
+
function conditionalBranchCreate(slot, templateFnRef, decls, vars, tag, constIndex, localRefs, sourceSpan) {
|
|
22826
|
+
const args = [
|
|
22827
|
+
literal$1(slot),
|
|
22828
|
+
templateFnRef,
|
|
22829
|
+
literal$1(decls),
|
|
22830
|
+
literal$1(vars),
|
|
22831
|
+
literal$1(tag),
|
|
22832
|
+
literal$1(constIndex),
|
|
22833
|
+
];
|
|
22834
|
+
if (localRefs !== null) {
|
|
22835
|
+
args.push(literal$1(localRefs));
|
|
22836
|
+
args.push(importExpr(Identifiers.templateRefExtractor));
|
|
22837
|
+
}
|
|
22838
|
+
while (args[args.length - 1].isEquivalent(NULL_EXPR)) {
|
|
22839
|
+
args.pop();
|
|
22840
|
+
}
|
|
22841
|
+
return call(Identifiers.conditionalBranchCreate, args, sourceSpan);
|
|
22842
|
+
}
|
|
22711
22843
|
function repeaterCreate(slot, viewFnName, decls, vars, tag, constIndex, trackByFn, trackByUsesComponentInstance, emptyViewFnName, emptyDecls, emptyVars, emptyTag, emptyConstIndex, sourceSpan) {
|
|
22712
22844
|
const args = [
|
|
22713
22845
|
literal$1(slot),
|
|
@@ -23277,6 +23409,26 @@ function reifyCreateOperations(unit, ops) {
|
|
|
23277
23409
|
}
|
|
23278
23410
|
OpList.replace(op, projection(op.handle.slot, op.projectionSlotIndex, op.attributes, fallbackViewFnName, fallbackDecls, fallbackVars, op.sourceSpan));
|
|
23279
23411
|
break;
|
|
23412
|
+
case OpKind.ConditionalCreate:
|
|
23413
|
+
if (!(unit instanceof ViewCompilationUnit)) {
|
|
23414
|
+
throw new Error(`AssertionError: must be compiling a component`);
|
|
23415
|
+
}
|
|
23416
|
+
if (Array.isArray(op.localRefs)) {
|
|
23417
|
+
throw new Error(`AssertionError: local refs array should have been extracted into a constant`);
|
|
23418
|
+
}
|
|
23419
|
+
const conditionalCreateChildView = unit.job.views.get(op.xref);
|
|
23420
|
+
OpList.replace(op, conditionalCreate(op.handle.slot, variable(conditionalCreateChildView.fnName), conditionalCreateChildView.decls, conditionalCreateChildView.vars, op.tag, op.attributes, op.localRefs, op.startSourceSpan));
|
|
23421
|
+
break;
|
|
23422
|
+
case OpKind.ConditionalBranchCreate:
|
|
23423
|
+
if (!(unit instanceof ViewCompilationUnit)) {
|
|
23424
|
+
throw new Error(`AssertionError: must be compiling a component`);
|
|
23425
|
+
}
|
|
23426
|
+
if (Array.isArray(op.localRefs)) {
|
|
23427
|
+
throw new Error(`AssertionError: local refs array should have been extracted into a constant`);
|
|
23428
|
+
}
|
|
23429
|
+
const conditionalBranchCreateChildView = unit.job.views.get(op.xref);
|
|
23430
|
+
OpList.replace(op, conditionalBranchCreate(op.handle.slot, variable(conditionalBranchCreateChildView.fnName), conditionalBranchCreateChildView.decls, conditionalBranchCreateChildView.vars, op.tag, op.attributes, op.localRefs, op.startSourceSpan));
|
|
23431
|
+
break;
|
|
23280
23432
|
case OpKind.RepeaterCreate:
|
|
23281
23433
|
if (op.handle.slot === null) {
|
|
23282
23434
|
throw new Error('No slot was assigned for repeater instruction');
|
|
@@ -23834,6 +23986,8 @@ function resolvePlaceholdersForView(job, unit, i18nContexts, elements, pendingSt
|
|
|
23834
23986
|
pendingStructuralDirective = undefined;
|
|
23835
23987
|
}
|
|
23836
23988
|
break;
|
|
23989
|
+
case OpKind.ConditionalCreate:
|
|
23990
|
+
case OpKind.ConditionalBranchCreate:
|
|
23837
23991
|
case OpKind.Template:
|
|
23838
23992
|
const view = job.views.get(op.xref);
|
|
23839
23993
|
if (op.i18nPlaceholder === undefined) {
|
|
@@ -24397,7 +24551,10 @@ function allocateSlots(job) {
|
|
|
24397
24551
|
// propagate the number of slots used for each view into the operation which declares it.
|
|
24398
24552
|
for (const unit of job.units) {
|
|
24399
24553
|
for (const op of unit.ops()) {
|
|
24400
|
-
if (op.kind === OpKind.Template ||
|
|
24554
|
+
if (op.kind === OpKind.Template ||
|
|
24555
|
+
op.kind === OpKind.ConditionalCreate ||
|
|
24556
|
+
op.kind === OpKind.ConditionalBranchCreate ||
|
|
24557
|
+
op.kind === OpKind.RepeaterCreate) {
|
|
24401
24558
|
// Record the number of slots used by the view this `ir.TemplateOp` declares in the
|
|
24402
24559
|
// operation itself, so it can be emitted later.
|
|
24403
24560
|
const childView = job.views.get(op.xref);
|
|
@@ -24458,6 +24615,8 @@ function optimizeStoreLet(job) {
|
|
|
24458
24615
|
* typescript AST, the parentheses node is removed, and then the remaining AST is printed, it
|
|
24459
24616
|
* incorrectly prints `a ? b : c ?? d`. This is different from how it handles the same situation
|
|
24460
24617
|
* with `||` and `&&` where it prints the parentheses even if they are not present in the AST.
|
|
24618
|
+
* Note: We may be able to remove this case if Typescript resolves the following issue:
|
|
24619
|
+
* https://github.com/microsoft/TypeScript/issues/61369
|
|
24461
24620
|
*/
|
|
24462
24621
|
function stripNonrequiredParentheses(job) {
|
|
24463
24622
|
// Check which parentheses are required.
|
|
@@ -24832,7 +24991,10 @@ function countVariables(job) {
|
|
|
24832
24991
|
// an embedded view).
|
|
24833
24992
|
for (const unit of job.units) {
|
|
24834
24993
|
for (const op of unit.create) {
|
|
24835
|
-
if (op.kind !== OpKind.Template &&
|
|
24994
|
+
if (op.kind !== OpKind.Template &&
|
|
24995
|
+
op.kind !== OpKind.RepeaterCreate &&
|
|
24996
|
+
op.kind !== OpKind.ConditionalCreate &&
|
|
24997
|
+
op.kind !== OpKind.ConditionalBranchCreate) {
|
|
24836
24998
|
continue;
|
|
24837
24999
|
}
|
|
24838
25000
|
const childView = job.views.get(op.xref);
|
|
@@ -25816,13 +25978,14 @@ function ingestIfBlock(unit, ifBlock) {
|
|
|
25816
25978
|
}
|
|
25817
25979
|
ifCaseI18nMeta = ifCase.i18n;
|
|
25818
25980
|
}
|
|
25819
|
-
const
|
|
25820
|
-
|
|
25981
|
+
const createOp = i === 0 ? createConditionalCreateOp : createConditionalBranchCreateOp;
|
|
25982
|
+
const conditionalCreateOp = createOp(cView.xref, TemplateKind.Block, tagName, 'Conditional', Namespace.HTML, ifCaseI18nMeta, ifCase.startSourceSpan, ifCase.sourceSpan);
|
|
25983
|
+
unit.create.push(conditionalCreateOp);
|
|
25821
25984
|
if (firstXref === null) {
|
|
25822
25985
|
firstXref = cView.xref;
|
|
25823
25986
|
}
|
|
25824
25987
|
const caseExpr = ifCase.expression ? convertAst(ifCase.expression, unit.job, null) : null;
|
|
25825
|
-
const conditionalCaseExpr = new ConditionalCaseExpr(caseExpr,
|
|
25988
|
+
const conditionalCaseExpr = new ConditionalCaseExpr(caseExpr, conditionalCreateOp.xref, conditionalCreateOp.handle, ifCase.expressionAlias);
|
|
25826
25989
|
conditions.push(conditionalCaseExpr);
|
|
25827
25990
|
ingestNodes(cView, ifCase.children);
|
|
25828
25991
|
}
|
|
@@ -25838,7 +26001,8 @@ function ingestSwitchBlock(unit, switchBlock) {
|
|
|
25838
26001
|
}
|
|
25839
26002
|
let firstXref = null;
|
|
25840
26003
|
let conditions = [];
|
|
25841
|
-
for (
|
|
26004
|
+
for (let i = 0; i < switchBlock.cases.length; i++) {
|
|
26005
|
+
const switchCase = switchBlock.cases[i];
|
|
25842
26006
|
const cView = unit.job.allocateView(unit.xref);
|
|
25843
26007
|
const tagName = ingestControlFlowInsertionPoint(unit, cView.xref, switchCase);
|
|
25844
26008
|
let switchCaseI18nMeta = undefined;
|
|
@@ -25848,15 +26012,16 @@ function ingestSwitchBlock(unit, switchBlock) {
|
|
|
25848
26012
|
}
|
|
25849
26013
|
switchCaseI18nMeta = switchCase.i18n;
|
|
25850
26014
|
}
|
|
25851
|
-
const
|
|
25852
|
-
|
|
26015
|
+
const createOp = i === 0 ? createConditionalCreateOp : createConditionalBranchCreateOp;
|
|
26016
|
+
const conditionalCreateOp = createOp(cView.xref, TemplateKind.Block, tagName, 'Case', Namespace.HTML, switchCaseI18nMeta, switchCase.startSourceSpan, switchCase.sourceSpan);
|
|
26017
|
+
unit.create.push(conditionalCreateOp);
|
|
25853
26018
|
if (firstXref === null) {
|
|
25854
26019
|
firstXref = cView.xref;
|
|
25855
26020
|
}
|
|
25856
26021
|
const caseExpr = switchCase.expression
|
|
25857
26022
|
? convertAst(switchCase.expression, unit.job, switchBlock.startSourceSpan)
|
|
25858
26023
|
: null;
|
|
25859
|
-
const conditionalCaseExpr = new ConditionalCaseExpr(caseExpr,
|
|
26024
|
+
const conditionalCaseExpr = new ConditionalCaseExpr(caseExpr, conditionalCreateOp.xref, conditionalCreateOp.handle);
|
|
25860
26025
|
conditions.push(conditionalCaseExpr);
|
|
25861
26026
|
ingestNodes(cView, switchCase.children);
|
|
25862
26027
|
}
|
|
@@ -29463,7 +29628,7 @@ class R3TargetBinder {
|
|
|
29463
29628
|
* metadata about the types referenced in the template.
|
|
29464
29629
|
*/
|
|
29465
29630
|
bind(target) {
|
|
29466
|
-
if (!target.template) {
|
|
29631
|
+
if (!target.template && !target.host) {
|
|
29467
29632
|
throw new Error('Empty bound targets are not supported');
|
|
29468
29633
|
}
|
|
29469
29634
|
const directives = new Map();
|
|
@@ -29493,6 +29658,11 @@ class R3TargetBinder {
|
|
|
29493
29658
|
// template. This extracts all the metadata that doesn't depend on directive matching.
|
|
29494
29659
|
TemplateBinder.applyWithScope(target.template, scope, expressions, symbols, nestingLevel, usedPipes, eagerPipes, deferBlocks);
|
|
29495
29660
|
}
|
|
29661
|
+
// Bind the host element in a separate scope. Note that it only uses the
|
|
29662
|
+
// `TemplateBinder` since directives don't apply inside a host context.
|
|
29663
|
+
if (target.host) {
|
|
29664
|
+
TemplateBinder.applyWithScope(target.host, Scope$1.apply(target.host), expressions, symbols, nestingLevel, usedPipes, eagerPipes, deferBlocks);
|
|
29665
|
+
}
|
|
29496
29666
|
return new R3BoundTarget(target, directives, eagerDirectives, bindings, references, expressions, symbols, nestingLevel, scopedNodeEntities, usedPipes, eagerPipes, deferBlocks);
|
|
29497
29667
|
}
|
|
29498
29668
|
}
|
|
@@ -29568,7 +29738,7 @@ let Scope$1 = class Scope {
|
|
|
29568
29738
|
nodeOrNodes instanceof Content) {
|
|
29569
29739
|
nodeOrNodes.children.forEach((node) => node.visit(this));
|
|
29570
29740
|
}
|
|
29571
|
-
else {
|
|
29741
|
+
else if (!(nodeOrNodes instanceof HostElement)) {
|
|
29572
29742
|
// No overarching `Template` instance, so process the nodes directly.
|
|
29573
29743
|
nodeOrNodes.forEach((node) => node.visit(this));
|
|
29574
29744
|
}
|
|
@@ -29897,7 +30067,7 @@ class TemplateBinder extends RecursiveAstVisitor {
|
|
|
29897
30067
|
/**
|
|
29898
30068
|
* Process a template and extract metadata about expressions and symbols within.
|
|
29899
30069
|
*
|
|
29900
|
-
* @param
|
|
30070
|
+
* @param nodeOrNodes the nodes of the template to process
|
|
29901
30071
|
* @param scope the `Scope` of the template being processed.
|
|
29902
30072
|
* @returns three maps which contain metadata about the template: `expressions` which interprets
|
|
29903
30073
|
* special `AST` nodes in expressions as pointing to references or variables declared within the
|
|
@@ -29906,11 +30076,11 @@ class TemplateBinder extends RecursiveAstVisitor {
|
|
|
29906
30076
|
* nesting level (how many levels deep within the template structure the `Template` is), starting
|
|
29907
30077
|
* at 1.
|
|
29908
30078
|
*/
|
|
29909
|
-
static applyWithScope(
|
|
29910
|
-
const template =
|
|
30079
|
+
static applyWithScope(nodeOrNodes, scope, expressions, symbols, nestingLevel, usedPipes, eagerPipes, deferBlocks) {
|
|
30080
|
+
const template = nodeOrNodes instanceof Template ? nodeOrNodes : null;
|
|
29911
30081
|
// The top-level template has nesting level 0.
|
|
29912
30082
|
const binder = new TemplateBinder(expressions, symbols, usedPipes, eagerPipes, deferBlocks, nestingLevel, scope, template, 0);
|
|
29913
|
-
binder.ingest(
|
|
30083
|
+
binder.ingest(nodeOrNodes);
|
|
29914
30084
|
}
|
|
29915
30085
|
ingest(nodeOrNodes) {
|
|
29916
30086
|
if (nodeOrNodes instanceof Template) {
|
|
@@ -29952,6 +30122,10 @@ class TemplateBinder extends RecursiveAstVisitor {
|
|
|
29952
30122
|
nodeOrNodes.children.forEach((node) => node.visit(this));
|
|
29953
30123
|
this.nestingLevel.set(nodeOrNodes, this.level);
|
|
29954
30124
|
}
|
|
30125
|
+
else if (nodeOrNodes instanceof HostElement) {
|
|
30126
|
+
// Host elements are always at the top level.
|
|
30127
|
+
this.nestingLevel.set(nodeOrNodes, 0);
|
|
30128
|
+
}
|
|
29955
30129
|
else {
|
|
29956
30130
|
// Visit each node from the top-level template.
|
|
29957
30131
|
nodeOrNodes.forEach(this.visitNode);
|
|
@@ -31437,7 +31611,7 @@ var FactoryTarget;
|
|
|
31437
31611
|
* @description
|
|
31438
31612
|
* Entry point for all public APIs of the compiler package.
|
|
31439
31613
|
*/
|
|
31440
|
-
new Version('20.0.0-next.
|
|
31614
|
+
new Version('20.0.0-next.4');
|
|
31441
31615
|
|
|
31442
31616
|
//////////////////////////////////////
|
|
31443
31617
|
// THIS FILE HAS GLOBAL SIDE EFFECT //
|
|
@@ -31903,6 +32077,10 @@ exports.ErrorCode = void 0;
|
|
|
31903
32077
|
* A symbol referenced in `@Component.imports` isn't being used within the template.
|
|
31904
32078
|
*/
|
|
31905
32079
|
ErrorCode[ErrorCode["UNUSED_STANDALONE_IMPORTS"] = 8113] = "UNUSED_STANDALONE_IMPORTS";
|
|
32080
|
+
/**
|
|
32081
|
+
* An expression mixes nullish coalescing and logical and/or without parentheses.
|
|
32082
|
+
*/
|
|
32083
|
+
ErrorCode[ErrorCode["UNPARENTHESIZED_NULLISH_COALESCING"] = 8114] = "UNPARENTHESIZED_NULLISH_COALESCING";
|
|
31906
32084
|
/**
|
|
31907
32085
|
* The template type-checking engine would need to generate an inline type check block for a
|
|
31908
32086
|
* component, but the current type-checking environment doesn't support it.
|
|
@@ -32061,6 +32239,7 @@ exports.ExtendedTemplateDiagnosticName = void 0;
|
|
|
32061
32239
|
ExtendedTemplateDiagnosticName["CONTROL_FLOW_PREVENTING_CONTENT_PROJECTION"] = "controlFlowPreventingContentProjection";
|
|
32062
32240
|
ExtendedTemplateDiagnosticName["UNUSED_LET_DECLARATION"] = "unusedLetDeclaration";
|
|
32063
32241
|
ExtendedTemplateDiagnosticName["UNUSED_STANDALONE_IMPORTS"] = "unusedStandaloneImports";
|
|
32242
|
+
ExtendedTemplateDiagnosticName["UNPARENTHESIZED_NULLISH_COALESCING"] = "unparenthesizedNullishCoalescing";
|
|
32064
32243
|
})(exports.ExtendedTemplateDiagnosticName || (exports.ExtendedTemplateDiagnosticName = {}));
|
|
32065
32244
|
|
|
32066
32245
|
/**
|
|
@@ -32387,7 +32566,7 @@ class NodeJSPathManipulation {
|
|
|
32387
32566
|
// G3-ESM-MARKER: G3 uses CommonJS, but externally everything in ESM.
|
|
32388
32567
|
// CommonJS/ESM interop for determining the current file name and containing dir.
|
|
32389
32568
|
const isCommonJS = typeof __filename !== 'undefined';
|
|
32390
|
-
const currentFileUrl = isCommonJS ? null : (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('checker-
|
|
32569
|
+
const currentFileUrl = isCommonJS ? null : (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('checker-k591b6WQ.js', document.baseURI).href));
|
|
32391
32570
|
const currentFileName = isCommonJS ? __filename : url.fileURLToPath(currentFileUrl);
|
|
32392
32571
|
/**
|
|
32393
32572
|
* A wrapper around the Node.js file-system that supports readonly operations and path manipulation.
|
|
@@ -37638,33 +37817,7 @@ class ExpressionTranslatorVisitor {
|
|
|
37638
37817
|
}
|
|
37639
37818
|
}
|
|
37640
37819
|
visitConditionalExpr(ast, context) {
|
|
37641
|
-
|
|
37642
|
-
// Ordinarily the ternary operator is right-associative. The following are equivalent:
|
|
37643
|
-
// `a ? b : c ? d : e` => `a ? b : (c ? d : e)`
|
|
37644
|
-
//
|
|
37645
|
-
// However, occasionally Angular needs to produce a left-associative conditional, such as in
|
|
37646
|
-
// the case of a null-safe navigation production: `{{a?.b ? c : d}}`. This template produces
|
|
37647
|
-
// a ternary of the form:
|
|
37648
|
-
// `a == null ? null : rest of expression`
|
|
37649
|
-
// If the rest of the expression is also a ternary though, this would produce the form:
|
|
37650
|
-
// `a == null ? null : a.b ? c : d`
|
|
37651
|
-
// which, if left as right-associative, would be incorrectly associated as:
|
|
37652
|
-
// `a == null ? null : (a.b ? c : d)`
|
|
37653
|
-
//
|
|
37654
|
-
// In such cases, the left-associativity needs to be enforced with parentheses:
|
|
37655
|
-
// `(a == null ? null : a.b) ? c : d`
|
|
37656
|
-
//
|
|
37657
|
-
// Such parentheses could always be included in the condition (guaranteeing correct behavior) in
|
|
37658
|
-
// all cases, but this has a code size cost. Instead, parentheses are added only when a
|
|
37659
|
-
// conditional expression is directly used as the condition of another.
|
|
37660
|
-
//
|
|
37661
|
-
// TODO(alxhub): investigate better logic for precendence of conditional operators
|
|
37662
|
-
if (ast.condition instanceof ConditionalExpr) {
|
|
37663
|
-
// The condition of this ternary needs to be wrapped in parentheses to maintain
|
|
37664
|
-
// left-associativity.
|
|
37665
|
-
cond = this.factory.createParenthesizedExpression(cond);
|
|
37666
|
-
}
|
|
37667
|
-
return this.factory.createConditional(cond, ast.trueCase.visitExpression(this, context), ast.falseCase.visitExpression(this, context));
|
|
37820
|
+
return this.factory.createConditional(ast.condition.visitExpression(this, context), ast.trueCase.visitExpression(this, context), ast.falseCase.visitExpression(this, context));
|
|
37668
37821
|
}
|
|
37669
37822
|
visitDynamicImportExpr(ast, context) {
|
|
37670
37823
|
const urlExpression = typeof ast.url === 'string'
|
|
@@ -39209,7 +39362,12 @@ function extractDirectiveMetadata(clazz, decorator, reflector, importTracker, ev
|
|
|
39209
39362
|
throw new FatalDiagnosticError(exports.ErrorCode.DIRECTIVE_MISSING_SELECTOR, expr, `Directive ${clazz.name.text} has no selector, please add it!`);
|
|
39210
39363
|
}
|
|
39211
39364
|
}
|
|
39212
|
-
const
|
|
39365
|
+
const hostBindingNodes = {
|
|
39366
|
+
literal: null,
|
|
39367
|
+
bindingDecorators: new Set(),
|
|
39368
|
+
listenerDecorators: new Set(),
|
|
39369
|
+
};
|
|
39370
|
+
const host = extractHostBindings(decoratedElements, evaluator, coreModule, compilationMode, hostBindingNodes, directive);
|
|
39213
39371
|
const providers = directive.has('providers')
|
|
39214
39372
|
? new WrappedNodeExpr(annotateForClosureCompiler
|
|
39215
39373
|
? wrapFunctionExpressionsInParens(directive.get('providers'))
|
|
@@ -39321,6 +39479,7 @@ function extractDirectiveMetadata(clazz, decorator, reflector, importTracker, ev
|
|
|
39321
39479
|
isStructural,
|
|
39322
39480
|
hostDirectives,
|
|
39323
39481
|
rawHostDirectives,
|
|
39482
|
+
hostBindingNodes,
|
|
39324
39483
|
// Track inputs from class metadata. This is useful for migration efforts.
|
|
39325
39484
|
inputFieldNamesFromMetadataArray: new Set(Object.values(inputsFromMeta).map((i) => i.classPropertyName)),
|
|
39326
39485
|
};
|
|
@@ -39403,10 +39562,14 @@ function extractDecoratorQueryMetadata(exprNode, name, args, propertyName, refle
|
|
|
39403
39562
|
emitDistinctChangesOnly,
|
|
39404
39563
|
};
|
|
39405
39564
|
}
|
|
39406
|
-
function extractHostBindings(members, evaluator, coreModule, compilationMode, metadata) {
|
|
39565
|
+
function extractHostBindings(members, evaluator, coreModule, compilationMode, hostBindingNodes, metadata) {
|
|
39407
39566
|
let bindings;
|
|
39408
39567
|
if (metadata && metadata.has('host')) {
|
|
39409
|
-
|
|
39568
|
+
const hostExpression = metadata.get('host');
|
|
39569
|
+
bindings = evaluateHostExpressionBindings(hostExpression, evaluator);
|
|
39570
|
+
if (ts.isObjectLiteralExpression(hostExpression)) {
|
|
39571
|
+
hostBindingNodes.literal = hostExpression;
|
|
39572
|
+
}
|
|
39410
39573
|
}
|
|
39411
39574
|
else {
|
|
39412
39575
|
bindings = parseHostBindings({});
|
|
@@ -39430,6 +39593,9 @@ function extractHostBindings(members, evaluator, coreModule, compilationMode, me
|
|
|
39430
39593
|
}
|
|
39431
39594
|
hostPropertyName = resolved;
|
|
39432
39595
|
}
|
|
39596
|
+
if (ts.isDecorator(decorator.node)) {
|
|
39597
|
+
hostBindingNodes.bindingDecorators.add(decorator.node);
|
|
39598
|
+
}
|
|
39433
39599
|
// Since this is a decorator, we know that the value is a class member. Always access it
|
|
39434
39600
|
// through `this` so that further down the line it can't be confused for a literal value
|
|
39435
39601
|
// (e.g. if there's a property called `true`). There is no size penalty, because all
|
|
@@ -39465,6 +39631,9 @@ function extractHostBindings(members, evaluator, coreModule, compilationMode, me
|
|
|
39465
39631
|
args = resolvedArgs;
|
|
39466
39632
|
}
|
|
39467
39633
|
}
|
|
39634
|
+
if (ts.isDecorator(decorator.node)) {
|
|
39635
|
+
hostBindingNodes.listenerDecorators.add(decorator.node);
|
|
39636
|
+
}
|
|
39468
39637
|
bindings.listeners[eventName] = `${member.name}(${args.join(',')})`;
|
|
39469
39638
|
});
|
|
39470
39639
|
});
|
|
@@ -40134,6 +40303,19 @@ function toR3InputMetadata(mapping) {
|
|
|
40134
40303
|
isSignal: mapping.isSignal,
|
|
40135
40304
|
};
|
|
40136
40305
|
}
|
|
40306
|
+
function extractHostBindingResources(nodes) {
|
|
40307
|
+
const result = new Set();
|
|
40308
|
+
if (nodes.literal !== null) {
|
|
40309
|
+
result.add({ path: null, node: nodes.literal });
|
|
40310
|
+
}
|
|
40311
|
+
for (const current of nodes.bindingDecorators) {
|
|
40312
|
+
result.add({ path: null, node: current.expression });
|
|
40313
|
+
}
|
|
40314
|
+
for (const current of nodes.listenerDecorators) {
|
|
40315
|
+
result.add({ path: null, node: current.expression });
|
|
40316
|
+
}
|
|
40317
|
+
return result;
|
|
40318
|
+
}
|
|
40137
40319
|
|
|
40138
40320
|
const NgOriginalFile = Symbol('NgOriginalFile');
|
|
40139
40321
|
exports.UpdateMode = void 0;
|
|
@@ -40441,7 +40623,7 @@ function parseTemplateAsSourceFile(fileName, template) {
|
|
|
40441
40623
|
}
|
|
40442
40624
|
|
|
40443
40625
|
const TYPE_CHECK_ID_MAP = Symbol('TypeCheckId');
|
|
40444
|
-
function getTypeCheckId(clazz) {
|
|
40626
|
+
function getTypeCheckId$1(clazz) {
|
|
40445
40627
|
const sf = clazz.getSourceFile();
|
|
40446
40628
|
if (sf[TYPE_CHECK_ID_MAP] === undefined) {
|
|
40447
40629
|
sf[TYPE_CHECK_ID_MAP] = new Map();
|
|
@@ -42212,7 +42394,7 @@ class RegistryDomSchemaChecker {
|
|
|
42212
42394
|
this._diagnostics.push(diag);
|
|
42213
42395
|
}
|
|
42214
42396
|
}
|
|
42215
|
-
|
|
42397
|
+
checkTemplateElementProperty(id, element, name, span, schemas, hostIsStandalone) {
|
|
42216
42398
|
if (!REGISTRY$1.hasProperty(element.name, name, schemas)) {
|
|
42217
42399
|
const mapping = this.resolver.getTemplateSourceMapping(id);
|
|
42218
42400
|
const decorator = hostIsStandalone ? '@Component' : '@NgModule';
|
|
@@ -42235,6 +42417,18 @@ class RegistryDomSchemaChecker {
|
|
|
42235
42417
|
this._diagnostics.push(diag);
|
|
42236
42418
|
}
|
|
42237
42419
|
}
|
|
42420
|
+
checkHostElementProperty(id, element, name, span, schemas) {
|
|
42421
|
+
for (const tagName of element.tagNames) {
|
|
42422
|
+
if (REGISTRY$1.hasProperty(tagName, name, schemas)) {
|
|
42423
|
+
continue;
|
|
42424
|
+
}
|
|
42425
|
+
const errorMessage = `Can't bind to '${name}' since it isn't a known property of '${tagName}'.`;
|
|
42426
|
+
const mapping = this.resolver.getHostBindingsMapping(id);
|
|
42427
|
+
const diag = makeTemplateDiagnostic(id, mapping, span, ts.DiagnosticCategory.Error, ngErrorCode(exports.ErrorCode.SCHEMA_INVALID_ATTRIBUTE), errorMessage);
|
|
42428
|
+
this._diagnostics.push(diag);
|
|
42429
|
+
break;
|
|
42430
|
+
}
|
|
42431
|
+
}
|
|
42238
42432
|
}
|
|
42239
42433
|
|
|
42240
42434
|
/**
|
|
@@ -42346,13 +42540,26 @@ function tsCastToAny(expr) {
|
|
|
42346
42540
|
* Thanks to narrowing of `document.createElement()`, this expression will have its type inferred
|
|
42347
42541
|
* based on the tag name, including for custom elements that have appropriate .d.ts definitions.
|
|
42348
42542
|
*/
|
|
42349
|
-
function tsCreateElement(
|
|
42543
|
+
function tsCreateElement(...tagNames) {
|
|
42350
42544
|
const createElement = ts.factory.createPropertyAccessExpression(
|
|
42351
42545
|
/* expression */ ts.factory.createIdentifier('document'), 'createElement');
|
|
42546
|
+
let arg;
|
|
42547
|
+
if (tagNames.length === 1) {
|
|
42548
|
+
// If there's only one tag name, we can pass it in directly.
|
|
42549
|
+
arg = ts.factory.createStringLiteral(tagNames[0]);
|
|
42550
|
+
}
|
|
42551
|
+
else {
|
|
42552
|
+
// If there's more than one name, we have to generate a union of all the tag names. To do so,
|
|
42553
|
+
// create an expression in the form of `null! as 'tag-1' | 'tag-2' | 'tag-3'`. This allows
|
|
42554
|
+
// TypeScript to infer the type as a union of the differnet tags.
|
|
42555
|
+
const assertedNullExpression = ts.factory.createNonNullExpression(ts.factory.createNull());
|
|
42556
|
+
const type = ts.factory.createUnionTypeNode(tagNames.map((tag) => ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral(tag))));
|
|
42557
|
+
arg = ts.factory.createAsExpression(assertedNullExpression, type);
|
|
42558
|
+
}
|
|
42352
42559
|
return ts.factory.createCallExpression(
|
|
42353
42560
|
/* expression */ createElement,
|
|
42354
42561
|
/* typeArguments */ undefined,
|
|
42355
|
-
/* argumentsArray */ [
|
|
42562
|
+
/* argumentsArray */ [arg]);
|
|
42356
42563
|
}
|
|
42357
42564
|
/**
|
|
42358
42565
|
* Create a `ts.VariableStatement` which declares a variable without explicit initialization.
|
|
@@ -42528,6 +42735,353 @@ class TypeParameterEmitter {
|
|
|
42528
42735
|
}
|
|
42529
42736
|
}
|
|
42530
42737
|
|
|
42738
|
+
/*!
|
|
42739
|
+
* @license
|
|
42740
|
+
* Copyright Google LLC All Rights Reserved.
|
|
42741
|
+
*
|
|
42742
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
42743
|
+
* found in the LICENSE file at https://angular.dev/license
|
|
42744
|
+
*/
|
|
42745
|
+
/**
|
|
42746
|
+
* Comment attached to an AST node that serves as a guard to distinguish nodes
|
|
42747
|
+
* used for type checking host bindings from ones used for templates.
|
|
42748
|
+
*/
|
|
42749
|
+
const GUARD_COMMENT_TEXT = 'hostBindingsBlockGuard';
|
|
42750
|
+
/**
|
|
42751
|
+
* Creates an AST node that represents the host element of a directive.
|
|
42752
|
+
* Can return null if there are no valid bindings to be checked.
|
|
42753
|
+
* @param type Whether the host element is for a directive or a component.
|
|
42754
|
+
* @param selector Selector of the directive.
|
|
42755
|
+
* @param sourceNode Class declaration for the directive.
|
|
42756
|
+
* @param literal `host` object literal from the decorator.
|
|
42757
|
+
* @param bindingDecorators `HostBinding` decorators discovered on the node.
|
|
42758
|
+
* @param listenerDecorators `HostListener` decorators discovered on the node.
|
|
42759
|
+
*/
|
|
42760
|
+
function createHostElement(type, selector, sourceNode, literal, bindingDecorators, listenerDecorators) {
|
|
42761
|
+
const bindings = [];
|
|
42762
|
+
const listeners = [];
|
|
42763
|
+
let parser = null;
|
|
42764
|
+
if (literal !== null) {
|
|
42765
|
+
for (const prop of literal.properties) {
|
|
42766
|
+
// We only support type checking of static bindings.
|
|
42767
|
+
if (ts.isPropertyAssignment(prop) &&
|
|
42768
|
+
ts.isStringLiteralLike(prop.initializer) &&
|
|
42769
|
+
isStaticName(prop.name)) {
|
|
42770
|
+
parser ??= makeBindingParser();
|
|
42771
|
+
createNodeFromHostLiteralProperty(prop, parser, bindings, listeners);
|
|
42772
|
+
}
|
|
42773
|
+
}
|
|
42774
|
+
}
|
|
42775
|
+
for (const decorator of bindingDecorators) {
|
|
42776
|
+
createNodeFromBindingDecorator(decorator, bindings);
|
|
42777
|
+
}
|
|
42778
|
+
for (const decorator of listenerDecorators) {
|
|
42779
|
+
parser ??= makeBindingParser();
|
|
42780
|
+
createNodeFromListenerDecorator(decorator, parser, listeners);
|
|
42781
|
+
}
|
|
42782
|
+
// The element will be a no-op if there are no bindings.
|
|
42783
|
+
if (bindings.length === 0 && listeners.length === 0) {
|
|
42784
|
+
return null;
|
|
42785
|
+
}
|
|
42786
|
+
const tagNames = [];
|
|
42787
|
+
if (selector !== null) {
|
|
42788
|
+
const parts = CssSelector.parse(selector);
|
|
42789
|
+
for (const part of parts) {
|
|
42790
|
+
if (part.element !== null) {
|
|
42791
|
+
tagNames.push(part.element);
|
|
42792
|
+
}
|
|
42793
|
+
}
|
|
42794
|
+
}
|
|
42795
|
+
// If none of the selectors have a tag name, fall back to `ng-component`/`ng-directive`.
|
|
42796
|
+
// This is how the runtime handles components without tag names as well.
|
|
42797
|
+
if (tagNames.length === 0) {
|
|
42798
|
+
tagNames.push(`ng-${type}`);
|
|
42799
|
+
}
|
|
42800
|
+
return new HostElement(tagNames, bindings, listeners, createSourceSpan(sourceNode.name));
|
|
42801
|
+
}
|
|
42802
|
+
/**
|
|
42803
|
+
* Creates an AST node that can be used as a guard in `if` statements to distinguish TypeScript
|
|
42804
|
+
* nodes used for checking host bindings from ones used for checking templates.
|
|
42805
|
+
*/
|
|
42806
|
+
function createHostBindingsBlockGuard() {
|
|
42807
|
+
// Note that the comment text is quite generic. This doesn't really matter, because it is
|
|
42808
|
+
// used only inside a TCB and there's no way for users to produce a comment there.
|
|
42809
|
+
// `true /*hostBindings*/`.
|
|
42810
|
+
const trueExpr = ts.addSyntheticTrailingComment(ts.factory.createTrue(), ts.SyntaxKind.MultiLineCommentTrivia, GUARD_COMMENT_TEXT);
|
|
42811
|
+
// Wrap the expression in parentheses to ensure that the comment is attached to the correct node.
|
|
42812
|
+
return ts.factory.createParenthesizedExpression(trueExpr);
|
|
42813
|
+
}
|
|
42814
|
+
/**
|
|
42815
|
+
* Determines if a given node is a guard that indicates that descendant nodes are used to check
|
|
42816
|
+
* host bindings.
|
|
42817
|
+
*/
|
|
42818
|
+
function isHostBindingsBlockGuard(node) {
|
|
42819
|
+
if (!ts.isIfStatement(node)) {
|
|
42820
|
+
return false;
|
|
42821
|
+
}
|
|
42822
|
+
// Needs to be kept in sync with `createHostBindingsMarker`.
|
|
42823
|
+
const expr = node.expression;
|
|
42824
|
+
if (!ts.isParenthesizedExpression(expr) || expr.expression.kind !== ts.SyntaxKind.TrueKeyword) {
|
|
42825
|
+
return false;
|
|
42826
|
+
}
|
|
42827
|
+
const text = expr.getSourceFile().text;
|
|
42828
|
+
return (ts.forEachTrailingCommentRange(text, expr.expression.getEnd(), (pos, end, kind) => kind === ts.SyntaxKind.MultiLineCommentTrivia &&
|
|
42829
|
+
text.substring(pos + 2, end - 2) === GUARD_COMMENT_TEXT) || false);
|
|
42830
|
+
}
|
|
42831
|
+
/**
|
|
42832
|
+
* If possible, creates and tracks the relevant AST node for a binding declared
|
|
42833
|
+
* through a property on the `host` literal.
|
|
42834
|
+
* @param prop Property to parse.
|
|
42835
|
+
* @param parser Binding parser used to parse the expressions.
|
|
42836
|
+
* @param bindings Array tracking the bound attributes of the host element.
|
|
42837
|
+
* @param listeners Array tracking the event listeners of the host element.
|
|
42838
|
+
*/
|
|
42839
|
+
function createNodeFromHostLiteralProperty(property, parser, bindings, listeners) {
|
|
42840
|
+
// TODO(crisbeto): surface parsing errors here, because currently they just get ignored.
|
|
42841
|
+
// They'll still get reported when the handler tries to parse the bindings, but here we
|
|
42842
|
+
// can highlight the nodes more accurately.
|
|
42843
|
+
const { name, initializer } = property;
|
|
42844
|
+
if (name.text.startsWith('[') && name.text.endsWith(']')) {
|
|
42845
|
+
const { attrName, type } = inferBoundAttribute(name.text.slice(1, -1));
|
|
42846
|
+
const valueSpan = createStaticExpressionSpan(initializer);
|
|
42847
|
+
const ast = parser.parseBinding(initializer.text, true, valueSpan, valueSpan.start.offset);
|
|
42848
|
+
if (ast.errors.length > 0) {
|
|
42849
|
+
return; // See TODO above.
|
|
42850
|
+
}
|
|
42851
|
+
fixupSpans(ast, initializer);
|
|
42852
|
+
bindings.push(new BoundAttribute(attrName, type, 0, ast, null, createSourceSpan(property), createStaticExpressionSpan(name), valueSpan, undefined));
|
|
42853
|
+
}
|
|
42854
|
+
else if (name.text.startsWith('(') && name.text.endsWith(')')) {
|
|
42855
|
+
const events = [];
|
|
42856
|
+
parser.parseEvent(name.text.slice(1, -1), initializer.text, false, createSourceSpan(property), createStaticExpressionSpan(initializer), [], events, createStaticExpressionSpan(name));
|
|
42857
|
+
if (events.length === 0 || events[0].handler.errors.length > 0) {
|
|
42858
|
+
return; // See TODO above.
|
|
42859
|
+
}
|
|
42860
|
+
fixupSpans(events[0].handler, initializer);
|
|
42861
|
+
listeners.push(BoundEvent.fromParsedEvent(events[0]));
|
|
42862
|
+
}
|
|
42863
|
+
}
|
|
42864
|
+
/**
|
|
42865
|
+
* If possible, creates and tracks a bound attribute node from a `HostBinding` decorator.
|
|
42866
|
+
* @param decorator Decorator from which to create the node.
|
|
42867
|
+
* @param bindings Array tracking the bound attributes of the host element.
|
|
42868
|
+
*/
|
|
42869
|
+
function createNodeFromBindingDecorator(decorator, bindings) {
|
|
42870
|
+
// We only support decorators that are being called.
|
|
42871
|
+
if (!ts.isCallExpression(decorator.expression)) {
|
|
42872
|
+
return;
|
|
42873
|
+
}
|
|
42874
|
+
const args = decorator.expression.arguments;
|
|
42875
|
+
const property = decorator.parent;
|
|
42876
|
+
let nameNode = null;
|
|
42877
|
+
let propertyName = null;
|
|
42878
|
+
if (property && ts.isPropertyDeclaration(property) && isStaticName(property.name)) {
|
|
42879
|
+
propertyName = property.name;
|
|
42880
|
+
}
|
|
42881
|
+
// The first parameter is optional. If omitted, the name
|
|
42882
|
+
// of the class member is used as the property.
|
|
42883
|
+
if (args.length === 0) {
|
|
42884
|
+
nameNode = propertyName;
|
|
42885
|
+
}
|
|
42886
|
+
else if (ts.isStringLiteralLike(args[0])) {
|
|
42887
|
+
nameNode = args[0];
|
|
42888
|
+
}
|
|
42889
|
+
else {
|
|
42890
|
+
return;
|
|
42891
|
+
}
|
|
42892
|
+
if (nameNode === null || propertyName === null) {
|
|
42893
|
+
return;
|
|
42894
|
+
}
|
|
42895
|
+
// We can't synthesize a fake expression here and pass it through the binding parser, because
|
|
42896
|
+
// it constructs all the spans based on the source code origin and they aren't easily mappable
|
|
42897
|
+
// back to the source. E.g. `@HostBinding('foo') id = '123'` in source code would look
|
|
42898
|
+
// something like `[foo]="this.id"` in the AST. Instead we construct the expressions
|
|
42899
|
+
// manually here. Note that we use a dummy span with -1/-1 as offsets, because it isn't
|
|
42900
|
+
// used for type checking and constructing it accurately would take some effort.
|
|
42901
|
+
const span = new ParseSpan(-1, -1);
|
|
42902
|
+
const propertyStart = property.getStart();
|
|
42903
|
+
const receiver = new ThisReceiver(span, new AbsoluteSourceSpan(propertyStart, propertyStart));
|
|
42904
|
+
const nameSpan = new AbsoluteSourceSpan(propertyName.getStart(), propertyName.getEnd());
|
|
42905
|
+
const read = ts.isIdentifier(propertyName)
|
|
42906
|
+
? new PropertyRead(span, nameSpan, nameSpan, receiver, propertyName.text)
|
|
42907
|
+
: new KeyedRead(span, nameSpan, receiver, new LiteralPrimitive(span, nameSpan, propertyName.text));
|
|
42908
|
+
const { attrName, type } = inferBoundAttribute(nameNode.text);
|
|
42909
|
+
bindings.push(new BoundAttribute(attrName, type, 0, read, null, createSourceSpan(decorator), createStaticExpressionSpan(nameNode), createSourceSpan(decorator), undefined));
|
|
42910
|
+
}
|
|
42911
|
+
/**
|
|
42912
|
+
* If possible, creates and tracks a bound event node from a `HostBinding` decorator.
|
|
42913
|
+
* @param decorator Decorator from which to create the node.
|
|
42914
|
+
* @param parser Binding parser used to parse the expressions.
|
|
42915
|
+
* @param bindings Array tracking the bound events of the host element.
|
|
42916
|
+
*/
|
|
42917
|
+
function createNodeFromListenerDecorator(decorator, parser, listeners) {
|
|
42918
|
+
// We only support decorators that are being called with at least one argument.
|
|
42919
|
+
if (!ts.isCallExpression(decorator.expression) || decorator.expression.arguments.length === 0) {
|
|
42920
|
+
return;
|
|
42921
|
+
}
|
|
42922
|
+
const args = decorator.expression.arguments;
|
|
42923
|
+
const method = decorator.parent;
|
|
42924
|
+
// Only handle decorators that are statically analyzable.
|
|
42925
|
+
if (!method ||
|
|
42926
|
+
!ts.isMethodDeclaration(method) ||
|
|
42927
|
+
!isStaticName(method.name) ||
|
|
42928
|
+
!ts.isStringLiteralLike(args[0])) {
|
|
42929
|
+
return;
|
|
42930
|
+
}
|
|
42931
|
+
// We can't synthesize a fake expression here and pass it through the binding parser, because
|
|
42932
|
+
// it constructs all the spans based on the source code origin and they aren't easily mappable
|
|
42933
|
+
// back to the source. E.g. `@HostListener('foo') handleFoo() {}` in source code would look
|
|
42934
|
+
// something like `(foo)="handleFoo()"` in the AST. Instead we construct the expressions
|
|
42935
|
+
// manually here. Note that we use a dummy span with -1/-1 as offsets, because it isn't
|
|
42936
|
+
// used for type checking and constructing it accurately would take some effort.
|
|
42937
|
+
const span = new ParseSpan(-1, -1);
|
|
42938
|
+
const argNodes = [];
|
|
42939
|
+
const methodStart = method.getStart();
|
|
42940
|
+
const methodReceiver = new ThisReceiver(span, new AbsoluteSourceSpan(methodStart, methodStart));
|
|
42941
|
+
const nameSpan = new AbsoluteSourceSpan(method.name.getStart(), method.name.getEnd());
|
|
42942
|
+
const receiver = ts.isIdentifier(method.name)
|
|
42943
|
+
? new PropertyRead(span, nameSpan, nameSpan, methodReceiver, method.name.text)
|
|
42944
|
+
: new KeyedRead(span, nameSpan, methodReceiver, new LiteralPrimitive(span, nameSpan, method.name.text));
|
|
42945
|
+
if (args.length > 1 && ts.isArrayLiteralExpression(args[1])) {
|
|
42946
|
+
for (const expr of args[1].elements) {
|
|
42947
|
+
// If the parameter is a static string, parse it using the binding parser since it can be any
|
|
42948
|
+
// expression, otherwise treat it as `any` so the rest of the parameters can be checked.
|
|
42949
|
+
if (ts.isStringLiteralLike(expr)) {
|
|
42950
|
+
const span = createStaticExpressionSpan(expr);
|
|
42951
|
+
const ast = parser.parseBinding(expr.text, true, span, span.start.offset);
|
|
42952
|
+
fixupSpans(ast, expr);
|
|
42953
|
+
argNodes.push(ast);
|
|
42954
|
+
}
|
|
42955
|
+
else {
|
|
42956
|
+
// Represents `$any(0)`. We need to construct it manually in order to set the right spans.
|
|
42957
|
+
const expressionSpan = new AbsoluteSourceSpan(expr.getStart(), expr.getEnd());
|
|
42958
|
+
const anyRead = new PropertyRead(span, expressionSpan, expressionSpan, new ImplicitReceiver(span, expressionSpan), '$any');
|
|
42959
|
+
const anyCall = new Call(span, expressionSpan, anyRead, [new LiteralPrimitive(span, expressionSpan, 0)], expressionSpan);
|
|
42960
|
+
argNodes.push(anyCall);
|
|
42961
|
+
}
|
|
42962
|
+
}
|
|
42963
|
+
}
|
|
42964
|
+
const callNode = new Call(span, nameSpan, receiver, argNodes, span);
|
|
42965
|
+
const eventNameNode = args[0];
|
|
42966
|
+
const [eventName, phase] = eventNameNode.text.split('.');
|
|
42967
|
+
listeners.push(new BoundEvent(eventName, eventName.startsWith('@') ? exports.ParsedEventType.Animation : exports.ParsedEventType.Regular, callNode, null, phase, createSourceSpan(decorator), createSourceSpan(decorator), createStaticExpressionSpan(eventNameNode)));
|
|
42968
|
+
}
|
|
42969
|
+
/**
|
|
42970
|
+
* Infers the attribute name and binding type of a bound attribute based on its raw name.
|
|
42971
|
+
* @param name Name from which to infer the information.
|
|
42972
|
+
*/
|
|
42973
|
+
function inferBoundAttribute(name) {
|
|
42974
|
+
const attrPrefix = 'attr.';
|
|
42975
|
+
const classPrefix = 'class.';
|
|
42976
|
+
const stylePrefix = 'style.';
|
|
42977
|
+
const animationPrefix = '@';
|
|
42978
|
+
let attrName;
|
|
42979
|
+
let type;
|
|
42980
|
+
// Infer the binding type based on the prefix.
|
|
42981
|
+
if (name.startsWith(attrPrefix)) {
|
|
42982
|
+
attrName = name.slice(attrPrefix.length);
|
|
42983
|
+
type = exports.BindingType.Attribute;
|
|
42984
|
+
}
|
|
42985
|
+
else if (name.startsWith(classPrefix)) {
|
|
42986
|
+
attrName = name.slice(classPrefix.length);
|
|
42987
|
+
type = exports.BindingType.Class;
|
|
42988
|
+
}
|
|
42989
|
+
else if (name.startsWith(stylePrefix)) {
|
|
42990
|
+
attrName = name.slice(stylePrefix.length);
|
|
42991
|
+
type = exports.BindingType.Style;
|
|
42992
|
+
}
|
|
42993
|
+
else if (name.startsWith(animationPrefix)) {
|
|
42994
|
+
attrName = name.slice(animationPrefix.length);
|
|
42995
|
+
type = exports.BindingType.Animation;
|
|
42996
|
+
}
|
|
42997
|
+
else {
|
|
42998
|
+
attrName = name;
|
|
42999
|
+
type = exports.BindingType.Property;
|
|
43000
|
+
}
|
|
43001
|
+
return { attrName, type };
|
|
43002
|
+
}
|
|
43003
|
+
/** Checks whether the specified node is a static name node. */
|
|
43004
|
+
function isStaticName(node) {
|
|
43005
|
+
return ts.isIdentifier(node) || ts.isStringLiteralLike(node);
|
|
43006
|
+
}
|
|
43007
|
+
/** Creates a `ParseSourceSpan` pointing to a static expression AST node's source. */
|
|
43008
|
+
function createStaticExpressionSpan(node) {
|
|
43009
|
+
const span = createSourceSpan(node);
|
|
43010
|
+
// Offset by one on both sides to skip over the quotes.
|
|
43011
|
+
if (ts.isStringLiteralLike(node)) {
|
|
43012
|
+
span.fullStart = span.fullStart.moveBy(1);
|
|
43013
|
+
span.start = span.start.moveBy(1);
|
|
43014
|
+
span.end = span.end.moveBy(-1);
|
|
43015
|
+
}
|
|
43016
|
+
return span;
|
|
43017
|
+
}
|
|
43018
|
+
/**
|
|
43019
|
+
* Adjusts the spans of a parsed AST so that they're appropriate for a host bindings context.
|
|
43020
|
+
* @param ast The parsed AST that may need to be adjusted.
|
|
43021
|
+
* @param initializer TypeScript node from which the source of the AST was extracted.
|
|
43022
|
+
*/
|
|
43023
|
+
function fixupSpans(ast, initializer) {
|
|
43024
|
+
// When parsing the initializer as a property/event binding, we use `.text` which excludes escaped
|
|
43025
|
+
// quotes and is generally what we want, because preserving them would result in a parser error,
|
|
43026
|
+
// however it has the downside in that the spans of the expressions following the escaped
|
|
43027
|
+
// characters are no longer accurate relative to the source code. The more escaped characters
|
|
43028
|
+
// there are before a node, the more inaccurate its span will be. If we detect cases like that,
|
|
43029
|
+
// we override the spans of all nodes following the escaped string to point to the entire
|
|
43030
|
+
// initializer string so that we don't surface diagnostics with mangled spans. This isn't ideal,
|
|
43031
|
+
// but is likely rare in user code. Some workarounds that were attempted and ultimately discarded:
|
|
43032
|
+
// 1. Counting the number of escaped strings before a node and adjusting its span accordingly -
|
|
43033
|
+
// There's a prototype of this approach in https://github.com/crisbeto/angular/commit/1eb92353784a609f6be7e6653ae5a9faef549e6a
|
|
43034
|
+
// It works for the most part, but is complex and somewhat brittle, because it's not just the
|
|
43035
|
+
// escaped literals that need to be updated, but also any nodes _after_ them and any nodes
|
|
43036
|
+
// _containing_ them which gets increasingly complex with more complicated ASTs.
|
|
43037
|
+
// 2. Replacing escape characters with whitespaces, for example `\'foo\' + 123` would become
|
|
43038
|
+
// ` 'foo ' + 123` - this appears to produce accurate ASTs for some simpler use cases, but has
|
|
43039
|
+
// the potential of either changing the user's code into something that's no longer parseable or
|
|
43040
|
+
// causing type checking errors (e.g. the typings might require the exact string 'foo').
|
|
43041
|
+
// 3. Passing the raw text (e.g. `initializer.getText().slice(1, -1)`) into the binding parser -
|
|
43042
|
+
// This will preserve the right mappings, but can lead to parsing errors, because some of the
|
|
43043
|
+
// strings won't have to be escaped anymore. We could add a mode to the parser that allows it to
|
|
43044
|
+
// recover from such cases, but it'll introduce more complexity that we may not want to take on.
|
|
43045
|
+
// 4. Constructing some sort of string like `<host ${name.getText()}=${initializer.getText()}/>`,
|
|
43046
|
+
// passing it through the HTML parser and extracting the first attribute from it - wasn't explored
|
|
43047
|
+
// much, but likely has the same issues as approach #3.
|
|
43048
|
+
const escapeIndex = initializer.getText().indexOf('\\', 1);
|
|
43049
|
+
if (escapeIndex > -1) {
|
|
43050
|
+
const newSpan = new ParseSpan(0, initializer.getWidth());
|
|
43051
|
+
const newSourceSpan = new AbsoluteSourceSpan(initializer.getStart(), initializer.getEnd());
|
|
43052
|
+
ast.visit(new ReplaceSpanVisitor(escapeIndex, newSpan, newSourceSpan));
|
|
43053
|
+
}
|
|
43054
|
+
}
|
|
43055
|
+
/**
|
|
43056
|
+
* Visitor that replaces the spans of all nodes with new ones,
|
|
43057
|
+
* if they're defined after a specific index.
|
|
43058
|
+
*/
|
|
43059
|
+
class ReplaceSpanVisitor extends RecursiveAstVisitor {
|
|
43060
|
+
afterIndex;
|
|
43061
|
+
overrideSpan;
|
|
43062
|
+
overrideSourceSpan;
|
|
43063
|
+
constructor(afterIndex, overrideSpan, overrideSourceSpan) {
|
|
43064
|
+
super();
|
|
43065
|
+
this.afterIndex = afterIndex;
|
|
43066
|
+
this.overrideSpan = overrideSpan;
|
|
43067
|
+
this.overrideSourceSpan = overrideSourceSpan;
|
|
43068
|
+
}
|
|
43069
|
+
visit(ast) {
|
|
43070
|
+
// Only nodes after the index need to be adjusted, but all nodes should be visited.
|
|
43071
|
+
if (ast.span.start >= this.afterIndex || ast.span.end >= this.afterIndex) {
|
|
43072
|
+
ast.span = this.overrideSpan;
|
|
43073
|
+
ast.sourceSpan = this.overrideSourceSpan;
|
|
43074
|
+
if (ast instanceof ASTWithName) {
|
|
43075
|
+
ast.nameSpan = this.overrideSourceSpan;
|
|
43076
|
+
}
|
|
43077
|
+
if (ast instanceof Call || ast instanceof SafeCall) {
|
|
43078
|
+
ast.argumentSpan = this.overrideSourceSpan;
|
|
43079
|
+
}
|
|
43080
|
+
}
|
|
43081
|
+
super.visit(ast);
|
|
43082
|
+
}
|
|
43083
|
+
}
|
|
43084
|
+
|
|
42531
43085
|
/**
|
|
42532
43086
|
* External modules/identifiers that always should exist for type check
|
|
42533
43087
|
* block files.
|
|
@@ -42596,18 +43150,39 @@ function getSourceMapping(shimSf, position, resolver, isDiagnosticRequest) {
|
|
|
42596
43150
|
if (sourceLocation === null) {
|
|
42597
43151
|
return null;
|
|
42598
43152
|
}
|
|
42599
|
-
|
|
43153
|
+
if (isInHostBindingTcb(node)) {
|
|
43154
|
+
const hostSourceMapping = resolver.getHostBindingsMapping(sourceLocation.id);
|
|
43155
|
+
const span = resolver.toHostParseSourceSpan(sourceLocation.id, sourceLocation.span);
|
|
43156
|
+
if (span === null) {
|
|
43157
|
+
return null;
|
|
43158
|
+
}
|
|
43159
|
+
return { sourceLocation, sourceMapping: hostSourceMapping, span };
|
|
43160
|
+
}
|
|
42600
43161
|
const span = resolver.toTemplateParseSourceSpan(sourceLocation.id, sourceLocation.span);
|
|
42601
43162
|
if (span === null) {
|
|
42602
43163
|
return null;
|
|
42603
43164
|
}
|
|
42604
43165
|
// TODO(atscott): Consider adding a context span by walking up from `node` until we get a
|
|
42605
43166
|
// different span.
|
|
42606
|
-
return {
|
|
43167
|
+
return {
|
|
43168
|
+
sourceLocation,
|
|
43169
|
+
sourceMapping: resolver.getTemplateSourceMapping(sourceLocation.id),
|
|
43170
|
+
span,
|
|
43171
|
+
};
|
|
43172
|
+
}
|
|
43173
|
+
function isInHostBindingTcb(node) {
|
|
43174
|
+
let current = node;
|
|
43175
|
+
while (current && !ts.isFunctionDeclaration(current)) {
|
|
43176
|
+
if (isHostBindingsBlockGuard(current)) {
|
|
43177
|
+
return true;
|
|
43178
|
+
}
|
|
43179
|
+
current = current.parent;
|
|
43180
|
+
}
|
|
43181
|
+
return false;
|
|
42607
43182
|
}
|
|
42608
43183
|
function findTypeCheckBlock(file, id, isDiagnosticRequest) {
|
|
42609
43184
|
for (const stmt of file.statements) {
|
|
42610
|
-
if (ts.isFunctionDeclaration(stmt) &&
|
|
43185
|
+
if (ts.isFunctionDeclaration(stmt) && getTypeCheckId(stmt, file, isDiagnosticRequest) === id) {
|
|
42611
43186
|
return stmt;
|
|
42612
43187
|
}
|
|
42613
43188
|
}
|
|
@@ -42630,7 +43205,7 @@ function findSourceLocation(node, sourceFile, isDiagnosticsRequest) {
|
|
|
42630
43205
|
if (span !== null) {
|
|
42631
43206
|
// Once the positional information has been extracted, search further up the TCB to extract
|
|
42632
43207
|
// the unique id that is attached with the TCB's function declaration.
|
|
42633
|
-
const id =
|
|
43208
|
+
const id = getTypeCheckId(node, sourceFile, isDiagnosticsRequest);
|
|
42634
43209
|
if (id === null) {
|
|
42635
43210
|
return null;
|
|
42636
43211
|
}
|
|
@@ -42640,7 +43215,7 @@ function findSourceLocation(node, sourceFile, isDiagnosticsRequest) {
|
|
|
42640
43215
|
}
|
|
42641
43216
|
return null;
|
|
42642
43217
|
}
|
|
42643
|
-
function
|
|
43218
|
+
function getTypeCheckId(node, sourceFile, isDiagnosticRequest) {
|
|
42644
43219
|
// Walk up to the function declaration of the TCB, the file information is attached there.
|
|
42645
43220
|
while (!ts.isFunctionDeclaration(node)) {
|
|
42646
43221
|
if (hasIgnoreForDiagnosticsMarker(node, sourceFile) && isDiagnosticRequest) {
|
|
@@ -43896,7 +44471,6 @@ var TcbGenericContextBehavior;
|
|
|
43896
44471
|
*/
|
|
43897
44472
|
function generateTypeCheckBlock(env, ref, name, meta, domSchemaChecker, oobRecorder, genericContextBehavior) {
|
|
43898
44473
|
const tcb = new Context(env, domSchemaChecker, oobRecorder, meta.id, meta.boundTarget, meta.pipes, meta.schemas, meta.isStandalone, meta.preserveWhitespaces);
|
|
43899
|
-
const scope = Scope.forNodes(tcb, null, null, tcb.boundTarget.target.template, /* guard */ null);
|
|
43900
44474
|
const ctxRawType = env.referenceType(ref);
|
|
43901
44475
|
if (!ts.isTypeReferenceNode(ctxRawType)) {
|
|
43902
44476
|
throw new Error(`Expected TypeReferenceNode when referencing the ctx param for ${ref.debugName}`);
|
|
@@ -43923,13 +44497,19 @@ function generateTypeCheckBlock(env, ref, name, meta, domSchemaChecker, oobRecor
|
|
|
43923
44497
|
}
|
|
43924
44498
|
}
|
|
43925
44499
|
const paramList = [tcbThisParam(ctxRawType.typeName, typeArguments)];
|
|
43926
|
-
const
|
|
43927
|
-
|
|
43928
|
-
|
|
43929
|
-
|
|
43930
|
-
|
|
43931
|
-
|
|
43932
|
-
|
|
44500
|
+
const statements = [];
|
|
44501
|
+
// Add the template type checking code.
|
|
44502
|
+
if (tcb.boundTarget.target.template !== undefined) {
|
|
44503
|
+
const templateScope = Scope.forNodes(tcb, null, null, tcb.boundTarget.target.template,
|
|
44504
|
+
/* guard */ null);
|
|
44505
|
+
statements.push(renderBlockStatements(env, templateScope, ts.factory.createTrue()));
|
|
44506
|
+
}
|
|
44507
|
+
// Add the host bindings type checking code.
|
|
44508
|
+
if (tcb.boundTarget.target.host !== undefined) {
|
|
44509
|
+
const hostScope = Scope.forNodes(tcb, null, tcb.boundTarget.target.host, null, null);
|
|
44510
|
+
statements.push(renderBlockStatements(env, hostScope, createHostBindingsBlockGuard()));
|
|
44511
|
+
}
|
|
44512
|
+
const body = ts.factory.createBlock(statements);
|
|
43933
44513
|
const fnDecl = ts.factory.createFunctionDeclaration(
|
|
43934
44514
|
/* modifiers */ undefined,
|
|
43935
44515
|
/* asteriskToken */ undefined,
|
|
@@ -43941,6 +44521,14 @@ function generateTypeCheckBlock(env, ref, name, meta, domSchemaChecker, oobRecor
|
|
|
43941
44521
|
addTypeCheckId(fnDecl, meta.id);
|
|
43942
44522
|
return fnDecl;
|
|
43943
44523
|
}
|
|
44524
|
+
function renderBlockStatements(env, scope, wrapperExpression) {
|
|
44525
|
+
const scopeStatements = scope.render();
|
|
44526
|
+
const innerBody = ts.factory.createBlock([...env.getPreludeStatements(), ...scopeStatements]);
|
|
44527
|
+
// Wrap the body in an if statement. This serves two purposes:
|
|
44528
|
+
// 1. It allows us to distinguish between the sections of the block (e.g. host or template).
|
|
44529
|
+
// 2. It allows the `ts.Printer` to produce better-looking output.
|
|
44530
|
+
return ts.factory.createIfStatement(wrapperExpression, innerBody);
|
|
44531
|
+
}
|
|
43944
44532
|
/**
|
|
43945
44533
|
* A code generation operation that's involved in the construction of a Type Check Block.
|
|
43946
44534
|
*
|
|
@@ -44693,20 +45281,28 @@ class TcbDomSchemaCheckerOp extends TcbOp {
|
|
|
44693
45281
|
return false;
|
|
44694
45282
|
}
|
|
44695
45283
|
execute() {
|
|
44696
|
-
|
|
44697
|
-
|
|
45284
|
+
const element = this.element;
|
|
45285
|
+
const isTemplateElement = element instanceof Element$1;
|
|
45286
|
+
const bindings = isTemplateElement ? element.inputs : element.bindings;
|
|
45287
|
+
if (this.checkElement && isTemplateElement) {
|
|
45288
|
+
this.tcb.domSchemaChecker.checkElement(this.tcb.id, element, this.tcb.schemas, this.tcb.hostIsStandalone);
|
|
44698
45289
|
}
|
|
44699
45290
|
// TODO(alxhub): this could be more efficient.
|
|
44700
|
-
for (const binding of
|
|
45291
|
+
for (const binding of bindings) {
|
|
44701
45292
|
const isPropertyBinding = binding.type === exports.BindingType.Property || binding.type === exports.BindingType.TwoWay;
|
|
44702
|
-
if (isPropertyBinding && this.claimedInputs
|
|
45293
|
+
if (isPropertyBinding && this.claimedInputs?.has(binding.name)) {
|
|
44703
45294
|
// Skip this binding as it was claimed by a directive.
|
|
44704
45295
|
continue;
|
|
44705
45296
|
}
|
|
44706
45297
|
if (isPropertyBinding && binding.name !== 'style' && binding.name !== 'class') {
|
|
44707
45298
|
// A direct binding to a property.
|
|
44708
45299
|
const propertyName = ATTR_TO_PROP.get(binding.name) ?? binding.name;
|
|
44709
|
-
|
|
45300
|
+
if (isTemplateElement) {
|
|
45301
|
+
this.tcb.domSchemaChecker.checkTemplateElementProperty(this.tcb.id, element, propertyName, binding.sourceSpan, this.tcb.schemas, this.tcb.hostIsStandalone);
|
|
45302
|
+
}
|
|
45303
|
+
else {
|
|
45304
|
+
this.tcb.domSchemaChecker.checkHostElementProperty(this.tcb.id, element, propertyName, binding.keySpan, this.tcb.schemas);
|
|
45305
|
+
}
|
|
44710
45306
|
}
|
|
44711
45307
|
}
|
|
44712
45308
|
return null;
|
|
@@ -44821,6 +45417,30 @@ class TcbControlFlowContentProjectionOp extends TcbOp {
|
|
|
44821
45417
|
return false;
|
|
44822
45418
|
}
|
|
44823
45419
|
}
|
|
45420
|
+
/**
|
|
45421
|
+
* A `TcbOp` which creates an expression for a the host element of a directive.
|
|
45422
|
+
*
|
|
45423
|
+
* Executing this operation returns a reference to the element variable.
|
|
45424
|
+
*/
|
|
45425
|
+
class TcbHostElementOp extends TcbOp {
|
|
45426
|
+
tcb;
|
|
45427
|
+
scope;
|
|
45428
|
+
element;
|
|
45429
|
+
optional = true;
|
|
45430
|
+
constructor(tcb, scope, element) {
|
|
45431
|
+
super();
|
|
45432
|
+
this.tcb = tcb;
|
|
45433
|
+
this.scope = scope;
|
|
45434
|
+
this.element = element;
|
|
45435
|
+
}
|
|
45436
|
+
execute() {
|
|
45437
|
+
const id = this.tcb.allocateId();
|
|
45438
|
+
const initializer = tsCreateElement(...this.element.tagNames);
|
|
45439
|
+
addParseSpanInfo(initializer, this.element.sourceSpan);
|
|
45440
|
+
this.scope.addStatement(tsCreateVariable(id, initializer));
|
|
45441
|
+
return id;
|
|
45442
|
+
}
|
|
45443
|
+
}
|
|
44824
45444
|
/**
|
|
44825
45445
|
* Mapping between attributes names that don't correspond to their element property names.
|
|
44826
45446
|
* Note: this mapping has to be kept in sync with the equally named mapping in the runtime.
|
|
@@ -44846,13 +45466,15 @@ const ATTR_TO_PROP = new Map(Object.entries({
|
|
|
44846
45466
|
class TcbUnclaimedInputsOp extends TcbOp {
|
|
44847
45467
|
tcb;
|
|
44848
45468
|
scope;
|
|
44849
|
-
|
|
45469
|
+
inputs;
|
|
45470
|
+
target;
|
|
44850
45471
|
claimedInputs;
|
|
44851
|
-
constructor(tcb, scope,
|
|
45472
|
+
constructor(tcb, scope, inputs, target, claimedInputs) {
|
|
44852
45473
|
super();
|
|
44853
45474
|
this.tcb = tcb;
|
|
44854
45475
|
this.scope = scope;
|
|
44855
|
-
this.
|
|
45476
|
+
this.inputs = inputs;
|
|
45477
|
+
this.target = target;
|
|
44856
45478
|
this.claimedInputs = claimedInputs;
|
|
44857
45479
|
}
|
|
44858
45480
|
get optional() {
|
|
@@ -44863,9 +45485,9 @@ class TcbUnclaimedInputsOp extends TcbOp {
|
|
|
44863
45485
|
// the element itself.
|
|
44864
45486
|
let elId = null;
|
|
44865
45487
|
// TODO(alxhub): this could be more efficient.
|
|
44866
|
-
for (const binding of this.
|
|
45488
|
+
for (const binding of this.inputs) {
|
|
44867
45489
|
const isPropertyBinding = binding.type === exports.BindingType.Property || binding.type === exports.BindingType.TwoWay;
|
|
44868
|
-
if (isPropertyBinding && this.claimedInputs
|
|
45490
|
+
if (isPropertyBinding && this.claimedInputs?.has(binding.name)) {
|
|
44869
45491
|
// Skip this binding as it was claimed by a directive.
|
|
44870
45492
|
continue;
|
|
44871
45493
|
}
|
|
@@ -44873,7 +45495,7 @@ class TcbUnclaimedInputsOp extends TcbOp {
|
|
|
44873
45495
|
if (this.tcb.env.config.checkTypeOfDomBindings && isPropertyBinding) {
|
|
44874
45496
|
if (binding.name !== 'style' && binding.name !== 'class') {
|
|
44875
45497
|
if (elId === null) {
|
|
44876
|
-
elId = this.scope.resolve(this.
|
|
45498
|
+
elId = this.scope.resolve(this.target);
|
|
44877
45499
|
}
|
|
44878
45500
|
// A direct binding to a property.
|
|
44879
45501
|
const propertyName = ATTR_TO_PROP.get(binding.name) ?? binding.name;
|
|
@@ -44973,13 +45595,17 @@ class TcbDirectiveOutputsOp extends TcbOp {
|
|
|
44973
45595
|
class TcbUnclaimedOutputsOp extends TcbOp {
|
|
44974
45596
|
tcb;
|
|
44975
45597
|
scope;
|
|
44976
|
-
|
|
45598
|
+
target;
|
|
45599
|
+
outputs;
|
|
45600
|
+
inputs;
|
|
44977
45601
|
claimedOutputs;
|
|
44978
|
-
constructor(tcb, scope,
|
|
45602
|
+
constructor(tcb, scope, target, outputs, inputs, claimedOutputs) {
|
|
44979
45603
|
super();
|
|
44980
45604
|
this.tcb = tcb;
|
|
44981
45605
|
this.scope = scope;
|
|
44982
|
-
this.
|
|
45606
|
+
this.target = target;
|
|
45607
|
+
this.outputs = outputs;
|
|
45608
|
+
this.inputs = inputs;
|
|
44983
45609
|
this.claimedOutputs = claimedOutputs;
|
|
44984
45610
|
}
|
|
44985
45611
|
get optional() {
|
|
@@ -44988,14 +45614,16 @@ class TcbUnclaimedOutputsOp extends TcbOp {
|
|
|
44988
45614
|
execute() {
|
|
44989
45615
|
let elId = null;
|
|
44990
45616
|
// TODO(alxhub): this could be more efficient.
|
|
44991
|
-
for (const output of this.
|
|
44992
|
-
if (this.claimedOutputs
|
|
45617
|
+
for (const output of this.outputs) {
|
|
45618
|
+
if (this.claimedOutputs?.has(output.name)) {
|
|
44993
45619
|
// Skip this event handler as it was claimed by a directive.
|
|
44994
45620
|
continue;
|
|
44995
45621
|
}
|
|
44996
|
-
if (this.tcb.env.config.checkTypeOfOutputEvents &&
|
|
45622
|
+
if (this.tcb.env.config.checkTypeOfOutputEvents &&
|
|
45623
|
+
this.inputs !== null &&
|
|
45624
|
+
output.name.endsWith('Change')) {
|
|
44997
45625
|
const inputName = output.name.slice(0, -6);
|
|
44998
|
-
if (checkSplitTwoWayBinding(inputName, output, this.
|
|
45626
|
+
if (checkSplitTwoWayBinding(inputName, output, this.inputs, this.tcb)) {
|
|
44999
45627
|
// Skip this event handler as the error was already handled.
|
|
45000
45628
|
continue;
|
|
45001
45629
|
}
|
|
@@ -45016,7 +45644,7 @@ class TcbUnclaimedOutputsOp extends TcbOp {
|
|
|
45016
45644
|
// base `Event` type.
|
|
45017
45645
|
const handler = tcbCreateEventHandler(output, this.tcb, this.scope, 0 /* EventParamType.Infer */);
|
|
45018
45646
|
if (elId === null) {
|
|
45019
|
-
elId = this.scope.resolve(this.
|
|
45647
|
+
elId = this.scope.resolve(this.target);
|
|
45020
45648
|
}
|
|
45021
45649
|
const propertyAccess = ts.factory.createPropertyAccessExpression(elId, 'addEventListener');
|
|
45022
45650
|
addParseSpanInfo(propertyAccess, output.keySpan);
|
|
@@ -45406,6 +46034,10 @@ class Scope {
|
|
|
45406
46034
|
* A map of `TmplAstElement`s to the index of their `TcbElementOp` in the `opQueue`
|
|
45407
46035
|
*/
|
|
45408
46036
|
elementOpMap = new Map();
|
|
46037
|
+
/**
|
|
46038
|
+
* A map of `TmplAstHostElement`s to the index of their `TcbHostElementOp` in the `opQueue`
|
|
46039
|
+
*/
|
|
46040
|
+
hostElementOpMap = new Map();
|
|
45409
46041
|
/**
|
|
45410
46042
|
* A map of maps which tracks the index of `TcbDirectiveCtorOp`s in the `opQueue` for each
|
|
45411
46043
|
* directive on a `TmplAstElement` or `TmplAstTemplate` node.
|
|
@@ -45508,8 +46140,13 @@ class Scope {
|
|
|
45508
46140
|
this.registerVariable(scope, variable, new TcbBlockImplicitVariableOp(tcb, scope, type, variable));
|
|
45509
46141
|
}
|
|
45510
46142
|
}
|
|
45511
|
-
|
|
45512
|
-
scope.appendNode(
|
|
46143
|
+
else if (scopedNode instanceof HostElement) {
|
|
46144
|
+
scope.appendNode(scopedNode);
|
|
46145
|
+
}
|
|
46146
|
+
if (children !== null) {
|
|
46147
|
+
for (const node of children) {
|
|
46148
|
+
scope.appendNode(node);
|
|
46149
|
+
}
|
|
45513
46150
|
}
|
|
45514
46151
|
// Once everything is registered, we need to check if there are `@let`
|
|
45515
46152
|
// declarations that conflict with other local symbols defined after them.
|
|
@@ -45669,6 +46306,9 @@ class Scope {
|
|
|
45669
46306
|
// Resolving the DOM node of an element in this template.
|
|
45670
46307
|
return this.resolveOp(this.elementOpMap.get(ref));
|
|
45671
46308
|
}
|
|
46309
|
+
else if (ref instanceof HostElement && this.hostElementOpMap.has(ref)) {
|
|
46310
|
+
return this.resolveOp(this.hostElementOpMap.get(ref));
|
|
46311
|
+
}
|
|
45672
46312
|
else {
|
|
45673
46313
|
return null;
|
|
45674
46314
|
}
|
|
@@ -45764,6 +46404,11 @@ class Scope {
|
|
|
45764
46404
|
this.letDeclOpMap.set(node.name, { opIndex, node });
|
|
45765
46405
|
}
|
|
45766
46406
|
}
|
|
46407
|
+
else if (node instanceof HostElement) {
|
|
46408
|
+
const opIndex = this.opQueue.push(new TcbHostElementOp(this.tcb, this, node)) - 1;
|
|
46409
|
+
this.hostElementOpMap.set(node, opIndex);
|
|
46410
|
+
this.opQueue.push(new TcbUnclaimedInputsOp(this.tcb, this, node.bindings, node, null), new TcbUnclaimedOutputsOp(this.tcb, this, node, node.listeners, null, null), new TcbDomSchemaCheckerOp(this.tcb, node, false, null));
|
|
46411
|
+
}
|
|
45767
46412
|
}
|
|
45768
46413
|
appendChildren(node) {
|
|
45769
46414
|
for (const child of node.children) {
|
|
@@ -45798,8 +46443,7 @@ class Scope {
|
|
|
45798
46443
|
// If there are no directives, then all inputs are unclaimed inputs, so queue an operation
|
|
45799
46444
|
// to add them if needed.
|
|
45800
46445
|
if (node instanceof Element$1) {
|
|
45801
|
-
this.opQueue.push(new TcbUnclaimedInputsOp(this.tcb, this, node, claimedInputs));
|
|
45802
|
-
this.opQueue.push(new TcbDomSchemaCheckerOp(this.tcb, node, /* checkElement */ true, claimedInputs));
|
|
46446
|
+
this.opQueue.push(new TcbUnclaimedInputsOp(this.tcb, this, node.inputs, node, claimedInputs), new TcbDomSchemaCheckerOp(this.tcb, node, /* checkElement */ true, claimedInputs));
|
|
45803
46447
|
}
|
|
45804
46448
|
return;
|
|
45805
46449
|
}
|
|
@@ -45850,7 +46494,7 @@ class Scope {
|
|
|
45850
46494
|
claimedInputs.add(propertyName);
|
|
45851
46495
|
}
|
|
45852
46496
|
}
|
|
45853
|
-
this.opQueue.push(new TcbUnclaimedInputsOp(this.tcb, this, node, claimedInputs));
|
|
46497
|
+
this.opQueue.push(new TcbUnclaimedInputsOp(this.tcb, this, node.inputs, node, claimedInputs));
|
|
45854
46498
|
// If there are no directives which match this element, then it's a "plain" DOM element (or a
|
|
45855
46499
|
// web component), and should be checked against the DOM schema. If any directives match,
|
|
45856
46500
|
// we must assume that the element could be custom (either a component, or a directive like
|
|
@@ -45867,7 +46511,7 @@ class Scope {
|
|
|
45867
46511
|
// If there are no directives, then all outputs are unclaimed outputs, so queue an operation
|
|
45868
46512
|
// to add them if needed.
|
|
45869
46513
|
if (node instanceof Element$1) {
|
|
45870
|
-
this.opQueue.push(new TcbUnclaimedOutputsOp(this.tcb, this, node, claimedOutputs));
|
|
46514
|
+
this.opQueue.push(new TcbUnclaimedOutputsOp(this.tcb, this, node, node.outputs, node.inputs, claimedOutputs));
|
|
45871
46515
|
}
|
|
45872
46516
|
return;
|
|
45873
46517
|
}
|
|
@@ -45884,7 +46528,7 @@ class Scope {
|
|
|
45884
46528
|
claimedOutputs.add(outputProperty);
|
|
45885
46529
|
}
|
|
45886
46530
|
}
|
|
45887
|
-
this.opQueue.push(new TcbUnclaimedOutputsOp(this.tcb, this, node, claimedOutputs));
|
|
46531
|
+
this.opQueue.push(new TcbUnclaimedOutputsOp(this.tcb, this, node, node.outputs, node.inputs, claimedOutputs));
|
|
45888
46532
|
}
|
|
45889
46533
|
}
|
|
45890
46534
|
appendDeepSchemaChecks(nodes) {
|
|
@@ -46535,18 +47179,22 @@ class TypeCheckContextImpl {
|
|
|
46535
47179
|
*
|
|
46536
47180
|
* Implements `TypeCheckContext.addTemplate`.
|
|
46537
47181
|
*/
|
|
46538
|
-
addDirective(ref, binder, schemas, templateContext, isStandalone) {
|
|
47182
|
+
addDirective(ref, binder, schemas, templateContext, hostBindingContext, isStandalone) {
|
|
46539
47183
|
if (!this.host.shouldCheckClass(ref.node)) {
|
|
46540
47184
|
return;
|
|
46541
47185
|
}
|
|
46542
|
-
const
|
|
47186
|
+
const sourceFile = ref.node.getSourceFile();
|
|
47187
|
+
const fileData = this.dataForFile(sourceFile);
|
|
46543
47188
|
const shimData = this.pendingShimForClass(ref.node);
|
|
46544
47189
|
const id = fileData.sourceManager.getTypeCheckId(ref.node);
|
|
46545
47190
|
const templateParsingDiagnostics = [];
|
|
46546
47191
|
if (templateContext !== null && templateContext.parseErrors !== null) {
|
|
46547
47192
|
templateParsingDiagnostics.push(...getTemplateDiagnostics(templateContext.parseErrors, id, templateContext.sourceMapping));
|
|
46548
47193
|
}
|
|
46549
|
-
const boundTarget = binder.bind({
|
|
47194
|
+
const boundTarget = binder.bind({
|
|
47195
|
+
template: templateContext?.nodes,
|
|
47196
|
+
host: hostBindingContext?.node,
|
|
47197
|
+
});
|
|
46550
47198
|
if (this.inlining === InliningMode.InlineOps) {
|
|
46551
47199
|
// Get all of the directives used in the template and record inline type constructors when
|
|
46552
47200
|
// required.
|
|
@@ -46576,6 +47224,7 @@ class TypeCheckContextImpl {
|
|
|
46576
47224
|
template: templateContext?.nodes || null,
|
|
46577
47225
|
boundTarget,
|
|
46578
47226
|
templateParsingDiagnostics,
|
|
47227
|
+
hostElement: hostBindingContext?.node ?? null,
|
|
46579
47228
|
});
|
|
46580
47229
|
const usedPipes = [];
|
|
46581
47230
|
if (templateContext !== null) {
|
|
@@ -46601,6 +47250,12 @@ class TypeCheckContextImpl {
|
|
|
46601
47250
|
if (templateContext !== null) {
|
|
46602
47251
|
fileData.sourceManager.captureTemplateSource(id, templateContext.sourceMapping, templateContext.file);
|
|
46603
47252
|
}
|
|
47253
|
+
if (hostBindingContext !== null) {
|
|
47254
|
+
fileData.sourceManager.captureHostBindingsMapping(id, hostBindingContext.sourceMapping,
|
|
47255
|
+
// We only support host bindings in the same file as the directive
|
|
47256
|
+
// so we can get the source file from here.
|
|
47257
|
+
new ParseSourceFile(sourceFile.text, sourceFile.fileName));
|
|
47258
|
+
}
|
|
46604
47259
|
const meta = {
|
|
46605
47260
|
id,
|
|
46606
47261
|
boundTarget,
|
|
@@ -46904,10 +47559,10 @@ function findClosestLineStartPosition(linesMap, position, low = 0, high = linesM
|
|
|
46904
47559
|
}
|
|
46905
47560
|
|
|
46906
47561
|
/**
|
|
46907
|
-
* Represents the source of
|
|
46908
|
-
*
|
|
47562
|
+
* Represents the source of code processed during type-checking. This information is used when
|
|
47563
|
+
* translating parse offsets in diagnostics back to their original line/column location.
|
|
46909
47564
|
*/
|
|
46910
|
-
class
|
|
47565
|
+
class Source {
|
|
46911
47566
|
mapping;
|
|
46912
47567
|
file;
|
|
46913
47568
|
lineStarts = null;
|
|
@@ -46944,11 +47599,16 @@ class DirectiveSourceManager {
|
|
|
46944
47599
|
* diagnostics produced for TCB code to their source location in the template.
|
|
46945
47600
|
*/
|
|
46946
47601
|
templateSources = new Map();
|
|
47602
|
+
/** Keeps track of type check IDs and the source location of their host bindings. */
|
|
47603
|
+
hostBindingSources = new Map();
|
|
46947
47604
|
getTypeCheckId(node) {
|
|
46948
|
-
return getTypeCheckId(node);
|
|
47605
|
+
return getTypeCheckId$1(node);
|
|
46949
47606
|
}
|
|
46950
47607
|
captureTemplateSource(id, mapping, file) {
|
|
46951
|
-
this.templateSources.set(id, new
|
|
47608
|
+
this.templateSources.set(id, new Source(mapping, file));
|
|
47609
|
+
}
|
|
47610
|
+
captureHostBindingsMapping(id, mapping, file) {
|
|
47611
|
+
this.hostBindingSources.set(id, new Source(mapping, file));
|
|
46952
47612
|
}
|
|
46953
47613
|
getTemplateSourceMapping(id) {
|
|
46954
47614
|
if (!this.templateSources.has(id)) {
|
|
@@ -46956,6 +47616,12 @@ class DirectiveSourceManager {
|
|
|
46956
47616
|
}
|
|
46957
47617
|
return this.templateSources.get(id).mapping;
|
|
46958
47618
|
}
|
|
47619
|
+
getHostBindingsMapping(id) {
|
|
47620
|
+
if (!this.hostBindingSources.has(id)) {
|
|
47621
|
+
throw new Error(`Unexpected unknown type check ID: ${id}`);
|
|
47622
|
+
}
|
|
47623
|
+
return this.hostBindingSources.get(id).mapping;
|
|
47624
|
+
}
|
|
46959
47625
|
toTemplateParseSourceSpan(id, span) {
|
|
46960
47626
|
if (!this.templateSources.has(id)) {
|
|
46961
47627
|
return null;
|
|
@@ -46963,6 +47629,13 @@ class DirectiveSourceManager {
|
|
|
46963
47629
|
const templateSource = this.templateSources.get(id);
|
|
46964
47630
|
return templateSource.toParseSourceSpan(span.start, span.end);
|
|
46965
47631
|
}
|
|
47632
|
+
toHostParseSourceSpan(id, span) {
|
|
47633
|
+
if (!this.hostBindingSources.has(id)) {
|
|
47634
|
+
return null;
|
|
47635
|
+
}
|
|
47636
|
+
const source = this.hostBindingSources.get(id);
|
|
47637
|
+
return source.toParseSourceSpan(span.start, span.end);
|
|
47638
|
+
}
|
|
46966
47639
|
}
|
|
46967
47640
|
|
|
46968
47641
|
/**
|
|
@@ -47727,16 +48400,17 @@ class TemplateTypeCheckerImpl {
|
|
|
47727
48400
|
}
|
|
47728
48401
|
getTemplate(component, optimizeFor) {
|
|
47729
48402
|
const { data } = this.getLatestComponentState(component, optimizeFor);
|
|
47730
|
-
|
|
47731
|
-
|
|
47732
|
-
|
|
47733
|
-
|
|
48403
|
+
return data?.template ?? null;
|
|
48404
|
+
}
|
|
48405
|
+
getHostElement(directive, optimizeFor) {
|
|
48406
|
+
const { data } = this.getLatestComponentState(directive, optimizeFor);
|
|
48407
|
+
return data?.hostElement ?? null;
|
|
47734
48408
|
}
|
|
47735
48409
|
getUsedDirectives(component) {
|
|
47736
|
-
return this.getLatestComponentState(component).data?.boundTarget.getUsedDirectives()
|
|
48410
|
+
return this.getLatestComponentState(component).data?.boundTarget.getUsedDirectives() ?? null;
|
|
47737
48411
|
}
|
|
47738
48412
|
getUsedPipes(component) {
|
|
47739
|
-
return this.getLatestComponentState(component).data?.boundTarget.getUsedPipes()
|
|
48413
|
+
return this.getLatestComponentState(component).data?.boundTarget.getUsedPipes() ?? null;
|
|
47740
48414
|
}
|
|
47741
48415
|
getLatestComponentState(component, optimizeFor = exports.OptimizeFor.SingleFile) {
|
|
47742
48416
|
switch (optimizeFor) {
|
|
@@ -47931,7 +48605,7 @@ class TemplateTypeCheckerImpl {
|
|
|
47931
48605
|
this.isComplete = false;
|
|
47932
48606
|
}
|
|
47933
48607
|
getExpressionTarget(expression, clazz) {
|
|
47934
|
-
return (this.getLatestComponentState(clazz).data?.boundTarget.getExpressionTarget(expression)
|
|
48608
|
+
return (this.getLatestComponentState(clazz).data?.boundTarget.getExpressionTarget(expression) ?? null);
|
|
47935
48609
|
}
|
|
47936
48610
|
makeTemplateDiagnostic(clazz, sourceSpan, category, errorCode, message, relatedInformation) {
|
|
47937
48611
|
const sfPath = absoluteFromSourceFile(clazz.getSourceFile());
|
|
@@ -48607,6 +49281,7 @@ exports.createDirectiveType = createDirectiveType;
|
|
|
48607
49281
|
exports.createFactoryType = createFactoryType;
|
|
48608
49282
|
exports.createForwardRefResolver = createForwardRefResolver;
|
|
48609
49283
|
exports.createHostDirectivesMappingArray = createHostDirectivesMappingArray;
|
|
49284
|
+
exports.createHostElement = createHostElement;
|
|
48610
49285
|
exports.createInjectableType = createInjectableType;
|
|
48611
49286
|
exports.createInjectorType = createInjectorType;
|
|
48612
49287
|
exports.createMayBeForwardRefExpression = createMayBeForwardRefExpression;
|
|
@@ -48622,6 +49297,7 @@ exports.extraReferenceFromTypeQuery = extraReferenceFromTypeQuery;
|
|
|
48622
49297
|
exports.extractDecoratorQueryMetadata = extractDecoratorQueryMetadata;
|
|
48623
49298
|
exports.extractDirectiveMetadata = extractDirectiveMetadata;
|
|
48624
49299
|
exports.extractDirectiveTypeCheckMeta = extractDirectiveTypeCheckMeta;
|
|
49300
|
+
exports.extractHostBindingResources = extractHostBindingResources;
|
|
48625
49301
|
exports.extractMessages = extractMessages;
|
|
48626
49302
|
exports.extractReferencesFromType = extractReferencesFromType;
|
|
48627
49303
|
exports.findAngularDecorator = findAngularDecorator;
|