@angular/core 20.2.0-next.0 → 20.2.0-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/api.d.d.ts +1 -1
- package/chrome_dev_tools_performance.d.d.ts +1 -1
- package/discovery.d.d.ts +1 -1
- package/event_dispatcher.d.d.ts +1 -1
- package/fesm2022/attribute.mjs +1 -1
- package/fesm2022/core.mjs +47 -27
- package/fesm2022/core.mjs.map +1 -1
- package/fesm2022/debug_node.mjs +51 -11
- package/fesm2022/debug_node.mjs.map +1 -1
- package/fesm2022/not_found.mjs +1 -1
- package/fesm2022/primitives/di.mjs +1 -1
- package/fesm2022/primitives/event-dispatch.mjs +1 -1
- package/fesm2022/primitives/signals.mjs +1 -1
- package/fesm2022/resource.mjs +1 -1
- package/fesm2022/root_effect_scheduler.mjs +112 -53
- package/fesm2022/root_effect_scheduler.mjs.map +1 -1
- package/fesm2022/rxjs-interop.mjs +2 -2
- package/fesm2022/signal.mjs +1 -1
- package/fesm2022/testing.mjs +1 -1
- package/fesm2022/untracked.mjs +1 -1
- package/fesm2022/weak_ref.mjs +1 -1
- package/graph.d.d.ts +1 -1
- package/index.d.ts +15 -2
- package/package.json +2 -2
- package/primitives/di/index.d.ts +1 -1
- package/primitives/event-dispatch/index.d.ts +1 -1
- package/primitives/signals/index.d.ts +1 -1
- package/rxjs-interop/index.d.ts +1 -1
- package/schematics/bundles/{apply_import_manager-B0fYYMpr.cjs → apply_import_manager-ceekZYTK.cjs} +3 -3
- package/schematics/bundles/{checker-DLInMAS3.cjs → checker-BVY3FNBy.cjs} +604 -344
- package/schematics/bundles/cleanup-unused-imports.cjs +5 -5
- package/schematics/bundles/{compiler_host-Doj9KVJf.cjs → compiler_host-DRAgYPzr.cjs} +2 -2
- package/schematics/bundles/control-flow-migration.cjs +3 -3
- package/schematics/bundles/document-core.cjs +5 -5
- package/schematics/bundles/imports-CIX-JgAN.cjs +1 -1
- package/schematics/bundles/{index-BmuUS1AB.cjs → index-B7rvD9dh.cjs} +13 -13
- package/schematics/bundles/{index-Bp8sCiq1.cjs → index-DkKydW5H.cjs} +4 -4
- package/schematics/bundles/inject-flags.cjs +5 -5
- package/schematics/bundles/inject-migration.cjs +3 -3
- package/schematics/bundles/leading_space-D9nQ8UQC.cjs +1 -1
- package/schematics/bundles/{migrate_ts_type_references-CmZ0155c.cjs → migrate_ts_type_references-BRFh6uWT.cjs} +5 -441
- package/schematics/bundles/ng_decorators-B5HCqr20.cjs +1 -1
- package/schematics/bundles/nodes-B16H9JUd.cjs +1 -1
- package/schematics/bundles/output-migration.cjs +6 -6
- package/schematics/bundles/{project_paths-D2SJWT7x.cjs → project_paths-zgvnBQD8.cjs} +3 -3
- package/schematics/bundles/project_tsconfig_paths-CDVxT6Ov.cjs +1 -1
- package/schematics/bundles/property_name-BBwFuqMe.cjs +1 -1
- package/schematics/bundles/route-lazy-loading.cjs +3 -3
- package/schematics/bundles/self-closing-tags-migration.cjs +4 -4
- package/schematics/bundles/signal-input-migration.cjs +8 -8
- package/schematics/bundles/signal-queries-migration.cjs +7 -7
- package/schematics/bundles/signals.cjs +7 -7
- package/schematics/bundles/standalone-migration.cjs +4 -4
- package/schematics/bundles/symbol-VPWguRxr.cjs +1 -1
- package/schematics/bundles/test-bed-get.cjs +4 -4
- package/signal.d.d.ts +1 -1
- package/testing/index.d.ts +1 -1
- package/weak_ref.d.d.ts +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
/**
|
|
3
|
-
* @license Angular v20.2.0-next.
|
|
3
|
+
* @license Angular v20.2.0-next.1
|
|
4
4
|
* (c) 2010-2025 Google LLC. https://angular.io/
|
|
5
5
|
* License: MIT
|
|
6
6
|
*/
|
|
@@ -2868,6 +2868,7 @@ class Identifiers {
|
|
|
2868
2868
|
static InputSignalBrandWriteType = { name: 'ɵINPUT_SIGNAL_BRAND_WRITE_TYPE', moduleName: CORE };
|
|
2869
2869
|
static UnwrapDirectiveSignalInputs = { name: 'ɵUnwrapDirectiveSignalInputs', moduleName: CORE };
|
|
2870
2870
|
static unwrapWritableSignal = { name: 'ɵunwrapWritableSignal', moduleName: CORE };
|
|
2871
|
+
static assertType = { name: 'ɵassertType', moduleName: CORE };
|
|
2871
2872
|
}
|
|
2872
2873
|
|
|
2873
2874
|
const DASH_CASE_REGEXP = /-+([a-z0-9])/g;
|
|
@@ -4689,8 +4690,9 @@ let Element$1 = class Element {
|
|
|
4689
4690
|
sourceSpan;
|
|
4690
4691
|
startSourceSpan;
|
|
4691
4692
|
endSourceSpan;
|
|
4693
|
+
isVoid;
|
|
4692
4694
|
i18n;
|
|
4693
|
-
constructor(name, attributes, inputs, outputs, directives, children, references, isSelfClosing, sourceSpan, startSourceSpan, endSourceSpan, i18n) {
|
|
4695
|
+
constructor(name, attributes, inputs, outputs, directives, children, references, isSelfClosing, sourceSpan, startSourceSpan, endSourceSpan, isVoid, i18n) {
|
|
4694
4696
|
this.name = name;
|
|
4695
4697
|
this.attributes = attributes;
|
|
4696
4698
|
this.inputs = inputs;
|
|
@@ -4702,6 +4704,7 @@ let Element$1 = class Element {
|
|
|
4702
4704
|
this.sourceSpan = sourceSpan;
|
|
4703
4705
|
this.startSourceSpan = startSourceSpan;
|
|
4704
4706
|
this.endSourceSpan = endSourceSpan;
|
|
4707
|
+
this.isVoid = isVoid;
|
|
4705
4708
|
this.i18n = i18n;
|
|
4706
4709
|
}
|
|
4707
4710
|
visit(visitor) {
|
|
@@ -13321,7 +13324,8 @@ class Element extends NodeWithI18n {
|
|
|
13321
13324
|
isSelfClosing;
|
|
13322
13325
|
startSourceSpan;
|
|
13323
13326
|
endSourceSpan;
|
|
13324
|
-
|
|
13327
|
+
isVoid;
|
|
13328
|
+
constructor(name, attrs, directives, children, isSelfClosing, sourceSpan, startSourceSpan, endSourceSpan = null, isVoid, i18n) {
|
|
13325
13329
|
super(sourceSpan, i18n);
|
|
13326
13330
|
this.name = name;
|
|
13327
13331
|
this.attrs = attrs;
|
|
@@ -13330,6 +13334,7 @@ class Element extends NodeWithI18n {
|
|
|
13330
13334
|
this.isSelfClosing = isSelfClosing;
|
|
13331
13335
|
this.startSourceSpan = startSourceSpan;
|
|
13332
13336
|
this.endSourceSpan = endSourceSpan;
|
|
13337
|
+
this.isVoid = isVoid;
|
|
13333
13338
|
}
|
|
13334
13339
|
visit(visitor, context) {
|
|
13335
13340
|
return visitor.visitElement(this, context);
|
|
@@ -15667,6 +15672,19 @@ var CharacterReferenceType;
|
|
|
15667
15672
|
CharacterReferenceType["HEX"] = "hexadecimal";
|
|
15668
15673
|
CharacterReferenceType["DEC"] = "decimal";
|
|
15669
15674
|
})(CharacterReferenceType || (CharacterReferenceType = {}));
|
|
15675
|
+
const SUPPORTED_BLOCKS = [
|
|
15676
|
+
'@if',
|
|
15677
|
+
'@else', // Covers `@else if` as well
|
|
15678
|
+
'@for',
|
|
15679
|
+
'@switch',
|
|
15680
|
+
'@case',
|
|
15681
|
+
'@default',
|
|
15682
|
+
'@empty',
|
|
15683
|
+
'@defer',
|
|
15684
|
+
'@placeholder',
|
|
15685
|
+
'@loading',
|
|
15686
|
+
'@error',
|
|
15687
|
+
];
|
|
15670
15688
|
// See https://www.w3.org/TR/html51/syntax.html#writing-html-documents
|
|
15671
15689
|
class _Tokenizer {
|
|
15672
15690
|
_getTagDefinition;
|
|
@@ -15757,10 +15775,10 @@ class _Tokenizer {
|
|
|
15757
15775
|
// don't want to advance in case it's not `@let`.
|
|
15758
15776
|
this._cursor.peek() === $AT &&
|
|
15759
15777
|
!this._inInterpolation &&
|
|
15760
|
-
this.
|
|
15778
|
+
this._isLetStart()) {
|
|
15761
15779
|
this._consumeLetDeclaration(start);
|
|
15762
15780
|
}
|
|
15763
|
-
else if (this._tokenizeBlocks && this.
|
|
15781
|
+
else if (this._tokenizeBlocks && this._isBlockStart()) {
|
|
15764
15782
|
this._consumeBlockStart(start);
|
|
15765
15783
|
}
|
|
15766
15784
|
else if (this._tokenizeBlocks &&
|
|
@@ -15800,6 +15818,7 @@ class _Tokenizer {
|
|
|
15800
15818
|
return this._cursor.getChars(nameCursor).trim();
|
|
15801
15819
|
}
|
|
15802
15820
|
_consumeBlockStart(start) {
|
|
15821
|
+
this._requireCharCode($AT);
|
|
15803
15822
|
this._beginToken(24 /* TokenType.BLOCK_OPEN_START */, start);
|
|
15804
15823
|
const startToken = this._endToken([this._getBlockName()]);
|
|
15805
15824
|
if (this._cursor.peek() === $LPAREN) {
|
|
@@ -15872,6 +15891,7 @@ class _Tokenizer {
|
|
|
15872
15891
|
}
|
|
15873
15892
|
}
|
|
15874
15893
|
_consumeLetDeclaration(start) {
|
|
15894
|
+
this._requireStr('@let');
|
|
15875
15895
|
this._beginToken(29 /* TokenType.LET_START */, start);
|
|
15876
15896
|
// Require at least one white space after the `@let`.
|
|
15877
15897
|
if (isWhitespace(this._cursor.peek())) {
|
|
@@ -16085,6 +16105,27 @@ class _Tokenizer {
|
|
|
16085
16105
|
this._cursor.advance();
|
|
16086
16106
|
return char;
|
|
16087
16107
|
}
|
|
16108
|
+
_peekStr(chars) {
|
|
16109
|
+
const len = chars.length;
|
|
16110
|
+
if (this._cursor.charsLeft() < len) {
|
|
16111
|
+
return false;
|
|
16112
|
+
}
|
|
16113
|
+
const cursor = this._cursor.clone();
|
|
16114
|
+
for (let i = 0; i < len; i++) {
|
|
16115
|
+
if (cursor.peek() !== chars.charCodeAt(i)) {
|
|
16116
|
+
return false;
|
|
16117
|
+
}
|
|
16118
|
+
cursor.advance();
|
|
16119
|
+
}
|
|
16120
|
+
return true;
|
|
16121
|
+
}
|
|
16122
|
+
_isBlockStart() {
|
|
16123
|
+
return (this._cursor.peek() === $AT &&
|
|
16124
|
+
SUPPORTED_BLOCKS.some((blockName) => this._peekStr(blockName)));
|
|
16125
|
+
}
|
|
16126
|
+
_isLetStart() {
|
|
16127
|
+
return this._cursor.peek() === $AT && this._peekStr('@let');
|
|
16128
|
+
}
|
|
16088
16129
|
_consumeEntity(textTokenType) {
|
|
16089
16130
|
this._beginToken(9 /* TokenType.ENCODED_ENTITY */);
|
|
16090
16131
|
const start = this._cursor.clone();
|
|
@@ -16631,7 +16672,7 @@ class _Tokenizer {
|
|
|
16631
16672
|
if (this._tokenizeBlocks &&
|
|
16632
16673
|
!this._inInterpolation &&
|
|
16633
16674
|
!this._isInExpansion() &&
|
|
16634
|
-
(this.
|
|
16675
|
+
(this._isBlockStart() || this._isLetStart() || this._cursor.peek() === $RBRACE)) {
|
|
16635
16676
|
return true;
|
|
16636
16677
|
}
|
|
16637
16678
|
return false;
|
|
@@ -17268,13 +17309,13 @@ class _TreeBuilder {
|
|
|
17268
17309
|
const directives = [];
|
|
17269
17310
|
this._consumeAttributesAndDirectives(attrs, directives);
|
|
17270
17311
|
const fullName = this._getElementFullName(startTagToken, this._getClosestElementLikeParent());
|
|
17312
|
+
const tagDef = this._getTagDefinition(fullName);
|
|
17271
17313
|
let selfClosing = false;
|
|
17272
17314
|
// Note: There could have been a tokenizer error
|
|
17273
17315
|
// so that we don't get a token for the end tag...
|
|
17274
17316
|
if (this._peek.type === 2 /* TokenType.TAG_OPEN_END_VOID */) {
|
|
17275
17317
|
this._advance();
|
|
17276
17318
|
selfClosing = true;
|
|
17277
|
-
const tagDef = this._getTagDefinition(fullName);
|
|
17278
17319
|
if (!(tagDef?.canSelfClose || getNsPrefix(fullName) !== null || tagDef?.isVoid)) {
|
|
17279
17320
|
this.errors.push(TreeError.create(fullName, startTagToken.sourceSpan, `Only void, custom and foreign elements can be self closed "${startTagToken.parts[1]}"`));
|
|
17280
17321
|
}
|
|
@@ -17287,7 +17328,7 @@ class _TreeBuilder {
|
|
|
17287
17328
|
const span = new ParseSourceSpan(startTagToken.sourceSpan.start, end, startTagToken.sourceSpan.fullStart);
|
|
17288
17329
|
// Create a separate `startSpan` because `span` will be modified when there is an `end` span.
|
|
17289
17330
|
const startSpan = new ParseSourceSpan(startTagToken.sourceSpan.start, end, startTagToken.sourceSpan.fullStart);
|
|
17290
|
-
const el = new Element(fullName, attrs, directives, [], selfClosing, span, startSpan, undefined);
|
|
17331
|
+
const el = new Element(fullName, attrs, directives, [], selfClosing, span, startSpan, undefined, tagDef?.isVoid ?? false);
|
|
17291
17332
|
const parent = this._getContainer();
|
|
17292
17333
|
const isClosedByChild = parent !== null && !!this._getTagDefinition(parent)?.isClosedByChild(el.name);
|
|
17293
17334
|
this._pushContainer(el, isClosedByChild);
|
|
@@ -17730,11 +17771,11 @@ class WhitespaceVisitor {
|
|
|
17730
17771
|
if (SKIP_WS_TRIM_TAGS.has(element.name) || hasPreserveWhitespacesAttr(element.attrs)) {
|
|
17731
17772
|
// don't descent into elements where we need to preserve whitespaces
|
|
17732
17773
|
// but still visit all attributes to eliminate one used as a market to preserve WS
|
|
17733
|
-
const newElement = new Element(element.name, visitAllWithSiblings(this, element.attrs), visitAllWithSiblings(this, element.directives), element.children, element.isSelfClosing, element.sourceSpan, element.startSourceSpan, element.endSourceSpan, element.i18n);
|
|
17774
|
+
const newElement = new Element(element.name, visitAllWithSiblings(this, element.attrs), visitAllWithSiblings(this, element.directives), element.children, element.isSelfClosing, element.sourceSpan, element.startSourceSpan, element.endSourceSpan, element.isVoid, element.i18n);
|
|
17734
17775
|
this.originalNodeMap?.set(newElement, element);
|
|
17735
17776
|
return newElement;
|
|
17736
17777
|
}
|
|
17737
|
-
const newElement = new Element(element.name, element.attrs, element.directives, visitAllWithSiblings(this, element.children), element.isSelfClosing, element.sourceSpan, element.startSourceSpan, element.endSourceSpan, element.i18n);
|
|
17778
|
+
const newElement = new Element(element.name, element.attrs, element.directives, visitAllWithSiblings(this, element.children), element.isSelfClosing, element.sourceSpan, element.startSourceSpan, element.endSourceSpan, element.isVoid, element.i18n);
|
|
17738
17779
|
this.originalNodeMap?.set(newElement, element);
|
|
17739
17780
|
return newElement;
|
|
17740
17781
|
}
|
|
@@ -19381,12 +19422,13 @@ class _ParseAST {
|
|
|
19381
19422
|
else {
|
|
19382
19423
|
if (this.isAssignmentOperator(this.next)) {
|
|
19383
19424
|
const operation = this.next.strValue;
|
|
19384
|
-
this.advance();
|
|
19385
19425
|
if (!(this.parseFlags & 1 /* ParseFlags.Action */)) {
|
|
19426
|
+
this.advance();
|
|
19386
19427
|
this.error('Bindings cannot contain assignments');
|
|
19387
19428
|
return new EmptyExpr$1(this.span(start), this.sourceSpan(start));
|
|
19388
19429
|
}
|
|
19389
19430
|
const receiver = new PropertyRead(this.span(start), this.sourceSpan(start), nameSpan, readReceiver, id);
|
|
19431
|
+
this.advance();
|
|
19390
19432
|
const value = this.parseConditional();
|
|
19391
19433
|
return new Binary(this.span(start), this.sourceSpan(start), operation, receiver, value);
|
|
19392
19434
|
}
|
|
@@ -19505,12 +19547,13 @@ class _ParseAST {
|
|
|
19505
19547
|
this.expectCharacter($RBRACKET);
|
|
19506
19548
|
if (this.isAssignmentOperator(this.next)) {
|
|
19507
19549
|
const operation = this.next.strValue;
|
|
19508
|
-
this.advance();
|
|
19509
19550
|
if (isSafe) {
|
|
19551
|
+
this.advance();
|
|
19510
19552
|
this.error("The '?.' operator cannot be used in the assignment");
|
|
19511
19553
|
}
|
|
19512
19554
|
else {
|
|
19513
19555
|
const binaryReceiver = new KeyedRead(this.span(start), this.sourceSpan(start), receiver, key);
|
|
19556
|
+
this.advance();
|
|
19514
19557
|
const value = this.parseConditional();
|
|
19515
19558
|
return new Binary(this.span(start), this.sourceSpan(start), operation, binaryReceiver, value);
|
|
19516
19559
|
}
|
|
@@ -28865,7 +28908,7 @@ class HtmlAstToIvyAst {
|
|
|
28865
28908
|
}
|
|
28866
28909
|
else {
|
|
28867
28910
|
const attrs = this.categorizePropertyAttributes(element.name, parsedProperties, i18nAttrsMeta);
|
|
28868
|
-
parsedElement = new Element$1(element.name, attributes, attrs.bound, boundEvents, directives, children, references, element.isSelfClosing, element.sourceSpan, element.startSourceSpan, element.endSourceSpan, element.i18n);
|
|
28911
|
+
parsedElement = new Element$1(element.name, attributes, attrs.bound, boundEvents, directives, children, references, element.isSelfClosing, element.sourceSpan, element.startSourceSpan, element.endSourceSpan, element.isVoid, element.i18n);
|
|
28869
28912
|
}
|
|
28870
28913
|
if (elementHasInlineTemplate) {
|
|
28871
28914
|
// If this node is an inline-template (e.g. has *ngFor) then we need to create a template
|
|
@@ -29371,7 +29414,7 @@ class NonBindableVisitor {
|
|
|
29371
29414
|
/* inputs */ [],
|
|
29372
29415
|
/* outputs */ [],
|
|
29373
29416
|
/* directives */ [], children,
|
|
29374
|
-
/* references */ [], ast.isSelfClosing, ast.sourceSpan, ast.startSourceSpan, ast.endSourceSpan);
|
|
29417
|
+
/* references */ [], ast.isSelfClosing, ast.sourceSpan, ast.startSourceSpan, ast.endSourceSpan, ast.isVoid);
|
|
29375
29418
|
}
|
|
29376
29419
|
visitComment(comment) {
|
|
29377
29420
|
return null;
|
|
@@ -29412,7 +29455,7 @@ class NonBindableVisitor {
|
|
|
29412
29455
|
/* inputs */ [],
|
|
29413
29456
|
/* outputs */ [],
|
|
29414
29457
|
/* directives */ [], children,
|
|
29415
|
-
/* references */ [], ast.isSelfClosing, ast.sourceSpan, ast.startSourceSpan, ast.endSourceSpan);
|
|
29458
|
+
/* references */ [], ast.isSelfClosing, ast.sourceSpan, ast.startSourceSpan, ast.endSourceSpan, false);
|
|
29416
29459
|
}
|
|
29417
29460
|
visitDirective(directive, context) {
|
|
29418
29461
|
return null;
|
|
@@ -31819,7 +31862,7 @@ class _Visitor {
|
|
|
31819
31862
|
this._init(_VisitorMode.Merge, interpolationConfig);
|
|
31820
31863
|
this._translations = translations;
|
|
31821
31864
|
// Construct a single fake root element
|
|
31822
|
-
const wrapper = new Element('wrapper', [], [], nodes, false, undefined, undefined, undefined);
|
|
31865
|
+
const wrapper = new Element('wrapper', [], [], nodes, false, undefined, undefined, undefined, false);
|
|
31823
31866
|
const translatedNode = wrapper.visit(this, null);
|
|
31824
31867
|
if (this._inI18nBlock) {
|
|
31825
31868
|
this._reportError(nodes[nodes.length - 1], 'Unclosed block');
|
|
@@ -31997,7 +32040,7 @@ class _Visitor {
|
|
|
31997
32040
|
this._inImplicitNode = wasInImplicitNode;
|
|
31998
32041
|
if (this._mode === _VisitorMode.Merge) {
|
|
31999
32042
|
if (node instanceof Element) {
|
|
32000
|
-
return new Element(node.name, this._translateAttributes(node), this._translateDirectives(node), childNodes, node.isSelfClosing, node.sourceSpan, node.startSourceSpan, node.endSourceSpan);
|
|
32043
|
+
return new Element(node.name, this._translateAttributes(node), this._translateDirectives(node), childNodes, node.isSelfClosing, node.sourceSpan, node.startSourceSpan, node.endSourceSpan, node.isVoid);
|
|
32001
32044
|
}
|
|
32002
32045
|
else {
|
|
32003
32046
|
return new Component(node.componentName, node.tagName, node.fullName, this._translateAttributes(node), this._translateDirectives(node), childNodes, node.isSelfClosing, node.sourceSpan, node.startSourceSpan, node.endSourceSpan);
|
|
@@ -32228,7 +32271,7 @@ function isAttrNode(ast) {
|
|
|
32228
32271
|
* @description
|
|
32229
32272
|
* Entry point for all public APIs of the compiler package.
|
|
32230
32273
|
*/
|
|
32231
|
-
new Version('20.2.0-next.
|
|
32274
|
+
new Version('20.2.0-next.1');
|
|
32232
32275
|
|
|
32233
32276
|
//////////////////////////////////////
|
|
32234
32277
|
// THIS FILE HAS GLOBAL SIDE EFFECT //
|
|
@@ -33248,7 +33291,7 @@ class NodeJSPathManipulation {
|
|
|
33248
33291
|
// G3-ESM-MARKER: G3 uses CommonJS, but externally everything in ESM.
|
|
33249
33292
|
// CommonJS/ESM interop for determining the current file name and containing dir.
|
|
33250
33293
|
const isCommonJS = typeof __filename !== 'undefined';
|
|
33251
|
-
const currentFileUrl = isCommonJS ? null : (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('checker-
|
|
33294
|
+
const currentFileUrl = isCommonJS ? null : (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('checker-BVY3FNBy.cjs', document.baseURI).href));
|
|
33252
33295
|
// Note, when this code loads in the browser, `url` may be an empty `{}` due to the Closure shims.
|
|
33253
33296
|
const currentFileName = isCommonJS
|
|
33254
33297
|
? __filename
|
|
@@ -36668,75 +36711,83 @@ exports.PerfPhase = void 0;
|
|
|
36668
36711
|
* Time spent computing template type-checking diagnostics.
|
|
36669
36712
|
*/
|
|
36670
36713
|
PerfPhase[PerfPhase["TtcDiagnostics"] = 14] = "TtcDiagnostics";
|
|
36714
|
+
/**
|
|
36715
|
+
* Time spent computing template type-checking suggestion diagnostics.
|
|
36716
|
+
*/
|
|
36717
|
+
PerfPhase[PerfPhase["TtcSuggestionDiagnostics"] = 15] = "TtcSuggestionDiagnostics";
|
|
36671
36718
|
/**
|
|
36672
36719
|
* Time spent getting a `Symbol` from the `TemplateTypeChecker`.
|
|
36673
36720
|
*/
|
|
36674
|
-
PerfPhase[PerfPhase["TtcSymbol"] =
|
|
36721
|
+
PerfPhase[PerfPhase["TtcSymbol"] = 16] = "TtcSymbol";
|
|
36675
36722
|
/**
|
|
36676
36723
|
* Time spent by the Angular Language Service calculating a "get references" or a renaming
|
|
36677
36724
|
* operation.
|
|
36678
36725
|
*/
|
|
36679
|
-
PerfPhase[PerfPhase["LsReferencesAndRenames"] =
|
|
36726
|
+
PerfPhase[PerfPhase["LsReferencesAndRenames"] = 17] = "LsReferencesAndRenames";
|
|
36680
36727
|
/**
|
|
36681
36728
|
* Time spent by the Angular Language Service calculating a "quick info" operation.
|
|
36682
36729
|
*/
|
|
36683
|
-
PerfPhase[PerfPhase["LsQuickInfo"] =
|
|
36730
|
+
PerfPhase[PerfPhase["LsQuickInfo"] = 18] = "LsQuickInfo";
|
|
36684
36731
|
/**
|
|
36685
36732
|
* Time spent by the Angular Language Service calculating a "get type definition" or "get
|
|
36686
36733
|
* definition" operation.
|
|
36687
36734
|
*/
|
|
36688
|
-
PerfPhase[PerfPhase["LsDefinition"] =
|
|
36735
|
+
PerfPhase[PerfPhase["LsDefinition"] = 19] = "LsDefinition";
|
|
36689
36736
|
/**
|
|
36690
36737
|
* Time spent by the Angular Language Service calculating a "get completions" (AKA autocomplete)
|
|
36691
36738
|
* operation.
|
|
36692
36739
|
*/
|
|
36693
|
-
PerfPhase[PerfPhase["LsCompletions"] =
|
|
36740
|
+
PerfPhase[PerfPhase["LsCompletions"] = 20] = "LsCompletions";
|
|
36694
36741
|
/**
|
|
36695
36742
|
* Time spent by the Angular Language Service calculating a "view template typecheck block"
|
|
36696
36743
|
* operation.
|
|
36697
36744
|
*/
|
|
36698
|
-
PerfPhase[PerfPhase["LsTcb"] =
|
|
36745
|
+
PerfPhase[PerfPhase["LsTcb"] = 21] = "LsTcb";
|
|
36699
36746
|
/**
|
|
36700
36747
|
* Time spent by the Angular Language Service calculating diagnostics.
|
|
36701
36748
|
*/
|
|
36702
|
-
PerfPhase[PerfPhase["LsDiagnostics"] =
|
|
36749
|
+
PerfPhase[PerfPhase["LsDiagnostics"] = 22] = "LsDiagnostics";
|
|
36750
|
+
/**
|
|
36751
|
+
* Time spent by the Angular Language Service calculating suggestion diagnostics.
|
|
36752
|
+
*/
|
|
36753
|
+
PerfPhase[PerfPhase["LsSuggestionDiagnostics"] = 23] = "LsSuggestionDiagnostics";
|
|
36703
36754
|
/**
|
|
36704
36755
|
* Time spent by the Angular Language Service calculating a "get component locations for template"
|
|
36705
36756
|
* operation.
|
|
36706
36757
|
*/
|
|
36707
|
-
PerfPhase[PerfPhase["LsComponentLocations"] =
|
|
36758
|
+
PerfPhase[PerfPhase["LsComponentLocations"] = 24] = "LsComponentLocations";
|
|
36708
36759
|
/**
|
|
36709
36760
|
* Time spent by the Angular Language Service calculating signature help.
|
|
36710
36761
|
*/
|
|
36711
|
-
PerfPhase[PerfPhase["LsSignatureHelp"] =
|
|
36762
|
+
PerfPhase[PerfPhase["LsSignatureHelp"] = 25] = "LsSignatureHelp";
|
|
36712
36763
|
/**
|
|
36713
36764
|
* Time spent by the Angular Language Service calculating outlining spans.
|
|
36714
36765
|
*/
|
|
36715
|
-
PerfPhase[PerfPhase["OutliningSpans"] =
|
|
36766
|
+
PerfPhase[PerfPhase["OutliningSpans"] = 26] = "OutliningSpans";
|
|
36716
36767
|
/**
|
|
36717
36768
|
* Time spent by the Angular Language Service calculating code fixes.
|
|
36718
36769
|
*/
|
|
36719
|
-
PerfPhase[PerfPhase["LsCodeFixes"] =
|
|
36770
|
+
PerfPhase[PerfPhase["LsCodeFixes"] = 27] = "LsCodeFixes";
|
|
36720
36771
|
/**
|
|
36721
36772
|
* Time spent by the Angular Language Service to fix all detected same type errors.
|
|
36722
36773
|
*/
|
|
36723
|
-
PerfPhase[PerfPhase["LsCodeFixesAll"] =
|
|
36774
|
+
PerfPhase[PerfPhase["LsCodeFixesAll"] = 28] = "LsCodeFixesAll";
|
|
36724
36775
|
/**
|
|
36725
36776
|
* Time spent computing possible Angular refactorings.
|
|
36726
36777
|
*/
|
|
36727
|
-
PerfPhase[PerfPhase["LSComputeApplicableRefactorings"] =
|
|
36778
|
+
PerfPhase[PerfPhase["LSComputeApplicableRefactorings"] = 29] = "LSComputeApplicableRefactorings";
|
|
36728
36779
|
/**
|
|
36729
36780
|
* Time spent computing changes for applying a given refactoring.
|
|
36730
36781
|
*/
|
|
36731
|
-
PerfPhase[PerfPhase["LSApplyRefactoring"] =
|
|
36782
|
+
PerfPhase[PerfPhase["LSApplyRefactoring"] = 30] = "LSApplyRefactoring";
|
|
36732
36783
|
/**
|
|
36733
36784
|
* Time spent by the Angular Language Service calculating semantic classifications.
|
|
36734
36785
|
*/
|
|
36735
|
-
PerfPhase[PerfPhase["LSSemanticClassification"] =
|
|
36786
|
+
PerfPhase[PerfPhase["LSSemanticClassification"] = 31] = "LSSemanticClassification";
|
|
36736
36787
|
/**
|
|
36737
36788
|
* Tracks the number of `PerfPhase`s, and must appear at the end of the list.
|
|
36738
36789
|
*/
|
|
36739
|
-
PerfPhase[PerfPhase["LAST"] =
|
|
36790
|
+
PerfPhase[PerfPhase["LAST"] = 32] = "LAST";
|
|
36740
36791
|
})(exports.PerfPhase || (exports.PerfPhase = {}));
|
|
36741
36792
|
/**
|
|
36742
36793
|
* Represents some occurrence during compilation, and is tracked with a counter.
|
|
@@ -40275,6 +40326,314 @@ function extractHostBindingResources(nodes) {
|
|
|
40275
40326
|
return result;
|
|
40276
40327
|
}
|
|
40277
40328
|
|
|
40329
|
+
const parseSpanComment = /^(\d+),(\d+)$/;
|
|
40330
|
+
/**
|
|
40331
|
+
* Reads the trailing comments and finds the first match which is a span comment (i.e. 4,10) on a
|
|
40332
|
+
* node and returns it as an `AbsoluteSourceSpan`.
|
|
40333
|
+
*
|
|
40334
|
+
* Will return `null` if no trailing comments on the node match the expected form of a source span.
|
|
40335
|
+
*/
|
|
40336
|
+
function readSpanComment(node, sourceFile = node.getSourceFile()) {
|
|
40337
|
+
return (ts.forEachTrailingCommentRange(sourceFile.text, node.getEnd(), (pos, end, kind) => {
|
|
40338
|
+
if (kind !== ts.SyntaxKind.MultiLineCommentTrivia) {
|
|
40339
|
+
return null;
|
|
40340
|
+
}
|
|
40341
|
+
const commentText = sourceFile.text.substring(pos + 2, end - 2);
|
|
40342
|
+
const match = commentText.match(parseSpanComment);
|
|
40343
|
+
if (match === null) {
|
|
40344
|
+
return null;
|
|
40345
|
+
}
|
|
40346
|
+
return new AbsoluteSourceSpan(+match[1], +match[2]);
|
|
40347
|
+
}) || null);
|
|
40348
|
+
}
|
|
40349
|
+
/** Used to identify what type the comment is. */
|
|
40350
|
+
var CommentTriviaType;
|
|
40351
|
+
(function (CommentTriviaType) {
|
|
40352
|
+
CommentTriviaType["DIAGNOSTIC"] = "D";
|
|
40353
|
+
CommentTriviaType["EXPRESSION_TYPE_IDENTIFIER"] = "T";
|
|
40354
|
+
})(CommentTriviaType || (CommentTriviaType = {}));
|
|
40355
|
+
/** Identifies what the TCB expression is for (for example, a directive declaration). */
|
|
40356
|
+
var ExpressionIdentifier;
|
|
40357
|
+
(function (ExpressionIdentifier) {
|
|
40358
|
+
ExpressionIdentifier["DIRECTIVE"] = "DIR";
|
|
40359
|
+
ExpressionIdentifier["COMPONENT_COMPLETION"] = "COMPCOMP";
|
|
40360
|
+
ExpressionIdentifier["EVENT_PARAMETER"] = "EP";
|
|
40361
|
+
ExpressionIdentifier["VARIABLE_AS_EXPRESSION"] = "VAE";
|
|
40362
|
+
})(ExpressionIdentifier || (ExpressionIdentifier = {}));
|
|
40363
|
+
/** Tags the node with the given expression identifier. */
|
|
40364
|
+
function addExpressionIdentifier(node, identifier) {
|
|
40365
|
+
ts.addSyntheticTrailingComment(node, ts.SyntaxKind.MultiLineCommentTrivia, `${CommentTriviaType.EXPRESSION_TYPE_IDENTIFIER}:${identifier}`,
|
|
40366
|
+
/* hasTrailingNewLine */ false);
|
|
40367
|
+
}
|
|
40368
|
+
const IGNORE_FOR_DIAGNOSTICS_MARKER = `${CommentTriviaType.DIAGNOSTIC}:ignore`;
|
|
40369
|
+
/**
|
|
40370
|
+
* Tag the `ts.Node` with an indication that any errors arising from the evaluation of the node
|
|
40371
|
+
* should be ignored.
|
|
40372
|
+
*/
|
|
40373
|
+
function markIgnoreDiagnostics(node) {
|
|
40374
|
+
ts.addSyntheticTrailingComment(node, ts.SyntaxKind.MultiLineCommentTrivia, IGNORE_FOR_DIAGNOSTICS_MARKER,
|
|
40375
|
+
/* hasTrailingNewLine */ false);
|
|
40376
|
+
}
|
|
40377
|
+
/** Returns true if the node has a marker that indicates diagnostics errors should be ignored. */
|
|
40378
|
+
function hasIgnoreForDiagnosticsMarker(node, sourceFile) {
|
|
40379
|
+
return (ts.forEachTrailingCommentRange(sourceFile.text, node.getEnd(), (pos, end, kind) => {
|
|
40380
|
+
if (kind !== ts.SyntaxKind.MultiLineCommentTrivia) {
|
|
40381
|
+
return null;
|
|
40382
|
+
}
|
|
40383
|
+
const commentText = sourceFile.text.substring(pos + 2, end - 2);
|
|
40384
|
+
return commentText === IGNORE_FOR_DIAGNOSTICS_MARKER;
|
|
40385
|
+
}) === true);
|
|
40386
|
+
}
|
|
40387
|
+
function makeRecursiveVisitor(visitor) {
|
|
40388
|
+
function recursiveVisitor(node) {
|
|
40389
|
+
const res = visitor(node);
|
|
40390
|
+
return res !== null ? res : node.forEachChild(recursiveVisitor);
|
|
40391
|
+
}
|
|
40392
|
+
return recursiveVisitor;
|
|
40393
|
+
}
|
|
40394
|
+
function getSpanFromOptions(opts) {
|
|
40395
|
+
let withSpan = null;
|
|
40396
|
+
if (opts.withSpan !== undefined) {
|
|
40397
|
+
if (opts.withSpan instanceof AbsoluteSourceSpan) {
|
|
40398
|
+
withSpan = opts.withSpan;
|
|
40399
|
+
}
|
|
40400
|
+
else {
|
|
40401
|
+
withSpan = { start: opts.withSpan.start.offset, end: opts.withSpan.end.offset };
|
|
40402
|
+
}
|
|
40403
|
+
}
|
|
40404
|
+
return withSpan;
|
|
40405
|
+
}
|
|
40406
|
+
/**
|
|
40407
|
+
* Given a `ts.Node` with finds the first node whose matching the criteria specified
|
|
40408
|
+
* by the `FindOptions`.
|
|
40409
|
+
*
|
|
40410
|
+
* Returns `null` when no `ts.Node` matches the given conditions.
|
|
40411
|
+
*/
|
|
40412
|
+
function findFirstMatchingNode(tcb, opts) {
|
|
40413
|
+
const withSpan = getSpanFromOptions(opts);
|
|
40414
|
+
const withExpressionIdentifier = opts.withExpressionIdentifier;
|
|
40415
|
+
const sf = tcb.getSourceFile();
|
|
40416
|
+
const visitor = makeRecursiveVisitor((node) => {
|
|
40417
|
+
if (!opts.filter(node)) {
|
|
40418
|
+
return null;
|
|
40419
|
+
}
|
|
40420
|
+
if (withSpan !== null) {
|
|
40421
|
+
const comment = readSpanComment(node, sf);
|
|
40422
|
+
if (comment === null || withSpan.start !== comment.start || withSpan.end !== comment.end) {
|
|
40423
|
+
return null;
|
|
40424
|
+
}
|
|
40425
|
+
}
|
|
40426
|
+
if (withExpressionIdentifier !== undefined &&
|
|
40427
|
+
!hasExpressionIdentifier(sf, node, withExpressionIdentifier)) {
|
|
40428
|
+
return null;
|
|
40429
|
+
}
|
|
40430
|
+
return node;
|
|
40431
|
+
});
|
|
40432
|
+
return tcb.forEachChild(visitor) ?? null;
|
|
40433
|
+
}
|
|
40434
|
+
/**
|
|
40435
|
+
* Given a `ts.Node` with source span comments, finds the first node whose source span comment
|
|
40436
|
+
* matches the given `sourceSpan`. Additionally, the `filter` function allows matching only
|
|
40437
|
+
* `ts.Nodes` of a given type, which provides the ability to select only matches of a given type
|
|
40438
|
+
* when there may be more than one.
|
|
40439
|
+
*
|
|
40440
|
+
* Returns `null` when no `ts.Node` matches the given conditions.
|
|
40441
|
+
*/
|
|
40442
|
+
function findAllMatchingNodes(tcb, opts) {
|
|
40443
|
+
const withSpan = getSpanFromOptions(opts);
|
|
40444
|
+
const withExpressionIdentifier = opts.withExpressionIdentifier;
|
|
40445
|
+
const results = [];
|
|
40446
|
+
const stack = [tcb];
|
|
40447
|
+
const sf = tcb.getSourceFile();
|
|
40448
|
+
while (stack.length > 0) {
|
|
40449
|
+
const node = stack.pop();
|
|
40450
|
+
if (!opts.filter(node)) {
|
|
40451
|
+
stack.push(...node.getChildren());
|
|
40452
|
+
continue;
|
|
40453
|
+
}
|
|
40454
|
+
if (withSpan !== null) {
|
|
40455
|
+
const comment = readSpanComment(node, sf);
|
|
40456
|
+
if (comment === null || withSpan.start !== comment.start || withSpan.end !== comment.end) {
|
|
40457
|
+
stack.push(...node.getChildren());
|
|
40458
|
+
continue;
|
|
40459
|
+
}
|
|
40460
|
+
}
|
|
40461
|
+
if (withExpressionIdentifier !== undefined &&
|
|
40462
|
+
!hasExpressionIdentifier(sf, node, withExpressionIdentifier)) {
|
|
40463
|
+
continue;
|
|
40464
|
+
}
|
|
40465
|
+
results.push(node);
|
|
40466
|
+
}
|
|
40467
|
+
return results;
|
|
40468
|
+
}
|
|
40469
|
+
function hasExpressionIdentifier(sourceFile, node, identifier) {
|
|
40470
|
+
return (ts.forEachTrailingCommentRange(sourceFile.text, node.getEnd(), (pos, end, kind) => {
|
|
40471
|
+
if (kind !== ts.SyntaxKind.MultiLineCommentTrivia) {
|
|
40472
|
+
return false;
|
|
40473
|
+
}
|
|
40474
|
+
const commentText = sourceFile.text.substring(pos + 2, end - 2);
|
|
40475
|
+
return commentText === `${CommentTriviaType.EXPRESSION_TYPE_IDENTIFIER}:${identifier}`;
|
|
40476
|
+
}) || false);
|
|
40477
|
+
}
|
|
40478
|
+
|
|
40479
|
+
/**
|
|
40480
|
+
* A `Set` of `ts.SyntaxKind`s of `ts.Expression` which are safe to wrap in a `ts.AsExpression`
|
|
40481
|
+
* without needing to be wrapped in parentheses.
|
|
40482
|
+
*
|
|
40483
|
+
* For example, `foo.bar()` is a `ts.CallExpression`, and can be safely cast to `any` with
|
|
40484
|
+
* `foo.bar() as any`. however, `foo !== bar` is a `ts.BinaryExpression`, and attempting to cast
|
|
40485
|
+
* without the parentheses yields the expression `foo !== bar as any`. This is semantically
|
|
40486
|
+
* equivalent to `foo !== (bar as any)`, which is not what was intended. Thus,
|
|
40487
|
+
* `ts.BinaryExpression`s need to be wrapped in parentheses before casting.
|
|
40488
|
+
*/
|
|
40489
|
+
//
|
|
40490
|
+
let SAFE_TO_CAST_WITHOUT_PARENS = null;
|
|
40491
|
+
function tsCastToAny(expr) {
|
|
40492
|
+
if (SAFE_TO_CAST_WITHOUT_PARENS === null) {
|
|
40493
|
+
SAFE_TO_CAST_WITHOUT_PARENS = new Set([
|
|
40494
|
+
// Expressions which are already parenthesized can be cast without further wrapping.
|
|
40495
|
+
ts.SyntaxKind.ParenthesizedExpression,
|
|
40496
|
+
// Expressions which form a single lexical unit leave no room for precedence issues with the cast.
|
|
40497
|
+
ts.SyntaxKind.Identifier,
|
|
40498
|
+
ts.SyntaxKind.CallExpression,
|
|
40499
|
+
ts.SyntaxKind.NonNullExpression,
|
|
40500
|
+
ts.SyntaxKind.ElementAccessExpression,
|
|
40501
|
+
ts.SyntaxKind.PropertyAccessExpression,
|
|
40502
|
+
ts.SyntaxKind.ArrayLiteralExpression,
|
|
40503
|
+
ts.SyntaxKind.ObjectLiteralExpression,
|
|
40504
|
+
// The same goes for various literals.
|
|
40505
|
+
ts.SyntaxKind.StringLiteral,
|
|
40506
|
+
ts.SyntaxKind.NumericLiteral,
|
|
40507
|
+
ts.SyntaxKind.TrueKeyword,
|
|
40508
|
+
ts.SyntaxKind.FalseKeyword,
|
|
40509
|
+
ts.SyntaxKind.NullKeyword,
|
|
40510
|
+
ts.SyntaxKind.UndefinedKeyword,
|
|
40511
|
+
]);
|
|
40512
|
+
}
|
|
40513
|
+
// Wrap `expr` in parentheses if needed (see `SAFE_TO_CAST_WITHOUT_PARENS` above).
|
|
40514
|
+
if (!SAFE_TO_CAST_WITHOUT_PARENS.has(expr.kind)) {
|
|
40515
|
+
expr = ts.factory.createParenthesizedExpression(expr);
|
|
40516
|
+
}
|
|
40517
|
+
// The outer expression is always wrapped in parentheses.
|
|
40518
|
+
return ts.factory.createParenthesizedExpression(ts.factory.createAsExpression(expr, ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword)));
|
|
40519
|
+
}
|
|
40520
|
+
/**
|
|
40521
|
+
* Create an expression which instantiates an element by its HTML tagName.
|
|
40522
|
+
*
|
|
40523
|
+
* Thanks to narrowing of `document.createElement()`, this expression will have its type inferred
|
|
40524
|
+
* based on the tag name, including for custom elements that have appropriate .d.ts definitions.
|
|
40525
|
+
*/
|
|
40526
|
+
function tsCreateElement(...tagNames) {
|
|
40527
|
+
const createElement = ts.factory.createPropertyAccessExpression(
|
|
40528
|
+
/* expression */ ts.factory.createIdentifier('document'), 'createElement');
|
|
40529
|
+
let arg;
|
|
40530
|
+
if (tagNames.length === 1) {
|
|
40531
|
+
// If there's only one tag name, we can pass it in directly.
|
|
40532
|
+
arg = ts.factory.createStringLiteral(tagNames[0]);
|
|
40533
|
+
}
|
|
40534
|
+
else {
|
|
40535
|
+
// If there's more than one name, we have to generate a union of all the tag names. To do so,
|
|
40536
|
+
// create an expression in the form of `null! as 'tag-1' | 'tag-2' | 'tag-3'`. This allows
|
|
40537
|
+
// TypeScript to infer the type as a union of the differnet tags.
|
|
40538
|
+
const assertedNullExpression = ts.factory.createNonNullExpression(ts.factory.createNull());
|
|
40539
|
+
const type = ts.factory.createUnionTypeNode(tagNames.map((tag) => ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral(tag))));
|
|
40540
|
+
arg = ts.factory.createAsExpression(assertedNullExpression, type);
|
|
40541
|
+
}
|
|
40542
|
+
return ts.factory.createCallExpression(
|
|
40543
|
+
/* expression */ createElement,
|
|
40544
|
+
/* typeArguments */ undefined,
|
|
40545
|
+
/* argumentsArray */ [arg]);
|
|
40546
|
+
}
|
|
40547
|
+
/**
|
|
40548
|
+
* Create a `ts.VariableStatement` which declares a variable without explicit initialization.
|
|
40549
|
+
*
|
|
40550
|
+
* The initializer `null!` is used to bypass strict variable initialization checks.
|
|
40551
|
+
*
|
|
40552
|
+
* Unlike with `tsCreateVariable`, the type of the variable is explicitly specified.
|
|
40553
|
+
*/
|
|
40554
|
+
function tsDeclareVariable(id, type) {
|
|
40555
|
+
// When we create a variable like `var _t1: boolean = null!`, TypeScript actually infers `_t1`
|
|
40556
|
+
// to be `never`, instead of a `boolean`. To work around it, we cast the value
|
|
40557
|
+
// in the initializer, e.g. `var _t1 = null! as boolean;`.
|
|
40558
|
+
addExpressionIdentifier(type, ExpressionIdentifier.VARIABLE_AS_EXPRESSION);
|
|
40559
|
+
const initializer = ts.factory.createAsExpression(ts.factory.createNonNullExpression(ts.factory.createNull()), type);
|
|
40560
|
+
const decl = ts.factory.createVariableDeclaration(
|
|
40561
|
+
/* name */ id,
|
|
40562
|
+
/* exclamationToken */ undefined,
|
|
40563
|
+
/* type */ undefined,
|
|
40564
|
+
/* initializer */ initializer);
|
|
40565
|
+
return ts.factory.createVariableStatement(
|
|
40566
|
+
/* modifiers */ undefined,
|
|
40567
|
+
/* declarationList */ [decl]);
|
|
40568
|
+
}
|
|
40569
|
+
/**
|
|
40570
|
+
* Creates a `ts.TypeQueryNode` for a coerced input.
|
|
40571
|
+
*
|
|
40572
|
+
* For example: `typeof MatInput.ngAcceptInputType_value`, where MatInput is `typeName` and `value`
|
|
40573
|
+
* is the `coercedInputName`.
|
|
40574
|
+
*
|
|
40575
|
+
* @param typeName The `EntityName` of the Directive where the static coerced input is defined.
|
|
40576
|
+
* @param coercedInputName The field name of the coerced input.
|
|
40577
|
+
*/
|
|
40578
|
+
function tsCreateTypeQueryForCoercedInput(typeName, coercedInputName) {
|
|
40579
|
+
return ts.factory.createTypeQueryNode(ts.factory.createQualifiedName(typeName, `ngAcceptInputType_${coercedInputName}`));
|
|
40580
|
+
}
|
|
40581
|
+
/**
|
|
40582
|
+
* Create a `ts.VariableStatement` that initializes a variable with a given expression.
|
|
40583
|
+
*
|
|
40584
|
+
* Unlike with `tsDeclareVariable`, the type of the variable is inferred from the initializer
|
|
40585
|
+
* expression.
|
|
40586
|
+
*/
|
|
40587
|
+
function tsCreateVariable(id, initializer, flags = null) {
|
|
40588
|
+
const decl = ts.factory.createVariableDeclaration(
|
|
40589
|
+
/* name */ id,
|
|
40590
|
+
/* exclamationToken */ undefined,
|
|
40591
|
+
/* type */ undefined,
|
|
40592
|
+
/* initializer */ initializer);
|
|
40593
|
+
return ts.factory.createVariableStatement(
|
|
40594
|
+
/* modifiers */ undefined,
|
|
40595
|
+
/* declarationList */ flags === null
|
|
40596
|
+
? [decl]
|
|
40597
|
+
: ts.factory.createVariableDeclarationList([decl], flags));
|
|
40598
|
+
}
|
|
40599
|
+
/**
|
|
40600
|
+
* Construct a `ts.CallExpression` that calls a method on a receiver.
|
|
40601
|
+
*/
|
|
40602
|
+
function tsCallMethod(receiver, methodName, args = []) {
|
|
40603
|
+
const methodAccess = ts.factory.createPropertyAccessExpression(receiver, methodName);
|
|
40604
|
+
return ts.factory.createCallExpression(
|
|
40605
|
+
/* expression */ methodAccess,
|
|
40606
|
+
/* typeArguments */ undefined,
|
|
40607
|
+
/* argumentsArray */ args);
|
|
40608
|
+
}
|
|
40609
|
+
function isAccessExpression(node) {
|
|
40610
|
+
return ts.isPropertyAccessExpression(node) || ts.isElementAccessExpression(node);
|
|
40611
|
+
}
|
|
40612
|
+
/**
|
|
40613
|
+
* Creates a TypeScript node representing a numeric value.
|
|
40614
|
+
*/
|
|
40615
|
+
function tsNumericExpression(value) {
|
|
40616
|
+
// As of TypeScript 5.3 negative numbers are represented as `prefixUnaryOperator` and passing a
|
|
40617
|
+
// negative number (even as a string) into `createNumericLiteral` will result in an error.
|
|
40618
|
+
if (value < 0) {
|
|
40619
|
+
const operand = ts.factory.createNumericLiteral(Math.abs(value));
|
|
40620
|
+
return ts.factory.createPrefixUnaryExpression(ts.SyntaxKind.MinusToken, operand);
|
|
40621
|
+
}
|
|
40622
|
+
return ts.factory.createNumericLiteral(value);
|
|
40623
|
+
}
|
|
40624
|
+
/**
|
|
40625
|
+
* Check if a node represents a directive declaration in a TypeCheck Block.
|
|
40626
|
+
* Directive declarations can be either:
|
|
40627
|
+
* - var _t1: TestDir /*T:D*\/ = null! as TestDir;
|
|
40628
|
+
* - var _t1 /*T:D*\/ = _ctor1({});
|
|
40629
|
+
*/
|
|
40630
|
+
function isDirectiveDeclaration(node) {
|
|
40631
|
+
const sourceFile = node.getSourceFile();
|
|
40632
|
+
return ((ts.isTypeNode(node) || ts.isIdentifier(node)) &&
|
|
40633
|
+
ts.isVariableDeclaration(node.parent) &&
|
|
40634
|
+
hasExpressionIdentifier(sourceFile, node, ExpressionIdentifier.DIRECTIVE));
|
|
40635
|
+
}
|
|
40636
|
+
|
|
40278
40637
|
const NgOriginalFile = Symbol('NgOriginalFile');
|
|
40279
40638
|
exports.UpdateMode = void 0;
|
|
40280
40639
|
(function (UpdateMode) {
|
|
@@ -40463,12 +40822,13 @@ exports.SymbolKind = void 0;
|
|
|
40463
40822
|
|
|
40464
40823
|
/**
|
|
40465
40824
|
* Constructs a `ts.Diagnostic` for a given `ParseSourceSpan` within a template.
|
|
40825
|
+
*
|
|
40826
|
+
* @param deprecatedDiagInfo Optional information about deprecation and related messages.
|
|
40466
40827
|
*/
|
|
40467
|
-
function makeTemplateDiagnostic(id, mapping, span, category, code, messageText, relatedMessages) {
|
|
40828
|
+
function makeTemplateDiagnostic(id, mapping, span, category, code, messageText, relatedMessages, deprecatedDiagInfo) {
|
|
40468
40829
|
if (mapping.type === 'direct') {
|
|
40469
|
-
let relatedInformation =
|
|
40830
|
+
let relatedInformation = [];
|
|
40470
40831
|
if (relatedMessages !== undefined) {
|
|
40471
|
-
relatedInformation = [];
|
|
40472
40832
|
for (const relatedMessage of relatedMessages) {
|
|
40473
40833
|
relatedInformation.push({
|
|
40474
40834
|
category: ts.DiagnosticCategory.Message,
|
|
@@ -40480,6 +40840,9 @@ function makeTemplateDiagnostic(id, mapping, span, category, code, messageText,
|
|
|
40480
40840
|
});
|
|
40481
40841
|
}
|
|
40482
40842
|
}
|
|
40843
|
+
if (deprecatedDiagInfo !== undefined) {
|
|
40844
|
+
relatedInformation.push(...(deprecatedDiagInfo.relatedMessages ?? []));
|
|
40845
|
+
}
|
|
40483
40846
|
// For direct mappings, the error is shown inline as ngtsc was able to pinpoint a string
|
|
40484
40847
|
// constant within the `@Component` decorator for the template. This allows us to map the error
|
|
40485
40848
|
// directly into the bytes of the source file.
|
|
@@ -40494,6 +40857,7 @@ function makeTemplateDiagnostic(id, mapping, span, category, code, messageText,
|
|
|
40494
40857
|
start: span.start.offset,
|
|
40495
40858
|
length: span.end.offset - span.start.offset,
|
|
40496
40859
|
relatedInformation,
|
|
40860
|
+
reportsDeprecated: deprecatedDiagInfo?.reportsDeprecated,
|
|
40497
40861
|
};
|
|
40498
40862
|
}
|
|
40499
40863
|
else if (mapping.type === 'indirect' || mapping.type === 'external') {
|
|
@@ -40538,6 +40902,7 @@ function makeTemplateDiagnostic(id, mapping, span, category, code, messageText,
|
|
|
40538
40902
|
start: mapping.node.getStart(),
|
|
40539
40903
|
length: mapping.node.getEnd() - mapping.node.getStart(),
|
|
40540
40904
|
relatedInformation,
|
|
40905
|
+
reportsDeprecated: deprecatedDiagInfo?.reportsDeprecated,
|
|
40541
40906
|
};
|
|
40542
40907
|
}
|
|
40543
40908
|
let typeForMessage;
|
|
@@ -40553,6 +40918,9 @@ function makeTemplateDiagnostic(id, mapping, span, category, code, messageText,
|
|
|
40553
40918
|
else {
|
|
40554
40919
|
typeForMessage = 'Error';
|
|
40555
40920
|
}
|
|
40921
|
+
if (deprecatedDiagInfo !== undefined) {
|
|
40922
|
+
relatedInformation.push(...(deprecatedDiagInfo.relatedMessages ?? []));
|
|
40923
|
+
}
|
|
40556
40924
|
relatedInformation.push({
|
|
40557
40925
|
category: ts.DiagnosticCategory.Message,
|
|
40558
40926
|
code: 0,
|
|
@@ -40575,6 +40943,7 @@ function makeTemplateDiagnostic(id, mapping, span, category, code, messageText,
|
|
|
40575
40943
|
length: span.end.offset - span.start.offset,
|
|
40576
40944
|
// Show a secondary message indicating the component whose template contains the error.
|
|
40577
40945
|
relatedInformation,
|
|
40946
|
+
reportsDeprecated: deprecatedDiagInfo?.reportsDeprecated,
|
|
40578
40947
|
};
|
|
40579
40948
|
}
|
|
40580
40949
|
else {
|
|
@@ -40607,156 +40976,6 @@ function getTypeCheckId$1(clazz) {
|
|
|
40607
40976
|
return sf[TYPE_CHECK_ID_MAP].get(clazz);
|
|
40608
40977
|
}
|
|
40609
40978
|
|
|
40610
|
-
const parseSpanComment = /^(\d+),(\d+)$/;
|
|
40611
|
-
/**
|
|
40612
|
-
* Reads the trailing comments and finds the first match which is a span comment (i.e. 4,10) on a
|
|
40613
|
-
* node and returns it as an `AbsoluteSourceSpan`.
|
|
40614
|
-
*
|
|
40615
|
-
* Will return `null` if no trailing comments on the node match the expected form of a source span.
|
|
40616
|
-
*/
|
|
40617
|
-
function readSpanComment(node, sourceFile = node.getSourceFile()) {
|
|
40618
|
-
return (ts.forEachTrailingCommentRange(sourceFile.text, node.getEnd(), (pos, end, kind) => {
|
|
40619
|
-
if (kind !== ts.SyntaxKind.MultiLineCommentTrivia) {
|
|
40620
|
-
return null;
|
|
40621
|
-
}
|
|
40622
|
-
const commentText = sourceFile.text.substring(pos + 2, end - 2);
|
|
40623
|
-
const match = commentText.match(parseSpanComment);
|
|
40624
|
-
if (match === null) {
|
|
40625
|
-
return null;
|
|
40626
|
-
}
|
|
40627
|
-
return new AbsoluteSourceSpan(+match[1], +match[2]);
|
|
40628
|
-
}) || null);
|
|
40629
|
-
}
|
|
40630
|
-
/** Used to identify what type the comment is. */
|
|
40631
|
-
var CommentTriviaType;
|
|
40632
|
-
(function (CommentTriviaType) {
|
|
40633
|
-
CommentTriviaType["DIAGNOSTIC"] = "D";
|
|
40634
|
-
CommentTriviaType["EXPRESSION_TYPE_IDENTIFIER"] = "T";
|
|
40635
|
-
})(CommentTriviaType || (CommentTriviaType = {}));
|
|
40636
|
-
/** Identifies what the TCB expression is for (for example, a directive declaration). */
|
|
40637
|
-
var ExpressionIdentifier;
|
|
40638
|
-
(function (ExpressionIdentifier) {
|
|
40639
|
-
ExpressionIdentifier["DIRECTIVE"] = "DIR";
|
|
40640
|
-
ExpressionIdentifier["COMPONENT_COMPLETION"] = "COMPCOMP";
|
|
40641
|
-
ExpressionIdentifier["EVENT_PARAMETER"] = "EP";
|
|
40642
|
-
ExpressionIdentifier["VARIABLE_AS_EXPRESSION"] = "VAE";
|
|
40643
|
-
})(ExpressionIdentifier || (ExpressionIdentifier = {}));
|
|
40644
|
-
/** Tags the node with the given expression identifier. */
|
|
40645
|
-
function addExpressionIdentifier(node, identifier) {
|
|
40646
|
-
ts.addSyntheticTrailingComment(node, ts.SyntaxKind.MultiLineCommentTrivia, `${CommentTriviaType.EXPRESSION_TYPE_IDENTIFIER}:${identifier}`,
|
|
40647
|
-
/* hasTrailingNewLine */ false);
|
|
40648
|
-
}
|
|
40649
|
-
const IGNORE_FOR_DIAGNOSTICS_MARKER = `${CommentTriviaType.DIAGNOSTIC}:ignore`;
|
|
40650
|
-
/**
|
|
40651
|
-
* Tag the `ts.Node` with an indication that any errors arising from the evaluation of the node
|
|
40652
|
-
* should be ignored.
|
|
40653
|
-
*/
|
|
40654
|
-
function markIgnoreDiagnostics(node) {
|
|
40655
|
-
ts.addSyntheticTrailingComment(node, ts.SyntaxKind.MultiLineCommentTrivia, IGNORE_FOR_DIAGNOSTICS_MARKER,
|
|
40656
|
-
/* hasTrailingNewLine */ false);
|
|
40657
|
-
}
|
|
40658
|
-
/** Returns true if the node has a marker that indicates diagnostics errors should be ignored. */
|
|
40659
|
-
function hasIgnoreForDiagnosticsMarker(node, sourceFile) {
|
|
40660
|
-
return (ts.forEachTrailingCommentRange(sourceFile.text, node.getEnd(), (pos, end, kind) => {
|
|
40661
|
-
if (kind !== ts.SyntaxKind.MultiLineCommentTrivia) {
|
|
40662
|
-
return null;
|
|
40663
|
-
}
|
|
40664
|
-
const commentText = sourceFile.text.substring(pos + 2, end - 2);
|
|
40665
|
-
return commentText === IGNORE_FOR_DIAGNOSTICS_MARKER;
|
|
40666
|
-
}) === true);
|
|
40667
|
-
}
|
|
40668
|
-
function makeRecursiveVisitor(visitor) {
|
|
40669
|
-
function recursiveVisitor(node) {
|
|
40670
|
-
const res = visitor(node);
|
|
40671
|
-
return res !== null ? res : node.forEachChild(recursiveVisitor);
|
|
40672
|
-
}
|
|
40673
|
-
return recursiveVisitor;
|
|
40674
|
-
}
|
|
40675
|
-
function getSpanFromOptions(opts) {
|
|
40676
|
-
let withSpan = null;
|
|
40677
|
-
if (opts.withSpan !== undefined) {
|
|
40678
|
-
if (opts.withSpan instanceof AbsoluteSourceSpan) {
|
|
40679
|
-
withSpan = opts.withSpan;
|
|
40680
|
-
}
|
|
40681
|
-
else {
|
|
40682
|
-
withSpan = { start: opts.withSpan.start.offset, end: opts.withSpan.end.offset };
|
|
40683
|
-
}
|
|
40684
|
-
}
|
|
40685
|
-
return withSpan;
|
|
40686
|
-
}
|
|
40687
|
-
/**
|
|
40688
|
-
* Given a `ts.Node` with finds the first node whose matching the criteria specified
|
|
40689
|
-
* by the `FindOptions`.
|
|
40690
|
-
*
|
|
40691
|
-
* Returns `null` when no `ts.Node` matches the given conditions.
|
|
40692
|
-
*/
|
|
40693
|
-
function findFirstMatchingNode(tcb, opts) {
|
|
40694
|
-
const withSpan = getSpanFromOptions(opts);
|
|
40695
|
-
const withExpressionIdentifier = opts.withExpressionIdentifier;
|
|
40696
|
-
const sf = tcb.getSourceFile();
|
|
40697
|
-
const visitor = makeRecursiveVisitor((node) => {
|
|
40698
|
-
if (!opts.filter(node)) {
|
|
40699
|
-
return null;
|
|
40700
|
-
}
|
|
40701
|
-
if (withSpan !== null) {
|
|
40702
|
-
const comment = readSpanComment(node, sf);
|
|
40703
|
-
if (comment === null || withSpan.start !== comment.start || withSpan.end !== comment.end) {
|
|
40704
|
-
return null;
|
|
40705
|
-
}
|
|
40706
|
-
}
|
|
40707
|
-
if (withExpressionIdentifier !== undefined &&
|
|
40708
|
-
!hasExpressionIdentifier(sf, node, withExpressionIdentifier)) {
|
|
40709
|
-
return null;
|
|
40710
|
-
}
|
|
40711
|
-
return node;
|
|
40712
|
-
});
|
|
40713
|
-
return tcb.forEachChild(visitor) ?? null;
|
|
40714
|
-
}
|
|
40715
|
-
/**
|
|
40716
|
-
* Given a `ts.Node` with source span comments, finds the first node whose source span comment
|
|
40717
|
-
* matches the given `sourceSpan`. Additionally, the `filter` function allows matching only
|
|
40718
|
-
* `ts.Nodes` of a given type, which provides the ability to select only matches of a given type
|
|
40719
|
-
* when there may be more than one.
|
|
40720
|
-
*
|
|
40721
|
-
* Returns `null` when no `ts.Node` matches the given conditions.
|
|
40722
|
-
*/
|
|
40723
|
-
function findAllMatchingNodes(tcb, opts) {
|
|
40724
|
-
const withSpan = getSpanFromOptions(opts);
|
|
40725
|
-
const withExpressionIdentifier = opts.withExpressionIdentifier;
|
|
40726
|
-
const results = [];
|
|
40727
|
-
const stack = [tcb];
|
|
40728
|
-
const sf = tcb.getSourceFile();
|
|
40729
|
-
while (stack.length > 0) {
|
|
40730
|
-
const node = stack.pop();
|
|
40731
|
-
if (!opts.filter(node)) {
|
|
40732
|
-
stack.push(...node.getChildren());
|
|
40733
|
-
continue;
|
|
40734
|
-
}
|
|
40735
|
-
if (withSpan !== null) {
|
|
40736
|
-
const comment = readSpanComment(node, sf);
|
|
40737
|
-
if (comment === null || withSpan.start !== comment.start || withSpan.end !== comment.end) {
|
|
40738
|
-
stack.push(...node.getChildren());
|
|
40739
|
-
continue;
|
|
40740
|
-
}
|
|
40741
|
-
}
|
|
40742
|
-
if (withExpressionIdentifier !== undefined &&
|
|
40743
|
-
!hasExpressionIdentifier(sf, node, withExpressionIdentifier)) {
|
|
40744
|
-
continue;
|
|
40745
|
-
}
|
|
40746
|
-
results.push(node);
|
|
40747
|
-
}
|
|
40748
|
-
return results;
|
|
40749
|
-
}
|
|
40750
|
-
function hasExpressionIdentifier(sourceFile, node, identifier) {
|
|
40751
|
-
return (ts.forEachTrailingCommentRange(sourceFile.text, node.getEnd(), (pos, end, kind) => {
|
|
40752
|
-
if (kind !== ts.SyntaxKind.MultiLineCommentTrivia) {
|
|
40753
|
-
return false;
|
|
40754
|
-
}
|
|
40755
|
-
const commentText = sourceFile.text.substring(pos + 2, end - 2);
|
|
40756
|
-
return commentText === `${CommentTriviaType.EXPRESSION_TYPE_IDENTIFIER}:${identifier}`;
|
|
40757
|
-
}) || false);
|
|
40758
|
-
}
|
|
40759
|
-
|
|
40760
40979
|
/**
|
|
40761
40980
|
* Powers autocompletion for a specific component.
|
|
40762
40981
|
*
|
|
@@ -42473,152 +42692,6 @@ class ReferenceEmitEnvironment {
|
|
|
42473
42692
|
}
|
|
42474
42693
|
}
|
|
42475
42694
|
|
|
42476
|
-
/**
|
|
42477
|
-
* A `Set` of `ts.SyntaxKind`s of `ts.Expression` which are safe to wrap in a `ts.AsExpression`
|
|
42478
|
-
* without needing to be wrapped in parentheses.
|
|
42479
|
-
*
|
|
42480
|
-
* For example, `foo.bar()` is a `ts.CallExpression`, and can be safely cast to `any` with
|
|
42481
|
-
* `foo.bar() as any`. however, `foo !== bar` is a `ts.BinaryExpression`, and attempting to cast
|
|
42482
|
-
* without the parentheses yields the expression `foo !== bar as any`. This is semantically
|
|
42483
|
-
* equivalent to `foo !== (bar as any)`, which is not what was intended. Thus,
|
|
42484
|
-
* `ts.BinaryExpression`s need to be wrapped in parentheses before casting.
|
|
42485
|
-
*/
|
|
42486
|
-
//
|
|
42487
|
-
let SAFE_TO_CAST_WITHOUT_PARENS = null;
|
|
42488
|
-
function tsCastToAny(expr) {
|
|
42489
|
-
if (SAFE_TO_CAST_WITHOUT_PARENS === null) {
|
|
42490
|
-
SAFE_TO_CAST_WITHOUT_PARENS = new Set([
|
|
42491
|
-
// Expressions which are already parenthesized can be cast without further wrapping.
|
|
42492
|
-
ts.SyntaxKind.ParenthesizedExpression,
|
|
42493
|
-
// Expressions which form a single lexical unit leave no room for precedence issues with the cast.
|
|
42494
|
-
ts.SyntaxKind.Identifier,
|
|
42495
|
-
ts.SyntaxKind.CallExpression,
|
|
42496
|
-
ts.SyntaxKind.NonNullExpression,
|
|
42497
|
-
ts.SyntaxKind.ElementAccessExpression,
|
|
42498
|
-
ts.SyntaxKind.PropertyAccessExpression,
|
|
42499
|
-
ts.SyntaxKind.ArrayLiteralExpression,
|
|
42500
|
-
ts.SyntaxKind.ObjectLiteralExpression,
|
|
42501
|
-
// The same goes for various literals.
|
|
42502
|
-
ts.SyntaxKind.StringLiteral,
|
|
42503
|
-
ts.SyntaxKind.NumericLiteral,
|
|
42504
|
-
ts.SyntaxKind.TrueKeyword,
|
|
42505
|
-
ts.SyntaxKind.FalseKeyword,
|
|
42506
|
-
ts.SyntaxKind.NullKeyword,
|
|
42507
|
-
ts.SyntaxKind.UndefinedKeyword,
|
|
42508
|
-
]);
|
|
42509
|
-
}
|
|
42510
|
-
// Wrap `expr` in parentheses if needed (see `SAFE_TO_CAST_WITHOUT_PARENS` above).
|
|
42511
|
-
if (!SAFE_TO_CAST_WITHOUT_PARENS.has(expr.kind)) {
|
|
42512
|
-
expr = ts.factory.createParenthesizedExpression(expr);
|
|
42513
|
-
}
|
|
42514
|
-
// The outer expression is always wrapped in parentheses.
|
|
42515
|
-
return ts.factory.createParenthesizedExpression(ts.factory.createAsExpression(expr, ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword)));
|
|
42516
|
-
}
|
|
42517
|
-
/**
|
|
42518
|
-
* Create an expression which instantiates an element by its HTML tagName.
|
|
42519
|
-
*
|
|
42520
|
-
* Thanks to narrowing of `document.createElement()`, this expression will have its type inferred
|
|
42521
|
-
* based on the tag name, including for custom elements that have appropriate .d.ts definitions.
|
|
42522
|
-
*/
|
|
42523
|
-
function tsCreateElement(...tagNames) {
|
|
42524
|
-
const createElement = ts.factory.createPropertyAccessExpression(
|
|
42525
|
-
/* expression */ ts.factory.createIdentifier('document'), 'createElement');
|
|
42526
|
-
let arg;
|
|
42527
|
-
if (tagNames.length === 1) {
|
|
42528
|
-
// If there's only one tag name, we can pass it in directly.
|
|
42529
|
-
arg = ts.factory.createStringLiteral(tagNames[0]);
|
|
42530
|
-
}
|
|
42531
|
-
else {
|
|
42532
|
-
// If there's more than one name, we have to generate a union of all the tag names. To do so,
|
|
42533
|
-
// create an expression in the form of `null! as 'tag-1' | 'tag-2' | 'tag-3'`. This allows
|
|
42534
|
-
// TypeScript to infer the type as a union of the differnet tags.
|
|
42535
|
-
const assertedNullExpression = ts.factory.createNonNullExpression(ts.factory.createNull());
|
|
42536
|
-
const type = ts.factory.createUnionTypeNode(tagNames.map((tag) => ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral(tag))));
|
|
42537
|
-
arg = ts.factory.createAsExpression(assertedNullExpression, type);
|
|
42538
|
-
}
|
|
42539
|
-
return ts.factory.createCallExpression(
|
|
42540
|
-
/* expression */ createElement,
|
|
42541
|
-
/* typeArguments */ undefined,
|
|
42542
|
-
/* argumentsArray */ [arg]);
|
|
42543
|
-
}
|
|
42544
|
-
/**
|
|
42545
|
-
* Create a `ts.VariableStatement` which declares a variable without explicit initialization.
|
|
42546
|
-
*
|
|
42547
|
-
* The initializer `null!` is used to bypass strict variable initialization checks.
|
|
42548
|
-
*
|
|
42549
|
-
* Unlike with `tsCreateVariable`, the type of the variable is explicitly specified.
|
|
42550
|
-
*/
|
|
42551
|
-
function tsDeclareVariable(id, type) {
|
|
42552
|
-
// When we create a variable like `var _t1: boolean = null!`, TypeScript actually infers `_t1`
|
|
42553
|
-
// to be `never`, instead of a `boolean`. To work around it, we cast the value
|
|
42554
|
-
// in the initializer, e.g. `var _t1 = null! as boolean;`.
|
|
42555
|
-
addExpressionIdentifier(type, ExpressionIdentifier.VARIABLE_AS_EXPRESSION);
|
|
42556
|
-
const initializer = ts.factory.createAsExpression(ts.factory.createNonNullExpression(ts.factory.createNull()), type);
|
|
42557
|
-
const decl = ts.factory.createVariableDeclaration(
|
|
42558
|
-
/* name */ id,
|
|
42559
|
-
/* exclamationToken */ undefined,
|
|
42560
|
-
/* type */ undefined,
|
|
42561
|
-
/* initializer */ initializer);
|
|
42562
|
-
return ts.factory.createVariableStatement(
|
|
42563
|
-
/* modifiers */ undefined,
|
|
42564
|
-
/* declarationList */ [decl]);
|
|
42565
|
-
}
|
|
42566
|
-
/**
|
|
42567
|
-
* Creates a `ts.TypeQueryNode` for a coerced input.
|
|
42568
|
-
*
|
|
42569
|
-
* For example: `typeof MatInput.ngAcceptInputType_value`, where MatInput is `typeName` and `value`
|
|
42570
|
-
* is the `coercedInputName`.
|
|
42571
|
-
*
|
|
42572
|
-
* @param typeName The `EntityName` of the Directive where the static coerced input is defined.
|
|
42573
|
-
* @param coercedInputName The field name of the coerced input.
|
|
42574
|
-
*/
|
|
42575
|
-
function tsCreateTypeQueryForCoercedInput(typeName, coercedInputName) {
|
|
42576
|
-
return ts.factory.createTypeQueryNode(ts.factory.createQualifiedName(typeName, `ngAcceptInputType_${coercedInputName}`));
|
|
42577
|
-
}
|
|
42578
|
-
/**
|
|
42579
|
-
* Create a `ts.VariableStatement` that initializes a variable with a given expression.
|
|
42580
|
-
*
|
|
42581
|
-
* Unlike with `tsDeclareVariable`, the type of the variable is inferred from the initializer
|
|
42582
|
-
* expression.
|
|
42583
|
-
*/
|
|
42584
|
-
function tsCreateVariable(id, initializer, flags = null) {
|
|
42585
|
-
const decl = ts.factory.createVariableDeclaration(
|
|
42586
|
-
/* name */ id,
|
|
42587
|
-
/* exclamationToken */ undefined,
|
|
42588
|
-
/* type */ undefined,
|
|
42589
|
-
/* initializer */ initializer);
|
|
42590
|
-
return ts.factory.createVariableStatement(
|
|
42591
|
-
/* modifiers */ undefined,
|
|
42592
|
-
/* declarationList */ flags === null
|
|
42593
|
-
? [decl]
|
|
42594
|
-
: ts.factory.createVariableDeclarationList([decl], flags));
|
|
42595
|
-
}
|
|
42596
|
-
/**
|
|
42597
|
-
* Construct a `ts.CallExpression` that calls a method on a receiver.
|
|
42598
|
-
*/
|
|
42599
|
-
function tsCallMethod(receiver, methodName, args = []) {
|
|
42600
|
-
const methodAccess = ts.factory.createPropertyAccessExpression(receiver, methodName);
|
|
42601
|
-
return ts.factory.createCallExpression(
|
|
42602
|
-
/* expression */ methodAccess,
|
|
42603
|
-
/* typeArguments */ undefined,
|
|
42604
|
-
/* argumentsArray */ args);
|
|
42605
|
-
}
|
|
42606
|
-
function isAccessExpression(node) {
|
|
42607
|
-
return ts.isPropertyAccessExpression(node) || ts.isElementAccessExpression(node);
|
|
42608
|
-
}
|
|
42609
|
-
/**
|
|
42610
|
-
* Creates a TypeScript node representing a numeric value.
|
|
42611
|
-
*/
|
|
42612
|
-
function tsNumericExpression(value) {
|
|
42613
|
-
// As of TypeScript 5.3 negative numbers are represented as `prefixUnaryOperator` and passing a
|
|
42614
|
-
// negative number (even as a string) into `createNumericLiteral` will result in an error.
|
|
42615
|
-
if (value < 0) {
|
|
42616
|
-
const operand = ts.factory.createNumericLiteral(Math.abs(value));
|
|
42617
|
-
return ts.factory.createPrefixUnaryExpression(ts.SyntaxKind.MinusToken, operand);
|
|
42618
|
-
}
|
|
42619
|
-
return ts.factory.createNumericLiteral(value);
|
|
42620
|
-
}
|
|
42621
|
-
|
|
42622
42695
|
/**
|
|
42623
42696
|
* See `TypeEmitter` for more information on the emitting process.
|
|
42624
42697
|
*/
|
|
@@ -43993,7 +44066,12 @@ function translateDiagnostic(diagnostic, resolver) {
|
|
|
43993
44066
|
return null;
|
|
43994
44067
|
}
|
|
43995
44068
|
const { sourceLocation, sourceMapping: templateSourceMapping, span } = fullMapping;
|
|
43996
|
-
return makeTemplateDiagnostic(sourceLocation.id, templateSourceMapping, span, diagnostic.category, diagnostic.code, diagnostic.messageText
|
|
44069
|
+
return makeTemplateDiagnostic(sourceLocation.id, templateSourceMapping, span, diagnostic.category, diagnostic.code, diagnostic.messageText, undefined, diagnostic.reportsDeprecated !== undefined
|
|
44070
|
+
? {
|
|
44071
|
+
reportsDeprecated: diagnostic.reportsDeprecated,
|
|
44072
|
+
relatedMessages: diagnostic.relatedInformation,
|
|
44073
|
+
}
|
|
44074
|
+
: undefined);
|
|
43997
44075
|
}
|
|
43998
44076
|
|
|
43999
44077
|
/**
|
|
@@ -45724,8 +45802,8 @@ class TcbUnclaimedOutputsOp extends TcbOp {
|
|
|
45724
45802
|
// `HTMLElement.addEventListener` using `HTMLElementEventMap` to infer an accurate type for
|
|
45725
45803
|
// `$event` depending on the event name. For unknown event names, TypeScript resorts to the
|
|
45726
45804
|
// base `Event` type.
|
|
45727
|
-
const handler = tcbCreateEventHandler(output, this.tcb, this.scope, 0 /* EventParamType.Infer */);
|
|
45728
45805
|
let target;
|
|
45806
|
+
let domEventAssertion;
|
|
45729
45807
|
// Only check for `window` and `document` since in theory any target can be passed.
|
|
45730
45808
|
if (output.target === 'window' || output.target === 'document') {
|
|
45731
45809
|
target = ts.factory.createIdentifier(output.target);
|
|
@@ -45736,8 +45814,32 @@ class TcbUnclaimedOutputsOp extends TcbOp {
|
|
|
45736
45814
|
else {
|
|
45737
45815
|
target = elId;
|
|
45738
45816
|
}
|
|
45817
|
+
// By default the target of an event is `EventTarget | null`, because of bubbling
|
|
45818
|
+
// and custom events. This can be inconvenient in some common cases like `input` elements
|
|
45819
|
+
// since we don't have the ability to type cast in templates. We can improve the type
|
|
45820
|
+
// checking for some of these cases by inferring the target based on the element it was
|
|
45821
|
+
// bound to. We can only do this safely if the element is a void element (e.g. `input` or
|
|
45822
|
+
// `img`), because we know that it couldn't have bubbled from a child. The event handler
|
|
45823
|
+
// with the assertion would look as follows:
|
|
45824
|
+
//
|
|
45825
|
+
// ```
|
|
45826
|
+
// const _t1 = document.createElement('input');
|
|
45827
|
+
//
|
|
45828
|
+
// _t1.addEventListener('input', ($event) => {
|
|
45829
|
+
// ɵassertType<typeof _t1>($event.target);
|
|
45830
|
+
// handler($event.target);
|
|
45831
|
+
// });
|
|
45832
|
+
// ```
|
|
45833
|
+
if (this.target instanceof Element$1 &&
|
|
45834
|
+
this.target.isVoid &&
|
|
45835
|
+
ts.isIdentifier(target)) {
|
|
45836
|
+
domEventAssertion = ts.factory.createCallExpression(this.tcb.env.referenceExternalSymbol('@angular/core', 'ɵassertType'), [ts.factory.createTypeQueryNode(target)], [
|
|
45837
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier(EVENT_PARAMETER), 'target'),
|
|
45838
|
+
]);
|
|
45839
|
+
}
|
|
45739
45840
|
const propertyAccess = ts.factory.createPropertyAccessExpression(target, 'addEventListener');
|
|
45740
45841
|
addParseSpanInfo(propertyAccess, output.keySpan);
|
|
45842
|
+
const handler = tcbCreateEventHandler(output, this.tcb, this.scope, 0 /* EventParamType.Infer */, domEventAssertion);
|
|
45741
45843
|
const call = ts.factory.createCallExpression(
|
|
45742
45844
|
/* expression */ propertyAccess,
|
|
45743
45845
|
/* typeArguments */ undefined,
|
|
@@ -47168,9 +47270,12 @@ const EVENT_PARAMETER = '$event';
|
|
|
47168
47270
|
* parameter will have an explicit `any` type, effectively disabling strict type checking of event
|
|
47169
47271
|
* bindings. Alternatively, an explicit type can be passed for the `$event` parameter.
|
|
47170
47272
|
*/
|
|
47171
|
-
function tcbCreateEventHandler(event, tcb, scope, eventType) {
|
|
47273
|
+
function tcbCreateEventHandler(event, tcb, scope, eventType, assertionExpression) {
|
|
47172
47274
|
const handler = tcbEventHandlerExpression(event.handler, tcb, scope);
|
|
47173
47275
|
const statements = [];
|
|
47276
|
+
if (assertionExpression !== undefined) {
|
|
47277
|
+
statements.push(ts.factory.createExpressionStatement(assertionExpression));
|
|
47278
|
+
}
|
|
47174
47279
|
// TODO(crisbeto): remove the `checkTwoWayBoundEvents` check in v20.
|
|
47175
47280
|
if (event.type === exports.ParsedEventType.TwoWay && tcb.env.config.checkTwoWayBoundEvents) {
|
|
47176
47281
|
// If we're dealing with a two-way event, we create a variable initialized to the unwrapped
|
|
@@ -48016,13 +48121,6 @@ class SymbolBuilder {
|
|
|
48016
48121
|
}
|
|
48017
48122
|
getDirectivesOfNode(templateNode) {
|
|
48018
48123
|
const elementSourceSpan = templateNode.startSourceSpan ?? templateNode.sourceSpan;
|
|
48019
|
-
const tcbSourceFile = this.typeCheckBlock.getSourceFile();
|
|
48020
|
-
// directives could be either:
|
|
48021
|
-
// - var _t1: TestDir /*T:D*/ = null! as TestDir;
|
|
48022
|
-
// - var _t1 /*T:D*/ = _ctor1({});
|
|
48023
|
-
const isDirectiveDeclaration = (node) => (ts.isTypeNode(node) || ts.isIdentifier(node)) &&
|
|
48024
|
-
ts.isVariableDeclaration(node.parent) &&
|
|
48025
|
-
hasExpressionIdentifier(tcbSourceFile, node, ExpressionIdentifier.DIRECTIVE);
|
|
48026
48124
|
const nodes = findAllMatchingNodes(this.typeCheckBlock, {
|
|
48027
48125
|
withSpan: elementSourceSpan,
|
|
48028
48126
|
filter: isDirectiveDeclaration,
|
|
@@ -48886,6 +48984,29 @@ class TemplateTypeCheckerImpl {
|
|
|
48886
48984
|
return diagnostics.filter((diag) => diag !== null);
|
|
48887
48985
|
});
|
|
48888
48986
|
}
|
|
48987
|
+
getSuggestionDiagnosticsForFile(sf, tsLs, optimizeFor) {
|
|
48988
|
+
switch (optimizeFor) {
|
|
48989
|
+
case exports.OptimizeFor.WholeProgram:
|
|
48990
|
+
this.ensureAllShimsForAllFiles();
|
|
48991
|
+
break;
|
|
48992
|
+
case exports.OptimizeFor.SingleFile:
|
|
48993
|
+
this.ensureAllShimsForOneFile(sf);
|
|
48994
|
+
break;
|
|
48995
|
+
}
|
|
48996
|
+
return this.perf.inPhase(exports.PerfPhase.TtcSuggestionDiagnostics, () => {
|
|
48997
|
+
const sfPath = absoluteFromSourceFile(sf);
|
|
48998
|
+
const fileRecord = this.state.get(sfPath);
|
|
48999
|
+
const diagnostics = [];
|
|
49000
|
+
const program = this.programDriver.getProgram();
|
|
49001
|
+
if (fileRecord.hasInlines) {
|
|
49002
|
+
diagnostics.push(...getDeprecatedSuggestionDiagnostics(tsLs, program, sfPath, fileRecord, this));
|
|
49003
|
+
}
|
|
49004
|
+
for (const [shimPath] of fileRecord.shimData) {
|
|
49005
|
+
diagnostics.push(...getDeprecatedSuggestionDiagnostics(tsLs, program, shimPath, fileRecord, this));
|
|
49006
|
+
}
|
|
49007
|
+
return diagnostics.filter((diag) => diag !== null);
|
|
49008
|
+
});
|
|
49009
|
+
}
|
|
48889
49010
|
getDiagnosticsForComponent(component) {
|
|
48890
49011
|
this.ensureShimForComponent(component);
|
|
48891
49012
|
return this.perf.inPhase(exports.PerfPhase.TtcDiagnostics, () => {
|
|
@@ -48917,6 +49038,27 @@ class TemplateTypeCheckerImpl {
|
|
|
48917
49038
|
return diagnostics.filter((diag) => diag !== null && diag.typeCheckId === id);
|
|
48918
49039
|
});
|
|
48919
49040
|
}
|
|
49041
|
+
getSuggestionDiagnosticsForComponent(component, tsLs) {
|
|
49042
|
+
this.ensureShimForComponent(component);
|
|
49043
|
+
return this.perf.inPhase(exports.PerfPhase.TtcSuggestionDiagnostics, () => {
|
|
49044
|
+
const sf = component.getSourceFile();
|
|
49045
|
+
const sfPath = absoluteFromSourceFile(sf);
|
|
49046
|
+
const shimPath = TypeCheckShimGenerator.shimFor(sfPath);
|
|
49047
|
+
const fileRecord = this.getFileData(sfPath);
|
|
49048
|
+
if (!fileRecord.shimData.has(shimPath)) {
|
|
49049
|
+
return [];
|
|
49050
|
+
}
|
|
49051
|
+
const templateId = fileRecord.sourceManager.getTypeCheckId(component);
|
|
49052
|
+
const shimRecord = fileRecord.shimData.get(shimPath);
|
|
49053
|
+
const diagnostics = [];
|
|
49054
|
+
const program = this.programDriver.getProgram();
|
|
49055
|
+
if (shimRecord.hasInlines) {
|
|
49056
|
+
diagnostics.push(...getDeprecatedSuggestionDiagnostics(tsLs, program, sfPath, fileRecord, this));
|
|
49057
|
+
}
|
|
49058
|
+
diagnostics.push(...getDeprecatedSuggestionDiagnostics(tsLs, program, shimPath, fileRecord, this));
|
|
49059
|
+
return diagnostics.filter((diag) => diag !== null && diag.typeCheckId === templateId);
|
|
49060
|
+
});
|
|
49061
|
+
}
|
|
48920
49062
|
getTypeCheckBlock(component) {
|
|
48921
49063
|
return this.getLatestComponentState(component).tcb;
|
|
48922
49064
|
}
|
|
@@ -49740,6 +49882,124 @@ function getClassDeclFromSymbol(symbol, checker) {
|
|
|
49740
49882
|
}
|
|
49741
49883
|
return null;
|
|
49742
49884
|
}
|
|
49885
|
+
/**
|
|
49886
|
+
* Returns the diagnostics that report deprecated symbols in the given TypeScript language service.
|
|
49887
|
+
*
|
|
49888
|
+
* There are two logins here:
|
|
49889
|
+
*
|
|
49890
|
+
* 1. For input properties, function calls, and so on, the diagnostics reported in the TypeScript
|
|
49891
|
+
* Language Service can be directly transformed into template diagnostics.
|
|
49892
|
+
* 2. For the element tag deprecation, we need to manually connect the TCB node to the template node
|
|
49893
|
+
* and generate the template diagnostics.
|
|
49894
|
+
*/
|
|
49895
|
+
function getDeprecatedSuggestionDiagnostics(tsLs, program, path, fileRecord, templateTypeChecker) {
|
|
49896
|
+
const sourceFile = program.getSourceFile(path);
|
|
49897
|
+
if (sourceFile === undefined) {
|
|
49898
|
+
return [];
|
|
49899
|
+
}
|
|
49900
|
+
const tsDiags = tsLs.getSuggestionDiagnostics(path).filter(isDeprecatedDiagnostics);
|
|
49901
|
+
const commonTemplateDiags = tsDiags.map((diag) => {
|
|
49902
|
+
return convertDiagnostic(diag, fileRecord.sourceManager);
|
|
49903
|
+
});
|
|
49904
|
+
const elementTagDiags = getTheElementTagDeprecatedSuggestionDiagnostics(path, program, fileRecord, tsDiags, templateTypeChecker);
|
|
49905
|
+
return [...commonTemplateDiags, ...elementTagDiags];
|
|
49906
|
+
}
|
|
49907
|
+
/**
|
|
49908
|
+
* Connect the TCB node to the template node and generate the template diagnostics.
|
|
49909
|
+
*
|
|
49910
|
+
* How to generate the template diagnostics:
|
|
49911
|
+
*
|
|
49912
|
+
* 1. For each diagnostic, find the TCB node that is reported.
|
|
49913
|
+
* 2. Build a map called `nodeToDiag` that the key is the type node and value is the diagnostic.
|
|
49914
|
+
* For example:
|
|
49915
|
+
* ```
|
|
49916
|
+
* var _t1 = null! as TestDir;
|
|
49917
|
+
* ^^^^^^^------ This is diagnostic node that is reported by the ts.
|
|
49918
|
+
* ```
|
|
49919
|
+
* The key is the class component of TestDir.
|
|
49920
|
+
* 3. Find the all directive nodes in the TCB.
|
|
49921
|
+
* For example:
|
|
49922
|
+
* In the above example, the directive node is `_t1`, get the type of `_t1` which is the
|
|
49923
|
+
* class component of `TestDir`. Check if there is a diagnostic in the `nodeToDiag` map
|
|
49924
|
+
* that matches the class component of `TestDir`.
|
|
49925
|
+
* If there is a match, it means that the diagnostic is reported for the directive node
|
|
49926
|
+
* 4. Generate the template diagnostic and return the template diagnostics.
|
|
49927
|
+
*/
|
|
49928
|
+
function getTheElementTagDeprecatedSuggestionDiagnostics(shimPath, program, fileRecord, diags, templateTypeChecker) {
|
|
49929
|
+
const sourceFile = program.getSourceFile(shimPath);
|
|
49930
|
+
if (sourceFile === undefined) {
|
|
49931
|
+
return [];
|
|
49932
|
+
}
|
|
49933
|
+
const typeChecker = program.getTypeChecker();
|
|
49934
|
+
const nodeToDiag = new Map();
|
|
49935
|
+
for (const tsDiag of diags) {
|
|
49936
|
+
const diagNode = getTokenAtPosition(sourceFile, tsDiag.start);
|
|
49937
|
+
const nodeType = typeChecker.getTypeAtLocation(diagNode);
|
|
49938
|
+
const nodeSymbolDeclarations = nodeType.symbol.declarations;
|
|
49939
|
+
const decl = nodeSymbolDeclarations !== undefined && nodeSymbolDeclarations.length > 0
|
|
49940
|
+
? nodeSymbolDeclarations[0]
|
|
49941
|
+
: undefined;
|
|
49942
|
+
if (decl === undefined || !ts.isClassDeclaration(decl)) {
|
|
49943
|
+
continue;
|
|
49944
|
+
}
|
|
49945
|
+
const directiveForDiagnostic = templateTypeChecker.getDirectiveMetadata(decl);
|
|
49946
|
+
// For now, we only report deprecations for components. This is because
|
|
49947
|
+
// directive spans apply to the entire element, so it would cause the deprecation to
|
|
49948
|
+
// appear as a deprecation for the element rather than whatever the selector (likely an attribute)
|
|
49949
|
+
// is for the directive. Technically components have this issue as well but nearly
|
|
49950
|
+
// all component selectors are element selectors.
|
|
49951
|
+
if (directiveForDiagnostic === null || !directiveForDiagnostic.isComponent) {
|
|
49952
|
+
continue;
|
|
49953
|
+
}
|
|
49954
|
+
nodeToDiag.set(decl, tsDiag);
|
|
49955
|
+
}
|
|
49956
|
+
const directiveNodesInTcb = findAllMatchingNodes(sourceFile, {
|
|
49957
|
+
filter: isDirectiveDeclaration,
|
|
49958
|
+
});
|
|
49959
|
+
const templateDiagnostics = [];
|
|
49960
|
+
for (const directive of directiveNodesInTcb) {
|
|
49961
|
+
const directiveType = typeChecker.getTypeAtLocation(directive);
|
|
49962
|
+
const directiveSymbolDeclarations = directiveType.symbol.declarations;
|
|
49963
|
+
const decl = directiveSymbolDeclarations !== undefined && directiveSymbolDeclarations.length > 0
|
|
49964
|
+
? directiveSymbolDeclarations[0]
|
|
49965
|
+
: undefined;
|
|
49966
|
+
if (decl === undefined) {
|
|
49967
|
+
continue;
|
|
49968
|
+
}
|
|
49969
|
+
if (!ts.isClassDeclaration(decl)) {
|
|
49970
|
+
continue;
|
|
49971
|
+
}
|
|
49972
|
+
const diagnostic = nodeToDiag.get(decl);
|
|
49973
|
+
if (diagnostic === undefined) {
|
|
49974
|
+
continue;
|
|
49975
|
+
}
|
|
49976
|
+
const fullMapping = getSourceMapping(diagnostic.file, directive.getStart(), fileRecord.sourceManager,
|
|
49977
|
+
/**
|
|
49978
|
+
* Don't set to true, the deprecated diagnostics will be ignored if this is a diagnostics request.
|
|
49979
|
+
* Only the deprecated diagnostics will be reported here.
|
|
49980
|
+
*/
|
|
49981
|
+
// For example:
|
|
49982
|
+
// var _t2 /*T:DIR*/ /*87,104*/ = _ctor1({ "name": ("") /*96,103*/ }) /*D:ignore*/;
|
|
49983
|
+
// At the end of the statement, there is a comment `/*D:ignore*/` which means that this diagnostic
|
|
49984
|
+
// should be ignored in diagnostics request.
|
|
49985
|
+
/*isDiagnosticsRequest*/ false);
|
|
49986
|
+
if (fullMapping === null) {
|
|
49987
|
+
continue;
|
|
49988
|
+
}
|
|
49989
|
+
const { sourceLocation, sourceMapping: templateSourceMapping, span } = fullMapping;
|
|
49990
|
+
const templateDiagnostic = makeTemplateDiagnostic(sourceLocation.id, templateSourceMapping, span, diagnostic.category, diagnostic.code, diagnostic.messageText, undefined, diagnostic.reportsDeprecated !== undefined
|
|
49991
|
+
? {
|
|
49992
|
+
reportsDeprecated: diagnostic.reportsDeprecated,
|
|
49993
|
+
relatedMessages: diagnostic.relatedInformation,
|
|
49994
|
+
}
|
|
49995
|
+
: undefined);
|
|
49996
|
+
templateDiagnostics.push(templateDiagnostic);
|
|
49997
|
+
}
|
|
49998
|
+
return templateDiagnostics;
|
|
49999
|
+
}
|
|
50000
|
+
function isDeprecatedDiagnostics(diag) {
|
|
50001
|
+
return diag.reportsDeprecated !== undefined;
|
|
50002
|
+
}
|
|
49743
50003
|
|
|
49744
50004
|
exports.AST = AST;
|
|
49745
50005
|
exports.ASTWithSource = ASTWithSource;
|