@angular/language-service 10.1.3 → 10.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bundles/ivy.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Angular v10.1.3
2
+ * @license Angular v10.2.0
3
3
  * Copyright Google LLC All Rights Reserved.
4
4
  * License: MIT
5
5
  */
@@ -10780,11 +10780,12 @@ define(['exports', 'os', 'typescript', 'fs', 'constants', 'stream', 'util', 'ass
10780
10780
  function extractCommentsWithHash(input) {
10781
10781
  return input.match(_commentWithHashRe) || [];
10782
10782
  }
10783
- const _ruleRe = /(\s*)([^;\{\}]+?)(\s*)((?:{%BLOCK%}?\s*;?)|(?:\s*;))/g;
10784
- const _curlyRe = /([{}])/g;
10785
- const OPEN_CURLY = '{';
10786
- const CLOSE_CURLY = '}';
10787
10783
  const BLOCK_PLACEHOLDER = '%BLOCK%';
10784
+ const QUOTE_PLACEHOLDER = '%QUOTED%';
10785
+ const _ruleRe = /(\s*)([^;\{\}]+?)(\s*)((?:{%BLOCK%}?\s*;?)|(?:\s*;))/g;
10786
+ const _quotedRe = /%QUOTED%/g;
10787
+ const CONTENT_PAIRS = new Map([['{', '}']]);
10788
+ const QUOTE_PAIRS = new Map([[`"`, `"`], [`'`, `'`]]);
10788
10789
  class CssRule {
10789
10790
  constructor(selector, content) {
10790
10791
  this.selector = selector;
@@ -10792,9 +10793,12 @@ define(['exports', 'os', 'typescript', 'fs', 'constants', 'stream', 'util', 'ass
10792
10793
  }
10793
10794
  }
10794
10795
  function processRules(input, ruleCallback) {
10795
- const inputWithEscapedBlocks = escapeBlocks(input);
10796
+ const inputWithEscapedQuotes = escapeBlocks(input, QUOTE_PAIRS, QUOTE_PLACEHOLDER);
10797
+ const inputWithEscapedBlocks = escapeBlocks(inputWithEscapedQuotes.escapedString, CONTENT_PAIRS, BLOCK_PLACEHOLDER);
10796
10798
  let nextBlockIndex = 0;
10797
- return inputWithEscapedBlocks.escapedString.replace(_ruleRe, function (...m) {
10799
+ let nextQuoteIndex = 0;
10800
+ return inputWithEscapedBlocks.escapedString
10801
+ .replace(_ruleRe, (...m) => {
10798
10802
  const selector = m[2];
10799
10803
  let content = '';
10800
10804
  let suffix = m[4];
@@ -10806,7 +10810,8 @@ define(['exports', 'os', 'typescript', 'fs', 'constants', 'stream', 'util', 'ass
10806
10810
  }
10807
10811
  const rule = ruleCallback(new CssRule(selector, content));
10808
10812
  return `${m[1]}${rule.selector}${m[3]}${contentPrefix}${rule.content}${suffix}`;
10809
- });
10813
+ })
10814
+ .replace(_quotedRe, () => inputWithEscapedQuotes.blocks[nextQuoteIndex++]);
10810
10815
  }
10811
10816
  class StringWithEscapedBlocks {
10812
10817
  constructor(escapedString, blocks) {
@@ -10814,35 +10819,46 @@ define(['exports', 'os', 'typescript', 'fs', 'constants', 'stream', 'util', 'ass
10814
10819
  this.blocks = blocks;
10815
10820
  }
10816
10821
  }
10817
- function escapeBlocks(input) {
10818
- const inputParts = input.split(_curlyRe);
10822
+ function escapeBlocks(input, charPairs, placeholder) {
10819
10823
  const resultParts = [];
10820
10824
  const escapedBlocks = [];
10821
- let bracketCount = 0;
10822
- let currentBlockParts = [];
10823
- for (let partIndex = 0; partIndex < inputParts.length; partIndex++) {
10824
- const part = inputParts[partIndex];
10825
- if (part == CLOSE_CURLY) {
10826
- bracketCount--;
10827
- }
10828
- if (bracketCount > 0) {
10829
- currentBlockParts.push(part);
10830
- }
10831
- else {
10832
- if (currentBlockParts.length > 0) {
10833
- escapedBlocks.push(currentBlockParts.join(''));
10834
- resultParts.push(BLOCK_PLACEHOLDER);
10835
- currentBlockParts = [];
10836
- }
10837
- resultParts.push(part);
10838
- }
10839
- if (part == OPEN_CURLY) {
10840
- bracketCount++;
10841
- }
10825
+ let openCharCount = 0;
10826
+ let nonBlockStartIndex = 0;
10827
+ let blockStartIndex = -1;
10828
+ let openChar;
10829
+ let closeChar;
10830
+ for (let i = 0; i < input.length; i++) {
10831
+ const char = input[i];
10832
+ if (char === '\\') {
10833
+ i++;
10834
+ }
10835
+ else if (char === closeChar) {
10836
+ openCharCount--;
10837
+ if (openCharCount === 0) {
10838
+ escapedBlocks.push(input.substring(blockStartIndex, i));
10839
+ resultParts.push(placeholder);
10840
+ nonBlockStartIndex = i;
10841
+ blockStartIndex = -1;
10842
+ openChar = closeChar = undefined;
10843
+ }
10844
+ }
10845
+ else if (char === openChar) {
10846
+ openCharCount++;
10847
+ }
10848
+ else if (openCharCount === 0 && charPairs.has(char)) {
10849
+ openChar = char;
10850
+ closeChar = charPairs.get(char);
10851
+ openCharCount = 1;
10852
+ blockStartIndex = i + 1;
10853
+ resultParts.push(input.substring(nonBlockStartIndex, blockStartIndex));
10854
+ }
10855
+ }
10856
+ if (blockStartIndex !== -1) {
10857
+ escapedBlocks.push(input.substring(blockStartIndex));
10858
+ resultParts.push(placeholder);
10842
10859
  }
10843
- if (currentBlockParts.length > 0) {
10844
- escapedBlocks.push(currentBlockParts.join(''));
10845
- resultParts.push(BLOCK_PLACEHOLDER);
10860
+ else {
10861
+ resultParts.push(input.substring(nonBlockStartIndex));
10846
10862
  }
10847
10863
  return new StringWithEscapedBlocks(resultParts.join(''), escapedBlocks);
10848
10864
  }
@@ -13958,43 +13974,77 @@ define(['exports', 'os', 'typescript', 'fs', 'constants', 'stream', 'util', 'ass
13958
13974
  const span = new ParseSpan(0, input == null ? 0 : input.length);
13959
13975
  return new ASTWithSource(new Interpolation(span, span.toAbsolute(absoluteOffset), split.strings, expressions), input, location, absoluteOffset, this.errors);
13960
13976
  }
13977
+ /**
13978
+ * Splits a string of text into "raw" text segments and expressions present in interpolations in
13979
+ * the string.
13980
+ * Returns `null` if there are no interpolations, otherwise a
13981
+ * `SplitInterpolation` with splits that look like
13982
+ * <raw text> <expression> <raw text> ... <raw text> <expression> <raw text>
13983
+ */
13961
13984
  splitInterpolation(input, location, interpolationConfig = DEFAULT_INTERPOLATION_CONFIG) {
13962
- const regexp = _getInterpolateRegExp(interpolationConfig);
13963
- const parts = input.split(regexp);
13964
- if (parts.length <= 1) {
13965
- return null;
13966
- }
13967
13985
  const strings = [];
13968
13986
  const expressions = [];
13969
13987
  const offsets = [];
13970
13988
  const stringSpans = [];
13971
13989
  const expressionSpans = [];
13972
- let offset = 0;
13973
- for (let i = 0; i < parts.length; i++) {
13974
- const part = parts[i];
13975
- if (i % 2 === 0) {
13976
- // fixed string
13990
+ let i = 0;
13991
+ let atInterpolation = false;
13992
+ let extendLastString = false;
13993
+ let { start: interpStart, end: interpEnd } = interpolationConfig;
13994
+ while (i < input.length) {
13995
+ if (!atInterpolation) {
13996
+ // parse until starting {{
13997
+ const start = i;
13998
+ i = input.indexOf(interpStart, i);
13999
+ if (i === -1) {
14000
+ i = input.length;
14001
+ }
14002
+ const part = input.substring(start, i);
13977
14003
  strings.push(part);
13978
- const start = offset;
13979
- offset += part.length;
13980
- stringSpans.push({ start, end: offset });
13981
- }
13982
- else if (part.trim().length > 0) {
13983
- const start = offset;
13984
- offset += interpolationConfig.start.length;
13985
- expressions.push(part);
13986
- offsets.push(offset);
13987
- offset += part.length + interpolationConfig.end.length;
13988
- expressionSpans.push({ start, end: offset });
14004
+ stringSpans.push({ start, end: i });
14005
+ atInterpolation = true;
14006
+ }
14007
+ else {
14008
+ // parse from starting {{ to ending }}
14009
+ const fullStart = i;
14010
+ const exprStart = fullStart + interpStart.length;
14011
+ const exprEnd = input.indexOf(interpEnd, exprStart);
14012
+ if (exprEnd === -1) {
14013
+ // Could not find the end of the interpolation; do not parse an expression.
14014
+ // Instead we should extend the content on the last raw string.
14015
+ atInterpolation = false;
14016
+ extendLastString = true;
14017
+ break;
14018
+ }
14019
+ const fullEnd = exprEnd + interpEnd.length;
14020
+ const part = input.substring(exprStart, exprEnd);
14021
+ if (part.trim().length > 0) {
14022
+ expressions.push(part);
14023
+ }
14024
+ else {
14025
+ this._reportError('Blank expressions are not allowed in interpolated strings', input, `at column ${i} in`, location);
14026
+ expressions.push('$implicit');
14027
+ }
14028
+ offsets.push(exprStart);
14029
+ expressionSpans.push({ start: fullStart, end: fullEnd });
14030
+ i = fullEnd;
14031
+ atInterpolation = false;
14032
+ }
14033
+ }
14034
+ if (!atInterpolation) {
14035
+ // If we are now at a text section, add the remaining content as a raw string.
14036
+ if (extendLastString) {
14037
+ strings[strings.length - 1] += input.substring(i);
14038
+ stringSpans[stringSpans.length - 1].end = input.length;
13989
14039
  }
13990
14040
  else {
13991
- this._reportError('Blank expressions are not allowed in interpolated strings', input, `at column ${this._findInterpolationErrorColumn(parts, i, interpolationConfig)} in`, location);
13992
- expressions.push('$implicit');
13993
- offsets.push(offset);
13994
- expressionSpans.push({ start: offset, end: offset });
14041
+ strings.push(input.substring(i));
14042
+ stringSpans.push({ start: i, end: input.length });
13995
14043
  }
13996
14044
  }
13997
- return new SplitInterpolation(strings, stringSpans, expressions, expressionSpans, offsets);
14045
+ return expressions.length === 0 ?
14046
+ null :
14047
+ new SplitInterpolation(strings, stringSpans, expressions, expressionSpans, offsets);
13998
14048
  }
13999
14049
  wrapLiteralPrimitive(input, location, absoluteOffset) {
14000
14050
  const span = new ParseSpan(0, input == null ? 0 : input.length);
@@ -14043,6 +14093,19 @@ define(['exports', 'os', 'typescript', 'fs', 'constants', 'stream', 'util', 'ass
14043
14093
  this.simpleExpressionChecker = IvySimpleExpressionChecker; //
14044
14094
  }
14045
14095
  }
14096
+ /** Describes a stateful context an expression parser is in. */
14097
+ var ParseContextFlags;
14098
+ (function (ParseContextFlags) {
14099
+ ParseContextFlags[ParseContextFlags["None"] = 0] = "None";
14100
+ /**
14101
+ * A Writable context is one in which a value may be written to an lvalue.
14102
+ * For example, after we see a property access, we may expect a write to the
14103
+ * property via the "=" operator.
14104
+ * prop
14105
+ * ^ possible "=" after
14106
+ */
14107
+ ParseContextFlags[ParseContextFlags["Writable"] = 1] = "Writable";
14108
+ })(ParseContextFlags || (ParseContextFlags = {}));
14046
14109
  class _ParseAST {
14047
14110
  constructor(input, location, absoluteOffset, tokens, inputLength, parseAction, errors, offset) {
14048
14111
  this.input = input;
@@ -14056,6 +14119,7 @@ define(['exports', 'os', 'typescript', 'fs', 'constants', 'stream', 'util', 'ass
14056
14119
  this.rparensExpected = 0;
14057
14120
  this.rbracketsExpected = 0;
14058
14121
  this.rbracesExpected = 0;
14122
+ this.context = ParseContextFlags.None;
14059
14123
  // Cache of expression start and input indeces to the absolute source span they map to, used to
14060
14124
  // prevent creating superfluous source spans in `sourceSpan`.
14061
14125
  // A serial of the expression start and input index is used for mapping because both are stateful
@@ -14116,6 +14180,15 @@ define(['exports', 'os', 'typescript', 'fs', 'constants', 'stream', 'util', 'ass
14116
14180
  advance() {
14117
14181
  this.index++;
14118
14182
  }
14183
+ /**
14184
+ * Executes a callback in the provided context.
14185
+ */
14186
+ withContext(context, cb) {
14187
+ this.context |= context;
14188
+ const ret = cb();
14189
+ this.context ^= context;
14190
+ return ret;
14191
+ }
14119
14192
  consumeOptionalCharacter(code) {
14120
14193
  if (this.next.isCharacter(code)) {
14121
14194
  this.advance();
@@ -14131,6 +14204,12 @@ define(['exports', 'os', 'typescript', 'fs', 'constants', 'stream', 'util', 'ass
14131
14204
  peekKeywordAs() {
14132
14205
  return this.next.isKeywordAs();
14133
14206
  }
14207
+ /**
14208
+ * Consumes an expected character, otherwise emits an error about the missing expected character
14209
+ * and skips over the token stream until reaching a recoverable point.
14210
+ *
14211
+ * See `this.error` and `this.skip` for more details.
14212
+ */
14134
14213
  expectCharacter(code) {
14135
14214
  if (this.consumeOptionalCharacter(code))
14136
14215
  return;
@@ -14366,17 +14445,23 @@ define(['exports', 'os', 'typescript', 'fs', 'constants', 'stream', 'util', 'ass
14366
14445
  result = this.parseAccessMemberOrMethodCall(result, true);
14367
14446
  }
14368
14447
  else if (this.consumeOptionalCharacter($LBRACKET)) {
14369
- this.rbracketsExpected++;
14370
- const key = this.parsePipe();
14371
- this.rbracketsExpected--;
14372
- this.expectCharacter($RBRACKET);
14373
- if (this.consumeOptionalOperator('=')) {
14374
- const value = this.parseConditional();
14375
- result = new KeyedWrite(this.span(resultStart), this.sourceSpan(resultStart), result, key, value);
14376
- }
14377
- else {
14378
- result = new KeyedRead(this.span(resultStart), this.sourceSpan(resultStart), result, key);
14379
- }
14448
+ this.withContext(ParseContextFlags.Writable, () => {
14449
+ this.rbracketsExpected++;
14450
+ const key = this.parsePipe();
14451
+ if (key instanceof EmptyExpr) {
14452
+ this.error(`Key access cannot be empty`);
14453
+ }
14454
+ this.rbracketsExpected--;
14455
+ this.expectCharacter($RBRACKET);
14456
+ if (this.consumeOptionalOperator('=')) {
14457
+ const value = this.parseConditional();
14458
+ result = new KeyedWrite(this.span(resultStart), this.sourceSpan(resultStart), result, key, value);
14459
+ }
14460
+ else {
14461
+ result =
14462
+ new KeyedRead(this.span(resultStart), this.sourceSpan(resultStart), result, key);
14463
+ }
14464
+ });
14380
14465
  }
14381
14466
  else if (this.consumeOptionalCharacter($LPAREN)) {
14382
14467
  this.rparensExpected++;
@@ -14715,6 +14800,10 @@ define(['exports', 'os', 'typescript', 'fs', 'constants', 'stream', 'util', 'ass
14715
14800
  consumeStatementTerminator() {
14716
14801
  this.consumeOptionalCharacter($SEMICOLON) || this.consumeOptionalCharacter($COMMA);
14717
14802
  }
14803
+ /**
14804
+ * Records an error and skips over the token stream until reaching a recoverable point. See
14805
+ * `this.skip` for more details on token skipping.
14806
+ */
14718
14807
  error(message, index = null) {
14719
14808
  this.errors.push(new ParserError(message, this.input, this.locationText(index), this.location));
14720
14809
  this.skip();
@@ -14725,24 +14814,32 @@ define(['exports', 'os', 'typescript', 'fs', 'constants', 'stream', 'util', 'ass
14725
14814
  return (index < this.tokens.length) ? `at column ${this.tokens[index].index + 1} in` :
14726
14815
  `at the end of the expression`;
14727
14816
  }
14728
- // Error recovery should skip tokens until it encounters a recovery point. skip() treats
14729
- // the end of input and a ';' as unconditionally a recovery point. It also treats ')',
14730
- // '}' and ']' as conditional recovery points if one of calling productions is expecting
14731
- // one of these symbols. This allows skip() to recover from errors such as '(a.) + 1' allowing
14732
- // more of the AST to be retained (it doesn't skip any tokens as the ')' is retained because
14733
- // of the '(' begins an '(' <expr> ')' production). The recovery points of grouping symbols
14734
- // must be conditional as they must be skipped if none of the calling productions are not
14735
- // expecting the closing token else we will never make progress in the case of an
14736
- // extraneous group closing symbol (such as a stray ')'). This is not the case for ';' because
14737
- // parseChain() is always the root production and it expects a ';'.
14738
- // If a production expects one of these token it increments the corresponding nesting count,
14739
- // and then decrements it just prior to checking if the token is in the input.
14817
+ /**
14818
+ * Error recovery should skip tokens until it encounters a recovery point. skip() treats
14819
+ * the end of input and a ';' as unconditionally a recovery point. It also treats ')',
14820
+ * '}' and ']' as conditional recovery points if one of calling productions is expecting
14821
+ * one of these symbols. This allows skip() to recover from errors such as '(a.) + 1' allowing
14822
+ * more of the AST to be retained (it doesn't skip any tokens as the ')' is retained because
14823
+ * of the '(' begins an '(' <expr> ')' production). The recovery points of grouping symbols
14824
+ * must be conditional as they must be skipped if none of the calling productions are not
14825
+ * expecting the closing token else we will never make progress in the case of an
14826
+ * extraneous group closing symbol (such as a stray ')'). This is not the case for ';' because
14827
+ * parseChain() is always the root production and it expects a ';'.
14828
+ *
14829
+ * Furthermore, the presence of a stateful context can add more recovery points.
14830
+ * - in a `Writable` context, we are able to recover after seeing the `=` operator, which
14831
+ * signals the presence of an independent rvalue expression following the `=` operator.
14832
+ *
14833
+ * If a production expects one of these token it increments the corresponding nesting count,
14834
+ * and then decrements it just prior to checking if the token is in the input.
14835
+ */
14740
14836
  skip() {
14741
14837
  let n = this.next;
14742
14838
  while (this.index < this.tokens.length && !n.isCharacter($SEMICOLON) &&
14743
14839
  (this.rparensExpected <= 0 || !n.isCharacter($RPAREN)) &&
14744
14840
  (this.rbracesExpected <= 0 || !n.isCharacter($RBRACE)) &&
14745
- (this.rbracketsExpected <= 0 || !n.isCharacter($RBRACKET))) {
14841
+ (this.rbracketsExpected <= 0 || !n.isCharacter($RBRACKET)) &&
14842
+ (!(this.context & ParseContextFlags.Writable) || !n.isOperator('='))) {
14746
14843
  if (this.next.isError()) {
14747
14844
  this.errors.push(new ParserError(this.next.toString(), this.input, this.locationText(), this.location));
14748
14845
  }
@@ -19066,7 +19163,7 @@ define(['exports', 'os', 'typescript', 'fs', 'constants', 'stream', 'util', 'ass
19066
19163
  * Use of this source code is governed by an MIT-style license that can be
19067
19164
  * found in the LICENSE file at https://angular.io/license
19068
19165
  */
19069
- const VERSION$1 = new Version('10.1.3');
19166
+ const VERSION$1 = new Version('10.2.0');
19070
19167
 
19071
19168
  /**
19072
19169
  * @license
@@ -19659,7 +19756,7 @@ define(['exports', 'os', 'typescript', 'fs', 'constants', 'stream', 'util', 'ass
19659
19756
  * Use of this source code is governed by an MIT-style license that can be
19660
19757
  * found in the LICENSE file at https://angular.io/license
19661
19758
  */
19662
- const VERSION$2 = new Version('10.1.3');
19759
+ const VERSION$2 = new Version('10.2.0');
19663
19760
 
19664
19761
  /**
19665
19762
  * @license
@@ -20166,11 +20263,7 @@ define(['exports', 'os', 'typescript', 'fs', 'constants', 'stream', 'util', 'ass
20166
20263
  }
20167
20264
  const exportMap = new Map();
20168
20265
  exports.forEach((declaration, name) => {
20169
- // It's okay to skip inline declarations, since by definition they're not target-able with a
20170
- // ts.Declaration anyway.
20171
- if (declaration.node !== null) {
20172
- exportMap.set(declaration.node, name);
20173
- }
20266
+ exportMap.set(declaration.node, name);
20174
20267
  });
20175
20268
  return exportMap;
20176
20269
  }
@@ -20842,6 +20935,13 @@ define(['exports', 'os', 'typescript', 'fs', 'constants', 'stream', 'util', 'ass
20842
20935
  */
20843
20936
  KnownDeclaration[KnownDeclaration["TsHelperSpreadArrays"] = 3] = "TsHelperSpreadArrays";
20844
20937
  })(KnownDeclaration || (KnownDeclaration = {}));
20938
+ /**
20939
+ * Returns true if the `decl` is a `ConcreteDeclaration` (ie. that its `node` property is a
20940
+ * `ts.Declaration`).
20941
+ */
20942
+ function isConcreteDeclaration(decl) {
20943
+ return decl.kind === 0 /* Concrete */;
20944
+ }
20845
20945
 
20846
20946
  /**
20847
20947
  * @license
@@ -21093,7 +21193,10 @@ define(['exports', 'os', 'typescript', 'fs', 'constants', 'stream', 'util', 'ass
21093
21193
  * found in the LICENSE file at https://angular.io/license
21094
21194
  */
21095
21195
  function isNamedClassDeclaration(node) {
21096
- return ts.isClassDeclaration(node) && (node.name !== undefined);
21196
+ return ts.isClassDeclaration(node) && isIdentifier$1(node.name);
21197
+ }
21198
+ function isIdentifier$1(node) {
21199
+ return node !== undefined && ts.isIdentifier(node);
21097
21200
  }
21098
21201
 
21099
21202
  /**
@@ -21184,13 +21287,13 @@ define(['exports', 'os', 'typescript', 'fs', 'constants', 'stream', 'util', 'ass
21184
21287
  if (!ts.isSourceFile(node)) {
21185
21288
  throw new Error(`getExportsOfModule() called on non-SourceFile in TS code`);
21186
21289
  }
21187
- const map = new Map();
21188
21290
  // Reflect the module to a Symbol, and use getExportsOfModule() to get a list of exported
21189
21291
  // Symbols.
21190
21292
  const symbol = this.checker.getSymbolAtLocation(node);
21191
21293
  if (symbol === undefined) {
21192
21294
  return null;
21193
21295
  }
21296
+ const map = new Map();
21194
21297
  this.checker.getExportsOfModule(symbol).forEach(exportSymbol => {
21195
21298
  // Map each exported Symbol to a Declaration and add it to the map.
21196
21299
  const decl = this.getDeclarationOfSymbol(exportSymbol, null);
@@ -21369,6 +21472,7 @@ define(['exports', 'os', 'typescript', 'fs', 'constants', 'stream', 'util', 'ass
21369
21472
  known: null,
21370
21473
  viaModule,
21371
21474
  identity: null,
21475
+ kind: 0 /* Concrete */,
21372
21476
  };
21373
21477
  }
21374
21478
  else if (symbol.declarations !== undefined && symbol.declarations.length > 0) {
@@ -21377,6 +21481,7 @@ define(['exports', 'os', 'typescript', 'fs', 'constants', 'stream', 'util', 'ass
21377
21481
  known: null,
21378
21482
  viaModule,
21379
21483
  identity: null,
21484
+ kind: 0 /* Concrete */,
21380
21485
  };
21381
21486
  }
21382
21487
  else {
@@ -22851,12 +22956,7 @@ define(['exports', 'os', 'typescript', 'fs', 'constants', 'stream', 'util', 'ass
22851
22956
  return this.getResolvedEnum(decl.node, decl.identity.enumMembers, context);
22852
22957
  }
22853
22958
  const declContext = Object.assign(Object.assign({}, context), joinModuleContext(context, node, decl));
22854
- // The identifier's declaration is either concrete (a ts.Declaration exists for it) or inline
22855
- // (a direct reference to a ts.Expression).
22856
- // TODO(alxhub): remove cast once TS is upgraded in g3.
22857
- const result = decl.node !== null ?
22858
- this.visitDeclaration(decl.node, declContext) :
22859
- this.visitExpression(decl.expression, declContext);
22959
+ const result = this.visitAmbiguousDeclaration(decl, declContext);
22860
22960
  if (result instanceof Reference$1) {
22861
22961
  // Only record identifiers to non-synthetic references. Synthetic references may not have the
22862
22962
  // same value at runtime as they do at compile time, so it's not legal to refer to them by the
@@ -22957,12 +23057,16 @@ define(['exports', 'os', 'typescript', 'fs', 'constants', 'stream', 'util', 'ass
22957
23057
  }
22958
23058
  const declContext = Object.assign(Object.assign({}, context), joinModuleContext(context, node, decl));
22959
23059
  // Visit both concrete and inline declarations.
22960
- // TODO(alxhub): remove cast once TS is upgraded in g3.
22961
- return decl.node !== null ?
22962
- this.visitDeclaration(decl.node, declContext) :
22963
- this.visitExpression(decl.expression, declContext);
23060
+ return this.visitAmbiguousDeclaration(decl, declContext);
22964
23061
  });
22965
23062
  }
23063
+ visitAmbiguousDeclaration(decl, declContext) {
23064
+ return decl.kind === 1 /* Inline */ && decl.implementation !== undefined ?
23065
+ // Inline declarations with an `implementation` should be visited as expressions
23066
+ this.visitExpression(decl.implementation, declContext) :
23067
+ // Otherwise just visit the declaration `node`
23068
+ this.visitDeclaration(decl.node, declContext);
23069
+ }
22966
23070
  accessHelper(node, lhs, rhs, context) {
22967
23071
  const strIndex = `${rhs}`;
22968
23072
  if (lhs instanceof Map) {
@@ -23310,13 +23414,6 @@ define(['exports', 'os', 'typescript', 'fs', 'constants', 'stream', 'util', 'ass
23310
23414
  return null;
23311
23415
  }
23312
23416
  }
23313
- /**
23314
- * Helper type guard to workaround a narrowing limitation in g3, where testing for
23315
- * `decl.node !== null` would not narrow `decl` to be of type `ConcreteDeclaration`.
23316
- */
23317
- function isConcreteDeclaration(decl) {
23318
- return decl.node !== null;
23319
- }
23320
23417
 
23321
23418
  /**
23322
23419
  * @license
@@ -26571,10 +26668,16 @@ Either add the @Injectable() decorator to '${provider.node.name
26571
26668
  }
26572
26669
  reflectObjectLiteral(queryData).forEach((queryExpr, propertyName) => {
26573
26670
  queryExpr = unwrapExpression(queryExpr);
26574
- if (!ts.isNewExpression(queryExpr) || !ts.isIdentifier(queryExpr.expression)) {
26671
+ if (!ts.isNewExpression(queryExpr)) {
26672
+ throw new FatalDiagnosticError(ErrorCode.VALUE_HAS_WRONG_TYPE, queryData, 'Decorator query metadata must be an instance of a query type');
26673
+ }
26674
+ const queryType = ts.isPropertyAccessExpression(queryExpr.expression) ?
26675
+ queryExpr.expression.name :
26676
+ queryExpr.expression;
26677
+ if (!ts.isIdentifier(queryType)) {
26575
26678
  throw new FatalDiagnosticError(ErrorCode.VALUE_HAS_WRONG_TYPE, queryData, 'Decorator query metadata must be an instance of a query type');
26576
26679
  }
26577
- const type = reflector.getImportOfIdentifier(queryExpr.expression);
26680
+ const type = reflector.getImportOfIdentifier(queryType);
26578
26681
  if (type === null || (!isCore && type.from !== '@angular/core') ||
26579
26682
  !QUERY_TYPES.has(type.name)) {
26580
26683
  throw new FatalDiagnosticError(ErrorCode.VALUE_HAS_WRONG_TYPE, queryData, 'Decorator query metadata must be an instance of a query type');
@@ -28100,7 +28203,7 @@ Either add the @Injectable() decorator to '${provider.node.name
28100
28203
  else {
28101
28204
  let typeRef = valueRef;
28102
28205
  let typeNode = this.reflector.getDtsDeclaration(typeRef.node);
28103
- if (typeNode !== null && ts.isClassDeclaration(typeNode)) {
28206
+ if (typeNode !== null && isNamedClassDeclaration(typeNode)) {
28104
28207
  typeRef = new Reference$1(typeNode);
28105
28208
  }
28106
28209
  return toR3Reference(valueRef, typeRef, valueContext, typeContext, this.refEmitter);
@@ -28180,7 +28283,7 @@ Either add the @Injectable() decorator to '${provider.node.name
28180
28283
  }
28181
28284
  return null;
28182
28285
  }
28183
- // Verify that a `ts.Declaration` reference is a `ClassDeclaration` reference.
28286
+ // Verify that a "Declaration" reference is a `ClassDeclaration` reference.
28184
28287
  isClassDeclarationReference(ref) {
28185
28288
  return this.reflector.isClass(ref.node);
28186
28289
  }
@@ -28202,7 +28305,7 @@ Either add the @Injectable() decorator to '${provider.node.name
28202
28305
  // Recurse into nested arrays.
28203
28306
  refList.push(...this.resolveTypeList(expr, entry, className, arrayName));
28204
28307
  }
28205
- else if (isDeclarationReference(entry)) {
28308
+ else if (entry instanceof Reference$1) {
28206
28309
  if (!this.isClassDeclarationReference(entry)) {
28207
28310
  throw createValueHasWrongTypeError(entry.node, entry, `Value at position ${idx} in the NgModule.${arrayName} of ${className} is not a class`);
28208
28311
  }
@@ -28220,11 +28323,6 @@ Either add the @Injectable() decorator to '${provider.node.name
28220
28323
  return !compilation.directives.some(directive => directive.ref.node === node) &&
28221
28324
  !compilation.pipes.some(pipe => pipe.ref.node === node);
28222
28325
  }
28223
- function isDeclarationReference(ref) {
28224
- return ref instanceof Reference$1 &&
28225
- (ts.isClassDeclaration(ref.node) || ts.isFunctionDeclaration(ref.node) ||
28226
- ts.isVariableDeclaration(ref.node));
28227
- }
28228
28326
 
28229
28327
  /**
28230
28328
  * @license
@@ -29567,13 +29665,6 @@ Either add the @Injectable() decorator to '${provider.node.name
29567
29665
  node.modifiers.some(mod => mod.kind === ts.SyntaxKind.StaticKeyword);
29568
29666
  }
29569
29667
 
29570
- /**
29571
- * @license
29572
- * Copyright Google LLC All Rights Reserved.
29573
- *
29574
- * Use of this source code is governed by an MIT-style license that can be
29575
- * found in the LICENSE file at https://angular.io/license
29576
- */
29577
29668
  const NOOP_PERF_RECORDER = {
29578
29669
  enabled: false,
29579
29670
  mark: (name, node, category, detail) => { },
@@ -33671,6 +33762,9 @@ Either add the @Injectable() decorator to '${provider.node.name
33671
33762
  this.templateCtxOpMap.set(node, ctxIndex);
33672
33763
  this.opQueue.push(new TcbTemplateBodyOp(this.tcb, this, node));
33673
33764
  }
33765
+ else if (this.tcb.env.config.alwaysCheckSchemaInTemplateBodies) {
33766
+ this.appendDeepSchemaChecks(node.children);
33767
+ }
33674
33768
  this.checkReferencesOfNode(node);
33675
33769
  }
33676
33770
  else if (node instanceof BoundText) {
@@ -33752,6 +33846,31 @@ Either add the @Injectable() decorator to '${provider.node.name
33752
33846
  this.opQueue.push(new TcbUnclaimedOutputsOp(this.tcb, this, node, claimedOutputs));
33753
33847
  }
33754
33848
  }
33849
+ appendDeepSchemaChecks(nodes) {
33850
+ for (const node of nodes) {
33851
+ if (!(node instanceof Element || node instanceof Template)) {
33852
+ continue;
33853
+ }
33854
+ if (node instanceof Element) {
33855
+ const claimedInputs = new Set();
33856
+ const directives = this.tcb.boundTarget.getDirectivesOfNode(node);
33857
+ let hasDirectives;
33858
+ if (directives === null || directives.length === 0) {
33859
+ hasDirectives = false;
33860
+ }
33861
+ else {
33862
+ hasDirectives = true;
33863
+ for (const dir of directives) {
33864
+ for (const propertyName of dir.inputs.propertyNames) {
33865
+ claimedInputs.add(propertyName);
33866
+ }
33867
+ }
33868
+ }
33869
+ this.opQueue.push(new TcbDomSchemaCheckerOp(this.tcb, node, !hasDirectives, claimedInputs));
33870
+ }
33871
+ this.appendDeepSchemaChecks(node.children);
33872
+ }
33873
+ }
33755
33874
  }
33756
33875
  /**
33757
33876
  * Create the `ctx` parameter to the top-level TCB function.
@@ -35328,6 +35447,7 @@ Either add the @Injectable() decorator to '${provider.node.name
35328
35447
  applyTemplateContextGuards: strictTemplates,
35329
35448
  checkQueries: false,
35330
35449
  checkTemplateBodies: true,
35450
+ alwaysCheckSchemaInTemplateBodies: true,
35331
35451
  checkTypeOfInputBindings: strictTemplates,
35332
35452
  honorAccessModifiersForInputBindings: false,
35333
35453
  strictNullInputBindings: strictTemplates,
@@ -35356,6 +35476,9 @@ Either add the @Injectable() decorator to '${provider.node.name
35356
35476
  applyTemplateContextGuards: false,
35357
35477
  checkQueries: false,
35358
35478
  checkTemplateBodies: false,
35479
+ // Enable deep schema checking in "basic" template type-checking mode only if Closure
35480
+ // compilation is requested, which is a good proxy for "only in google3".
35481
+ alwaysCheckSchemaInTemplateBodies: this.closureCompilerEnabled,
35359
35482
  checkTypeOfInputBindings: false,
35360
35483
  strictNullInputBindings: false,
35361
35484
  honorAccessModifiersForInputBindings: false,