@angular/language-service 12.2.11 → 12.2.15

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.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Angular v12.2.11
2
+ * @license Angular v12.2.15
3
3
  * Copyright Google LLC All Rights Reserved.
4
4
  * License: MIT
5
5
  */
@@ -2380,492 +2380,715 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
2380
2380
  * Use of this source code is governed by an MIT-style license that can be
2381
2381
  * found in the LICENSE file at https://angular.io/license
2382
2382
  */
2383
- /**
2384
- * This is an R3 `Node`-like wrapper for a raw `html.Comment` node. We do not currently
2385
- * require the implementation of a visitor for Comments as they are only collected at
2386
- * the top-level of the R3 AST, and only if `Render3ParseOptions['collectCommentNodes']`
2387
- * is true.
2388
- */
2389
- class Comment {
2390
- constructor(value, sourceSpan) {
2391
- this.value = value;
2392
- this.sourceSpan = sourceSpan;
2393
- }
2394
- visit(_visitor) {
2395
- throw new Error('visit() not implemented for Comment');
2383
+ // https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit
2384
+ const VERSION = 3;
2385
+ const JS_B64_PREFIX = '# sourceMappingURL=data:application/json;base64,';
2386
+ class SourceMapGenerator {
2387
+ constructor(file = null) {
2388
+ this.file = file;
2389
+ this.sourcesContent = new Map();
2390
+ this.lines = [];
2391
+ this.lastCol0 = 0;
2392
+ this.hasMappings = false;
2396
2393
  }
2397
- }
2398
- class Text {
2399
- constructor(value, sourceSpan) {
2400
- this.value = value;
2401
- this.sourceSpan = sourceSpan;
2394
+ // The content is `null` when the content is expected to be loaded using the URL
2395
+ addSource(url, content = null) {
2396
+ if (!this.sourcesContent.has(url)) {
2397
+ this.sourcesContent.set(url, content);
2398
+ }
2399
+ return this;
2402
2400
  }
2403
- visit(visitor) {
2404
- return visitor.visitText(this);
2401
+ addLine() {
2402
+ this.lines.push([]);
2403
+ this.lastCol0 = 0;
2404
+ return this;
2405
2405
  }
2406
- }
2407
- class BoundText {
2408
- constructor(value, sourceSpan, i18n) {
2409
- this.value = value;
2410
- this.sourceSpan = sourceSpan;
2411
- this.i18n = i18n;
2406
+ addMapping(col0, sourceUrl, sourceLine0, sourceCol0) {
2407
+ if (!this.currentLine) {
2408
+ throw new Error(`A line must be added before mappings can be added`);
2409
+ }
2410
+ if (sourceUrl != null && !this.sourcesContent.has(sourceUrl)) {
2411
+ throw new Error(`Unknown source file "${sourceUrl}"`);
2412
+ }
2413
+ if (col0 == null) {
2414
+ throw new Error(`The column in the generated code must be provided`);
2415
+ }
2416
+ if (col0 < this.lastCol0) {
2417
+ throw new Error(`Mapping should be added in output order`);
2418
+ }
2419
+ if (sourceUrl && (sourceLine0 == null || sourceCol0 == null)) {
2420
+ throw new Error(`The source location must be provided when a source url is provided`);
2421
+ }
2422
+ this.hasMappings = true;
2423
+ this.lastCol0 = col0;
2424
+ this.currentLine.push({ col0, sourceUrl, sourceLine0, sourceCol0 });
2425
+ return this;
2412
2426
  }
2413
- visit(visitor) {
2414
- return visitor.visitBoundText(this);
2427
+ /**
2428
+ * @internal strip this from published d.ts files due to
2429
+ * https://github.com/microsoft/TypeScript/issues/36216
2430
+ */
2431
+ get currentLine() {
2432
+ return this.lines.slice(-1)[0];
2415
2433
  }
2416
- }
2417
- /**
2418
- * Represents a text attribute in the template.
2419
- *
2420
- * `valueSpan` may not be present in cases where there is no value `<div a></div>`.
2421
- * `keySpan` may also not be present for synthetic attributes from ICU expansions.
2422
- */
2423
- class TextAttribute {
2424
- constructor(name, value, sourceSpan, keySpan, valueSpan, i18n) {
2425
- this.name = name;
2426
- this.value = value;
2427
- this.sourceSpan = sourceSpan;
2428
- this.keySpan = keySpan;
2429
- this.valueSpan = valueSpan;
2430
- this.i18n = i18n;
2434
+ toJSON() {
2435
+ if (!this.hasMappings) {
2436
+ return null;
2437
+ }
2438
+ const sourcesIndex = new Map();
2439
+ const sources = [];
2440
+ const sourcesContent = [];
2441
+ Array.from(this.sourcesContent.keys()).forEach((url, i) => {
2442
+ sourcesIndex.set(url, i);
2443
+ sources.push(url);
2444
+ sourcesContent.push(this.sourcesContent.get(url) || null);
2445
+ });
2446
+ let mappings = '';
2447
+ let lastCol0 = 0;
2448
+ let lastSourceIndex = 0;
2449
+ let lastSourceLine0 = 0;
2450
+ let lastSourceCol0 = 0;
2451
+ this.lines.forEach(segments => {
2452
+ lastCol0 = 0;
2453
+ mappings += segments
2454
+ .map(segment => {
2455
+ // zero-based starting column of the line in the generated code
2456
+ let segAsStr = toBase64VLQ(segment.col0 - lastCol0);
2457
+ lastCol0 = segment.col0;
2458
+ if (segment.sourceUrl != null) {
2459
+ // zero-based index into the “sources” list
2460
+ segAsStr +=
2461
+ toBase64VLQ(sourcesIndex.get(segment.sourceUrl) - lastSourceIndex);
2462
+ lastSourceIndex = sourcesIndex.get(segment.sourceUrl);
2463
+ // the zero-based starting line in the original source
2464
+ segAsStr += toBase64VLQ(segment.sourceLine0 - lastSourceLine0);
2465
+ lastSourceLine0 = segment.sourceLine0;
2466
+ // the zero-based starting column in the original source
2467
+ segAsStr += toBase64VLQ(segment.sourceCol0 - lastSourceCol0);
2468
+ lastSourceCol0 = segment.sourceCol0;
2469
+ }
2470
+ return segAsStr;
2471
+ })
2472
+ .join(',');
2473
+ mappings += ';';
2474
+ });
2475
+ mappings = mappings.slice(0, -1);
2476
+ return {
2477
+ 'file': this.file || '',
2478
+ 'version': VERSION,
2479
+ 'sourceRoot': '',
2480
+ 'sources': sources,
2481
+ 'sourcesContent': sourcesContent,
2482
+ 'mappings': mappings,
2483
+ };
2431
2484
  }
2432
- visit(visitor) {
2433
- return visitor.visitTextAttribute(this);
2485
+ toJsComment() {
2486
+ return this.hasMappings ? '//' + JS_B64_PREFIX + toBase64String(JSON.stringify(this, null, 0)) :
2487
+ '';
2434
2488
  }
2435
2489
  }
2436
- class BoundAttribute {
2437
- constructor(name, type, securityContext, value, unit, sourceSpan, keySpan, valueSpan, i18n) {
2438
- this.name = name;
2439
- this.type = type;
2440
- this.securityContext = securityContext;
2441
- this.value = value;
2442
- this.unit = unit;
2443
- this.sourceSpan = sourceSpan;
2444
- this.keySpan = keySpan;
2445
- this.valueSpan = valueSpan;
2446
- this.i18n = i18n;
2490
+ function toBase64String(value) {
2491
+ let b64 = '';
2492
+ const encoded = utf8Encode(value);
2493
+ for (let i = 0; i < encoded.length;) {
2494
+ const i1 = encoded[i++];
2495
+ const i2 = i < encoded.length ? encoded[i++] : null;
2496
+ const i3 = i < encoded.length ? encoded[i++] : null;
2497
+ b64 += toBase64Digit(i1 >> 2);
2498
+ b64 += toBase64Digit(((i1 & 3) << 4) | (i2 === null ? 0 : i2 >> 4));
2499
+ b64 += i2 === null ? '=' : toBase64Digit(((i2 & 15) << 2) | (i3 === null ? 0 : i3 >> 6));
2500
+ b64 += i2 === null || i3 === null ? '=' : toBase64Digit(i3 & 63);
2447
2501
  }
2448
- static fromBoundElementProperty(prop, i18n) {
2449
- if (prop.keySpan === undefined) {
2450
- throw new Error(`Unexpected state: keySpan must be defined for bound attributes but was not for ${prop.name}: ${prop.sourceSpan}`);
2502
+ return b64;
2503
+ }
2504
+ function toBase64VLQ(value) {
2505
+ value = value < 0 ? ((-value) << 1) + 1 : value << 1;
2506
+ let out = '';
2507
+ do {
2508
+ let digit = value & 31;
2509
+ value = value >> 5;
2510
+ if (value > 0) {
2511
+ digit = digit | 32;
2451
2512
  }
2452
- return new BoundAttribute(prop.name, prop.type, prop.securityContext, prop.value, prop.unit, prop.sourceSpan, prop.keySpan, prop.valueSpan, i18n);
2453
- }
2454
- visit(visitor) {
2455
- return visitor.visitBoundAttribute(this);
2513
+ out += toBase64Digit(digit);
2514
+ } while (value > 0);
2515
+ return out;
2516
+ }
2517
+ const B64_DIGITS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
2518
+ function toBase64Digit(value) {
2519
+ if (value < 0 || value >= 64) {
2520
+ throw new Error(`Can only encode value in the range [0, 63]`);
2456
2521
  }
2522
+ return B64_DIGITS[value];
2457
2523
  }
2458
- class BoundEvent {
2459
- constructor(name, type, handler, target, phase, sourceSpan, handlerSpan, keySpan) {
2460
- this.name = name;
2461
- this.type = type;
2462
- this.handler = handler;
2463
- this.target = target;
2464
- this.phase = phase;
2465
- this.sourceSpan = sourceSpan;
2466
- this.handlerSpan = handlerSpan;
2467
- this.keySpan = keySpan;
2524
+
2525
+ /**
2526
+ * @license
2527
+ * Copyright Google LLC All Rights Reserved.
2528
+ *
2529
+ * Use of this source code is governed by an MIT-style license that can be
2530
+ * found in the LICENSE file at https://angular.io/license
2531
+ */
2532
+ const _SINGLE_QUOTE_ESCAPE_STRING_RE = /'|\\|\n|\r|\$/g;
2533
+ const _LEGAL_IDENTIFIER_RE = /^[$A-Z_][0-9A-Z_$]*$/i;
2534
+ const _INDENT_WITH = ' ';
2535
+ const CATCH_ERROR_VAR$1 = variable('error', null, null);
2536
+ const CATCH_STACK_VAR$1 = variable('stack', null, null);
2537
+ class _EmittedLine {
2538
+ constructor(indent) {
2539
+ this.indent = indent;
2540
+ this.partsLength = 0;
2541
+ this.parts = [];
2542
+ this.srcSpans = [];
2468
2543
  }
2469
- static fromParsedEvent(event) {
2470
- const target = event.type === 0 /* Regular */ ? event.targetOrPhase : null;
2471
- const phase = event.type === 1 /* Animation */ ? event.targetOrPhase : null;
2472
- if (event.keySpan === undefined) {
2473
- throw new Error(`Unexpected state: keySpan must be defined for bound event but was not for ${event.name}: ${event.sourceSpan}`);
2474
- }
2475
- return new BoundEvent(event.name, event.type, event.handler, target, phase, event.sourceSpan, event.handlerSpan, event.keySpan);
2544
+ }
2545
+ class EmitterVisitorContext {
2546
+ constructor(_indent) {
2547
+ this._indent = _indent;
2548
+ this._classes = [];
2549
+ this._preambleLineCount = 0;
2550
+ this._lines = [new _EmittedLine(_indent)];
2476
2551
  }
2477
- visit(visitor) {
2478
- return visitor.visitBoundEvent(this);
2552
+ static createRoot() {
2553
+ return new EmitterVisitorContext(0);
2479
2554
  }
2480
- }
2481
- class Element {
2482
- constructor(name, attributes, inputs, outputs, children, references, sourceSpan, startSourceSpan, endSourceSpan, i18n) {
2483
- this.name = name;
2484
- this.attributes = attributes;
2485
- this.inputs = inputs;
2486
- this.outputs = outputs;
2487
- this.children = children;
2488
- this.references = references;
2489
- this.sourceSpan = sourceSpan;
2490
- this.startSourceSpan = startSourceSpan;
2491
- this.endSourceSpan = endSourceSpan;
2492
- this.i18n = i18n;
2555
+ /**
2556
+ * @internal strip this from published d.ts files due to
2557
+ * https://github.com/microsoft/TypeScript/issues/36216
2558
+ */
2559
+ get _currentLine() {
2560
+ return this._lines[this._lines.length - 1];
2493
2561
  }
2494
- visit(visitor) {
2495
- return visitor.visitElement(this);
2562
+ println(from, lastPart = '') {
2563
+ this.print(from || null, lastPart, true);
2496
2564
  }
2497
- }
2498
- class Template {
2499
- constructor(tagName, attributes, inputs, outputs, templateAttrs, children, references, variables, sourceSpan, startSourceSpan, endSourceSpan, i18n) {
2500
- this.tagName = tagName;
2501
- this.attributes = attributes;
2502
- this.inputs = inputs;
2503
- this.outputs = outputs;
2504
- this.templateAttrs = templateAttrs;
2505
- this.children = children;
2506
- this.references = references;
2507
- this.variables = variables;
2508
- this.sourceSpan = sourceSpan;
2509
- this.startSourceSpan = startSourceSpan;
2510
- this.endSourceSpan = endSourceSpan;
2511
- this.i18n = i18n;
2565
+ lineIsEmpty() {
2566
+ return this._currentLine.parts.length === 0;
2512
2567
  }
2513
- visit(visitor) {
2514
- return visitor.visitTemplate(this);
2568
+ lineLength() {
2569
+ return this._currentLine.indent * _INDENT_WITH.length + this._currentLine.partsLength;
2515
2570
  }
2516
- }
2517
- class Content {
2518
- constructor(selector, attributes, sourceSpan, i18n) {
2519
- this.selector = selector;
2520
- this.attributes = attributes;
2521
- this.sourceSpan = sourceSpan;
2522
- this.i18n = i18n;
2523
- this.name = 'ng-content';
2571
+ print(from, part, newLine = false) {
2572
+ if (part.length > 0) {
2573
+ this._currentLine.parts.push(part);
2574
+ this._currentLine.partsLength += part.length;
2575
+ this._currentLine.srcSpans.push(from && from.sourceSpan || null);
2576
+ }
2577
+ if (newLine) {
2578
+ this._lines.push(new _EmittedLine(this._indent));
2579
+ }
2524
2580
  }
2525
- visit(visitor) {
2526
- return visitor.visitContent(this);
2581
+ removeEmptyLastLine() {
2582
+ if (this.lineIsEmpty()) {
2583
+ this._lines.pop();
2584
+ }
2527
2585
  }
2528
- }
2529
- class Variable {
2530
- constructor(name, value, sourceSpan, keySpan, valueSpan) {
2531
- this.name = name;
2532
- this.value = value;
2533
- this.sourceSpan = sourceSpan;
2534
- this.keySpan = keySpan;
2535
- this.valueSpan = valueSpan;
2586
+ incIndent() {
2587
+ this._indent++;
2588
+ if (this.lineIsEmpty()) {
2589
+ this._currentLine.indent = this._indent;
2590
+ }
2536
2591
  }
2537
- visit(visitor) {
2538
- return visitor.visitVariable(this);
2592
+ decIndent() {
2593
+ this._indent--;
2594
+ if (this.lineIsEmpty()) {
2595
+ this._currentLine.indent = this._indent;
2596
+ }
2539
2597
  }
2540
- }
2541
- class Reference {
2542
- constructor(name, value, sourceSpan, keySpan, valueSpan) {
2543
- this.name = name;
2544
- this.value = value;
2545
- this.sourceSpan = sourceSpan;
2546
- this.keySpan = keySpan;
2547
- this.valueSpan = valueSpan;
2598
+ pushClass(clazz) {
2599
+ this._classes.push(clazz);
2548
2600
  }
2549
- visit(visitor) {
2550
- return visitor.visitReference(this);
2601
+ popClass() {
2602
+ return this._classes.pop();
2551
2603
  }
2552
- }
2553
- class Icu {
2554
- constructor(vars, placeholders, sourceSpan, i18n) {
2555
- this.vars = vars;
2556
- this.placeholders = placeholders;
2557
- this.sourceSpan = sourceSpan;
2558
- this.i18n = i18n;
2604
+ get currentClass() {
2605
+ return this._classes.length > 0 ? this._classes[this._classes.length - 1] : null;
2559
2606
  }
2560
- visit(visitor) {
2561
- return visitor.visitIcu(this);
2607
+ toSource() {
2608
+ return this.sourceLines
2609
+ .map(l => l.parts.length > 0 ? _createIndent(l.indent) + l.parts.join('') : '')
2610
+ .join('\n');
2562
2611
  }
2563
- }
2564
- function visitAll(visitor, nodes) {
2565
- const result = [];
2566
- if (visitor.visit) {
2567
- for (const node of nodes) {
2568
- const newNode = visitor.visit(node) || node.visit(visitor);
2612
+ toSourceMapGenerator(genFilePath, startsAtLine = 0) {
2613
+ const map = new SourceMapGenerator(genFilePath);
2614
+ let firstOffsetMapped = false;
2615
+ const mapFirstOffsetIfNeeded = () => {
2616
+ if (!firstOffsetMapped) {
2617
+ // Add a single space so that tools won't try to load the file from disk.
2618
+ // Note: We are using virtual urls like `ng:///`, so we have to
2619
+ // provide a content here.
2620
+ map.addSource(genFilePath, ' ').addMapping(0, genFilePath, 0, 0);
2621
+ firstOffsetMapped = true;
2622
+ }
2623
+ };
2624
+ for (let i = 0; i < startsAtLine; i++) {
2625
+ map.addLine();
2626
+ mapFirstOffsetIfNeeded();
2569
2627
  }
2628
+ this.sourceLines.forEach((line, lineIdx) => {
2629
+ map.addLine();
2630
+ const spans = line.srcSpans;
2631
+ const parts = line.parts;
2632
+ let col0 = line.indent * _INDENT_WITH.length;
2633
+ let spanIdx = 0;
2634
+ // skip leading parts without source spans
2635
+ while (spanIdx < spans.length && !spans[spanIdx]) {
2636
+ col0 += parts[spanIdx].length;
2637
+ spanIdx++;
2638
+ }
2639
+ if (spanIdx < spans.length && lineIdx === 0 && col0 === 0) {
2640
+ firstOffsetMapped = true;
2641
+ }
2642
+ else {
2643
+ mapFirstOffsetIfNeeded();
2644
+ }
2645
+ while (spanIdx < spans.length) {
2646
+ const span = spans[spanIdx];
2647
+ const source = span.start.file;
2648
+ const sourceLine = span.start.line;
2649
+ const sourceCol = span.start.col;
2650
+ map.addSource(source.url, source.content)
2651
+ .addMapping(col0, source.url, sourceLine, sourceCol);
2652
+ col0 += parts[spanIdx].length;
2653
+ spanIdx++;
2654
+ // assign parts without span or the same span to the previous segment
2655
+ while (spanIdx < spans.length && (span === spans[spanIdx] || !spans[spanIdx])) {
2656
+ col0 += parts[spanIdx].length;
2657
+ spanIdx++;
2658
+ }
2659
+ }
2660
+ });
2661
+ return map;
2570
2662
  }
2571
- else {
2572
- for (const node of nodes) {
2573
- const newNode = node.visit(visitor);
2574
- if (newNode) {
2575
- result.push(newNode);
2663
+ setPreambleLineCount(count) {
2664
+ return this._preambleLineCount = count;
2665
+ }
2666
+ spanOf(line, column) {
2667
+ const emittedLine = this._lines[line - this._preambleLineCount];
2668
+ if (emittedLine) {
2669
+ let columnsLeft = column - _createIndent(emittedLine.indent).length;
2670
+ for (let partIndex = 0; partIndex < emittedLine.parts.length; partIndex++) {
2671
+ const part = emittedLine.parts[partIndex];
2672
+ if (part.length > columnsLeft) {
2673
+ return emittedLine.srcSpans[partIndex];
2674
+ }
2675
+ columnsLeft -= part.length;
2576
2676
  }
2577
2677
  }
2678
+ return null;
2578
2679
  }
2579
- return result;
2580
- }
2581
-
2582
- /**
2583
- * @license
2584
- * Copyright Google LLC All Rights Reserved.
2585
- *
2586
- * Use of this source code is governed by an MIT-style license that can be
2587
- * found in the LICENSE file at https://angular.io/license
2588
- */
2589
- class Message {
2590
2680
  /**
2591
- * @param nodes message AST
2592
- * @param placeholders maps placeholder names to static content and their source spans
2593
- * @param placeholderToMessage maps placeholder names to messages (used for nested ICU messages)
2594
- * @param meaning
2595
- * @param description
2596
- * @param customId
2681
+ * @internal strip this from published d.ts files due to
2682
+ * https://github.com/microsoft/TypeScript/issues/36216
2597
2683
  */
2598
- constructor(nodes, placeholders, placeholderToMessage, meaning, description, customId) {
2599
- this.nodes = nodes;
2600
- this.placeholders = placeholders;
2601
- this.placeholderToMessage = placeholderToMessage;
2602
- this.meaning = meaning;
2603
- this.description = description;
2604
- this.customId = customId;
2605
- this.id = this.customId;
2606
- /** The ids to use if there are no custom id and if `i18nLegacyMessageIdFormat` is not empty */
2607
- this.legacyIds = [];
2608
- if (nodes.length) {
2609
- this.sources = [{
2610
- filePath: nodes[0].sourceSpan.start.file.url,
2611
- startLine: nodes[0].sourceSpan.start.line + 1,
2612
- startCol: nodes[0].sourceSpan.start.col + 1,
2613
- endLine: nodes[nodes.length - 1].sourceSpan.end.line + 1,
2614
- endCol: nodes[0].sourceSpan.start.col + 1
2615
- }];
2616
- }
2617
- else {
2618
- this.sources = [];
2684
+ get sourceLines() {
2685
+ if (this._lines.length && this._lines[this._lines.length - 1].parts.length === 0) {
2686
+ return this._lines.slice(0, -1);
2619
2687
  }
2688
+ return this._lines;
2620
2689
  }
2621
2690
  }
2622
- class Text$1 {
2623
- constructor(value, sourceSpan) {
2624
- this.value = value;
2625
- this.sourceSpan = sourceSpan;
2691
+ class AbstractEmitterVisitor {
2692
+ constructor(_escapeDollarInStrings) {
2693
+ this._escapeDollarInStrings = _escapeDollarInStrings;
2626
2694
  }
2627
- visit(visitor, context) {
2628
- return visitor.visitText(this, context);
2695
+ printLeadingComments(stmt, ctx) {
2696
+ if (stmt.leadingComments === undefined) {
2697
+ return;
2698
+ }
2699
+ for (const comment of stmt.leadingComments) {
2700
+ if (comment instanceof JSDocComment) {
2701
+ ctx.print(stmt, `/*${comment.toString()}*/`, comment.trailingNewline);
2702
+ }
2703
+ else {
2704
+ if (comment.multiline) {
2705
+ ctx.print(stmt, `/* ${comment.text} */`, comment.trailingNewline);
2706
+ }
2707
+ else {
2708
+ comment.text.split('\n').forEach((line) => {
2709
+ ctx.println(stmt, `// ${line}`);
2710
+ });
2711
+ }
2712
+ }
2713
+ }
2629
2714
  }
2630
- }
2631
- // TODO(vicb): do we really need this node (vs an array) ?
2632
- class Container {
2633
- constructor(children, sourceSpan) {
2634
- this.children = children;
2635
- this.sourceSpan = sourceSpan;
2715
+ visitExpressionStmt(stmt, ctx) {
2716
+ this.printLeadingComments(stmt, ctx);
2717
+ stmt.expr.visitExpression(this, ctx);
2718
+ ctx.println(stmt, ';');
2719
+ return null;
2636
2720
  }
2637
- visit(visitor, context) {
2638
- return visitor.visitContainer(this, context);
2721
+ visitReturnStmt(stmt, ctx) {
2722
+ this.printLeadingComments(stmt, ctx);
2723
+ ctx.print(stmt, `return `);
2724
+ stmt.value.visitExpression(this, ctx);
2725
+ ctx.println(stmt, ';');
2726
+ return null;
2639
2727
  }
2640
- }
2641
- class Icu$1 {
2642
- constructor(expression, type, cases, sourceSpan) {
2643
- this.expression = expression;
2644
- this.type = type;
2645
- this.cases = cases;
2646
- this.sourceSpan = sourceSpan;
2728
+ visitIfStmt(stmt, ctx) {
2729
+ this.printLeadingComments(stmt, ctx);
2730
+ ctx.print(stmt, `if (`);
2731
+ stmt.condition.visitExpression(this, ctx);
2732
+ ctx.print(stmt, `) {`);
2733
+ const hasElseCase = stmt.falseCase != null && stmt.falseCase.length > 0;
2734
+ if (stmt.trueCase.length <= 1 && !hasElseCase) {
2735
+ ctx.print(stmt, ` `);
2736
+ this.visitAllStatements(stmt.trueCase, ctx);
2737
+ ctx.removeEmptyLastLine();
2738
+ ctx.print(stmt, ` `);
2739
+ }
2740
+ else {
2741
+ ctx.println();
2742
+ ctx.incIndent();
2743
+ this.visitAllStatements(stmt.trueCase, ctx);
2744
+ ctx.decIndent();
2745
+ if (hasElseCase) {
2746
+ ctx.println(stmt, `} else {`);
2747
+ ctx.incIndent();
2748
+ this.visitAllStatements(stmt.falseCase, ctx);
2749
+ ctx.decIndent();
2750
+ }
2751
+ }
2752
+ ctx.println(stmt, `}`);
2753
+ return null;
2647
2754
  }
2648
- visit(visitor, context) {
2649
- return visitor.visitIcu(this, context);
2755
+ visitThrowStmt(stmt, ctx) {
2756
+ this.printLeadingComments(stmt, ctx);
2757
+ ctx.print(stmt, `throw `);
2758
+ stmt.error.visitExpression(this, ctx);
2759
+ ctx.println(stmt, `;`);
2760
+ return null;
2650
2761
  }
2651
- }
2652
- class TagPlaceholder {
2653
- constructor(tag, attrs, startName, closeName, children, isVoid,
2654
- // TODO sourceSpan should cover all (we need a startSourceSpan and endSourceSpan)
2655
- sourceSpan, startSourceSpan, endSourceSpan) {
2656
- this.tag = tag;
2657
- this.attrs = attrs;
2658
- this.startName = startName;
2659
- this.closeName = closeName;
2660
- this.children = children;
2661
- this.isVoid = isVoid;
2662
- this.sourceSpan = sourceSpan;
2663
- this.startSourceSpan = startSourceSpan;
2664
- this.endSourceSpan = endSourceSpan;
2762
+ visitWriteVarExpr(expr, ctx) {
2763
+ const lineWasEmpty = ctx.lineIsEmpty();
2764
+ if (!lineWasEmpty) {
2765
+ ctx.print(expr, '(');
2766
+ }
2767
+ ctx.print(expr, `${expr.name} = `);
2768
+ expr.value.visitExpression(this, ctx);
2769
+ if (!lineWasEmpty) {
2770
+ ctx.print(expr, ')');
2771
+ }
2772
+ return null;
2665
2773
  }
2666
- visit(visitor, context) {
2667
- return visitor.visitTagPlaceholder(this, context);
2774
+ visitWriteKeyExpr(expr, ctx) {
2775
+ const lineWasEmpty = ctx.lineIsEmpty();
2776
+ if (!lineWasEmpty) {
2777
+ ctx.print(expr, '(');
2778
+ }
2779
+ expr.receiver.visitExpression(this, ctx);
2780
+ ctx.print(expr, `[`);
2781
+ expr.index.visitExpression(this, ctx);
2782
+ ctx.print(expr, `] = `);
2783
+ expr.value.visitExpression(this, ctx);
2784
+ if (!lineWasEmpty) {
2785
+ ctx.print(expr, ')');
2786
+ }
2787
+ return null;
2668
2788
  }
2669
- }
2670
- class Placeholder {
2671
- constructor(value, name, sourceSpan) {
2672
- this.value = value;
2673
- this.name = name;
2674
- this.sourceSpan = sourceSpan;
2789
+ visitWritePropExpr(expr, ctx) {
2790
+ const lineWasEmpty = ctx.lineIsEmpty();
2791
+ if (!lineWasEmpty) {
2792
+ ctx.print(expr, '(');
2793
+ }
2794
+ expr.receiver.visitExpression(this, ctx);
2795
+ ctx.print(expr, `.${expr.name} = `);
2796
+ expr.value.visitExpression(this, ctx);
2797
+ if (!lineWasEmpty) {
2798
+ ctx.print(expr, ')');
2799
+ }
2800
+ return null;
2675
2801
  }
2676
- visit(visitor, context) {
2677
- return visitor.visitPlaceholder(this, context);
2802
+ visitInvokeMethodExpr(expr, ctx) {
2803
+ expr.receiver.visitExpression(this, ctx);
2804
+ let name = expr.name;
2805
+ if (expr.builtin != null) {
2806
+ name = this.getBuiltinMethodName(expr.builtin);
2807
+ if (name == null) {
2808
+ // some builtins just mean to skip the call.
2809
+ return null;
2810
+ }
2811
+ }
2812
+ ctx.print(expr, `.${name}(`);
2813
+ this.visitAllExpressions(expr.args, ctx, `,`);
2814
+ ctx.print(expr, `)`);
2815
+ return null;
2678
2816
  }
2679
- }
2680
- class IcuPlaceholder {
2681
- constructor(value, name, sourceSpan) {
2682
- this.value = value;
2683
- this.name = name;
2684
- this.sourceSpan = sourceSpan;
2817
+ visitInvokeFunctionExpr(expr, ctx) {
2818
+ expr.fn.visitExpression(this, ctx);
2819
+ ctx.print(expr, `(`);
2820
+ this.visitAllExpressions(expr.args, ctx, ',');
2821
+ ctx.print(expr, `)`);
2822
+ return null;
2685
2823
  }
2686
- visit(visitor, context) {
2687
- return visitor.visitIcuPlaceholder(this, context);
2824
+ visitTaggedTemplateExpr(expr, ctx) {
2825
+ expr.tag.visitExpression(this, ctx);
2826
+ ctx.print(expr, '`' + expr.template.elements[0].rawText);
2827
+ for (let i = 1; i < expr.template.elements.length; i++) {
2828
+ ctx.print(expr, '${');
2829
+ expr.template.expressions[i - 1].visitExpression(this, ctx);
2830
+ ctx.print(expr, `}${expr.template.elements[i].rawText}`);
2831
+ }
2832
+ ctx.print(expr, '`');
2833
+ return null;
2688
2834
  }
2689
- }
2690
-
2691
- /**
2692
- * @license
2693
- * Copyright Google LLC All Rights Reserved.
2694
- *
2695
- * Use of this source code is governed by an MIT-style license that can be
2696
- * found in the LICENSE file at https://angular.io/license
2697
- */
2698
- /**
2699
- * Represents a big integer using a buffer of its individual digits, with the least significant
2700
- * digit stored at the beginning of the array (little endian).
2701
- *
2702
- * For performance reasons, each instance is mutable. The addition operation can be done in-place
2703
- * to reduce memory pressure of allocation for the digits array.
2704
- */
2705
- class BigInteger {
2706
- /**
2707
- * Creates a big integer using its individual digits in little endian storage.
2708
- */
2709
- constructor(digits) {
2710
- this.digits = digits;
2835
+ visitWrappedNodeExpr(ast, ctx) {
2836
+ throw new Error('Abstract emitter cannot visit WrappedNodeExpr.');
2711
2837
  }
2712
- static zero() {
2713
- return new BigInteger([0]);
2838
+ visitTypeofExpr(expr, ctx) {
2839
+ ctx.print(expr, 'typeof ');
2840
+ expr.expr.visitExpression(this, ctx);
2714
2841
  }
2715
- static one() {
2716
- return new BigInteger([1]);
2842
+ visitReadVarExpr(ast, ctx) {
2843
+ let varName = ast.name;
2844
+ if (ast.builtin != null) {
2845
+ switch (ast.builtin) {
2846
+ case BuiltinVar.Super:
2847
+ varName = 'super';
2848
+ break;
2849
+ case BuiltinVar.This:
2850
+ varName = 'this';
2851
+ break;
2852
+ case BuiltinVar.CatchError:
2853
+ varName = CATCH_ERROR_VAR$1.name;
2854
+ break;
2855
+ case BuiltinVar.CatchStack:
2856
+ varName = CATCH_STACK_VAR$1.name;
2857
+ break;
2858
+ default:
2859
+ throw new Error(`Unknown builtin variable ${ast.builtin}`);
2860
+ }
2861
+ }
2862
+ ctx.print(ast, varName);
2863
+ return null;
2717
2864
  }
2718
- /**
2719
- * Creates a clone of this instance.
2720
- */
2721
- clone() {
2722
- return new BigInteger(this.digits.slice());
2865
+ visitInstantiateExpr(ast, ctx) {
2866
+ ctx.print(ast, `new `);
2867
+ ast.classExpr.visitExpression(this, ctx);
2868
+ ctx.print(ast, `(`);
2869
+ this.visitAllExpressions(ast.args, ctx, ',');
2870
+ ctx.print(ast, `)`);
2871
+ return null;
2723
2872
  }
2724
- /**
2725
- * Returns a new big integer with the sum of `this` and `other` as its value. This does not mutate
2726
- * `this` but instead returns a new instance, unlike `addToSelf`.
2727
- */
2728
- add(other) {
2729
- const result = this.clone();
2730
- result.addToSelf(other);
2731
- return result;
2873
+ visitLiteralExpr(ast, ctx) {
2874
+ const value = ast.value;
2875
+ if (typeof value === 'string') {
2876
+ ctx.print(ast, escapeIdentifier(value, this._escapeDollarInStrings));
2877
+ }
2878
+ else {
2879
+ ctx.print(ast, `${value}`);
2880
+ }
2881
+ return null;
2732
2882
  }
2733
- /**
2734
- * Adds `other` to the instance itself, thereby mutating its value.
2735
- */
2736
- addToSelf(other) {
2737
- const maxNrOfDigits = Math.max(this.digits.length, other.digits.length);
2738
- let carry = 0;
2739
- for (let i = 0; i < maxNrOfDigits; i++) {
2740
- let digitSum = carry;
2741
- if (i < this.digits.length) {
2742
- digitSum += this.digits[i];
2743
- }
2744
- if (i < other.digits.length) {
2745
- digitSum += other.digits[i];
2746
- }
2747
- if (digitSum >= 10) {
2748
- this.digits[i] = digitSum - 10;
2749
- carry = 1;
2750
- }
2751
- else {
2752
- this.digits[i] = digitSum;
2753
- carry = 0;
2754
- }
2883
+ visitLocalizedString(ast, ctx) {
2884
+ const head = ast.serializeI18nHead();
2885
+ ctx.print(ast, '$localize `' + head.raw);
2886
+ for (let i = 1; i < ast.messageParts.length; i++) {
2887
+ ctx.print(ast, '${');
2888
+ ast.expressions[i - 1].visitExpression(this, ctx);
2889
+ ctx.print(ast, `}${ast.serializeI18nTemplatePart(i).raw}`);
2755
2890
  }
2756
- // Apply a remaining carry if needed.
2757
- if (carry > 0) {
2758
- this.digits[maxNrOfDigits] = 1;
2891
+ ctx.print(ast, '`');
2892
+ return null;
2893
+ }
2894
+ visitConditionalExpr(ast, ctx) {
2895
+ ctx.print(ast, `(`);
2896
+ ast.condition.visitExpression(this, ctx);
2897
+ ctx.print(ast, '? ');
2898
+ ast.trueCase.visitExpression(this, ctx);
2899
+ ctx.print(ast, ': ');
2900
+ ast.falseCase.visitExpression(this, ctx);
2901
+ ctx.print(ast, `)`);
2902
+ return null;
2903
+ }
2904
+ visitNotExpr(ast, ctx) {
2905
+ ctx.print(ast, '!');
2906
+ ast.condition.visitExpression(this, ctx);
2907
+ return null;
2908
+ }
2909
+ visitAssertNotNullExpr(ast, ctx) {
2910
+ ast.condition.visitExpression(this, ctx);
2911
+ return null;
2912
+ }
2913
+ visitUnaryOperatorExpr(ast, ctx) {
2914
+ let opStr;
2915
+ switch (ast.operator) {
2916
+ case UnaryOperator.Plus:
2917
+ opStr = '+';
2918
+ break;
2919
+ case UnaryOperator.Minus:
2920
+ opStr = '-';
2921
+ break;
2922
+ default:
2923
+ throw new Error(`Unknown operator ${ast.operator}`);
2759
2924
  }
2925
+ if (ast.parens)
2926
+ ctx.print(ast, `(`);
2927
+ ctx.print(ast, opStr);
2928
+ ast.expr.visitExpression(this, ctx);
2929
+ if (ast.parens)
2930
+ ctx.print(ast, `)`);
2931
+ return null;
2760
2932
  }
2761
- /**
2762
- * Builds the decimal string representation of the big integer. As this is stored in
2763
- * little endian, the digits are concatenated in reverse order.
2764
- */
2765
- toString() {
2766
- let res = '';
2767
- for (let i = this.digits.length - 1; i >= 0; i--) {
2768
- res += this.digits[i];
2933
+ visitBinaryOperatorExpr(ast, ctx) {
2934
+ let opStr;
2935
+ switch (ast.operator) {
2936
+ case BinaryOperator.Equals:
2937
+ opStr = '==';
2938
+ break;
2939
+ case BinaryOperator.Identical:
2940
+ opStr = '===';
2941
+ break;
2942
+ case BinaryOperator.NotEquals:
2943
+ opStr = '!=';
2944
+ break;
2945
+ case BinaryOperator.NotIdentical:
2946
+ opStr = '!==';
2947
+ break;
2948
+ case BinaryOperator.And:
2949
+ opStr = '&&';
2950
+ break;
2951
+ case BinaryOperator.BitwiseAnd:
2952
+ opStr = '&';
2953
+ break;
2954
+ case BinaryOperator.Or:
2955
+ opStr = '||';
2956
+ break;
2957
+ case BinaryOperator.Plus:
2958
+ opStr = '+';
2959
+ break;
2960
+ case BinaryOperator.Minus:
2961
+ opStr = '-';
2962
+ break;
2963
+ case BinaryOperator.Divide:
2964
+ opStr = '/';
2965
+ break;
2966
+ case BinaryOperator.Multiply:
2967
+ opStr = '*';
2968
+ break;
2969
+ case BinaryOperator.Modulo:
2970
+ opStr = '%';
2971
+ break;
2972
+ case BinaryOperator.Lower:
2973
+ opStr = '<';
2974
+ break;
2975
+ case BinaryOperator.LowerEquals:
2976
+ opStr = '<=';
2977
+ break;
2978
+ case BinaryOperator.Bigger:
2979
+ opStr = '>';
2980
+ break;
2981
+ case BinaryOperator.BiggerEquals:
2982
+ opStr = '>=';
2983
+ break;
2984
+ case BinaryOperator.NullishCoalesce:
2985
+ opStr = '??';
2986
+ break;
2987
+ default:
2988
+ throw new Error(`Unknown operator ${ast.operator}`);
2769
2989
  }
2770
- return res;
2990
+ if (ast.parens)
2991
+ ctx.print(ast, `(`);
2992
+ ast.lhs.visitExpression(this, ctx);
2993
+ ctx.print(ast, ` ${opStr} `);
2994
+ ast.rhs.visitExpression(this, ctx);
2995
+ if (ast.parens)
2996
+ ctx.print(ast, `)`);
2997
+ return null;
2771
2998
  }
2772
- }
2773
- /**
2774
- * Represents a big integer which is optimized for multiplication operations, as its power-of-twos
2775
- * are memoized. See `multiplyBy()` for details on the multiplication algorithm.
2776
- */
2777
- class BigIntForMultiplication {
2778
- constructor(value) {
2779
- this.powerOfTwos = [value];
2999
+ visitReadPropExpr(ast, ctx) {
3000
+ ast.receiver.visitExpression(this, ctx);
3001
+ ctx.print(ast, `.`);
3002
+ ctx.print(ast, ast.name);
3003
+ return null;
2780
3004
  }
2781
- /**
2782
- * Returns the big integer itself.
2783
- */
2784
- getValue() {
2785
- return this.powerOfTwos[0];
3005
+ visitReadKeyExpr(ast, ctx) {
3006
+ ast.receiver.visitExpression(this, ctx);
3007
+ ctx.print(ast, `[`);
3008
+ ast.index.visitExpression(this, ctx);
3009
+ ctx.print(ast, `]`);
3010
+ return null;
2786
3011
  }
2787
- /**
2788
- * Computes the value for `num * b`, where `num` is a JS number and `b` is a big integer. The
2789
- * value for `b` is represented by a storage model that is optimized for this computation.
2790
- *
2791
- * This operation is implemented in N(log2(num)) by continuous halving of the number, where the
2792
- * least-significant bit (LSB) is tested in each iteration. If the bit is set, the bit's index is
2793
- * used as exponent into the power-of-two multiplication of `b`.
2794
- *
2795
- * As an example, consider the multiplication num=42, b=1337. In binary 42 is 0b00101010 and the
2796
- * algorithm unrolls into the following iterations:
2797
- *
2798
- * Iteration | num | LSB | b * 2^iter | Add? | product
2799
- * -----------|------------|------|------------|------|--------
2800
- * 0 | 0b00101010 | 0 | 1337 | No | 0
2801
- * 1 | 0b00010101 | 1 | 2674 | Yes | 2674
2802
- * 2 | 0b00001010 | 0 | 5348 | No | 2674
2803
- * 3 | 0b00000101 | 1 | 10696 | Yes | 13370
2804
- * 4 | 0b00000010 | 0 | 21392 | No | 13370
2805
- * 5 | 0b00000001 | 1 | 42784 | Yes | 56154
2806
- * 6 | 0b00000000 | 0 | 85568 | No | 56154
2807
- *
2808
- * The computed product of 56154 is indeed the correct result.
2809
- *
2810
- * The `BigIntForMultiplication` representation for a big integer provides memoized access to the
2811
- * power-of-two values to reduce the workload in computing those values.
2812
- */
2813
- multiplyBy(num) {
2814
- const product = BigInteger.zero();
2815
- this.multiplyByAndAddTo(num, product);
2816
- return product;
3012
+ visitLiteralArrayExpr(ast, ctx) {
3013
+ ctx.print(ast, `[`);
3014
+ this.visitAllExpressions(ast.entries, ctx, ',');
3015
+ ctx.print(ast, `]`);
3016
+ return null;
2817
3017
  }
2818
- /**
2819
- * See `multiplyBy()` for details. This function allows for the computed product to be added
2820
- * directly to the provided result big integer.
2821
- */
2822
- multiplyByAndAddTo(num, result) {
2823
- for (let exponent = 0; num !== 0; num = num >>> 1, exponent++) {
2824
- if (num & 1) {
2825
- const value = this.getMultipliedByPowerOfTwo(exponent);
2826
- result.addToSelf(value);
3018
+ visitLiteralMapExpr(ast, ctx) {
3019
+ ctx.print(ast, `{`);
3020
+ this.visitAllObjects(entry => {
3021
+ ctx.print(ast, `${escapeIdentifier(entry.key, this._escapeDollarInStrings, entry.quoted)}:`);
3022
+ entry.value.visitExpression(this, ctx);
3023
+ }, ast.entries, ctx, ',');
3024
+ ctx.print(ast, `}`);
3025
+ return null;
3026
+ }
3027
+ visitCommaExpr(ast, ctx) {
3028
+ ctx.print(ast, '(');
3029
+ this.visitAllExpressions(ast.parts, ctx, ',');
3030
+ ctx.print(ast, ')');
3031
+ return null;
3032
+ }
3033
+ visitAllExpressions(expressions, ctx, separator) {
3034
+ this.visitAllObjects(expr => expr.visitExpression(this, ctx), expressions, ctx, separator);
3035
+ }
3036
+ visitAllObjects(handler, expressions, ctx, separator) {
3037
+ let incrementedIndent = false;
3038
+ for (let i = 0; i < expressions.length; i++) {
3039
+ if (i > 0) {
3040
+ if (ctx.lineLength() > 80) {
3041
+ ctx.print(null, separator, true);
3042
+ if (!incrementedIndent) {
3043
+ // continuation are marked with double indent.
3044
+ ctx.incIndent();
3045
+ ctx.incIndent();
3046
+ incrementedIndent = true;
3047
+ }
3048
+ }
3049
+ else {
3050
+ ctx.print(null, separator, false);
3051
+ }
2827
3052
  }
3053
+ handler(expressions[i]);
2828
3054
  }
2829
- }
2830
- /**
2831
- * Computes and memoizes the big integer value for `this.number * 2^exponent`.
2832
- */
2833
- getMultipliedByPowerOfTwo(exponent) {
2834
- // Compute the powers up until the requested exponent, where each value is computed from its
2835
- // predecessor. This is simple as `this.number * 2^(exponent - 1)` only has to be doubled (i.e.
2836
- // added to itself) to reach `this.number * 2^exponent`.
2837
- for (let i = this.powerOfTwos.length; i <= exponent; i++) {
2838
- const previousPower = this.powerOfTwos[i - 1];
2839
- this.powerOfTwos[i] = previousPower.add(previousPower);
3055
+ if (incrementedIndent) {
3056
+ // continuation are marked with double indent.
3057
+ ctx.decIndent();
3058
+ ctx.decIndent();
2840
3059
  }
2841
- return this.powerOfTwos[exponent];
3060
+ }
3061
+ visitAllStatements(statements, ctx) {
3062
+ statements.forEach((stmt) => stmt.visitStatement(this, ctx));
2842
3063
  }
2843
3064
  }
2844
- /**
2845
- * Represents an exponentiation operation for the provided base, of which exponents are computed and
2846
- * memoized. The results are represented by a `BigIntForMultiplication` which is tailored for
2847
- * multiplication operations by memoizing the power-of-twos. This effectively results in a matrix
2848
- * representation that is lazily computed upon request.
2849
- */
2850
- class BigIntExponentiation {
2851
- constructor(base) {
2852
- this.base = base;
2853
- this.exponents = [new BigIntForMultiplication(BigInteger.one())];
3065
+ function escapeIdentifier(input, escapeDollar, alwaysQuote = true) {
3066
+ if (input == null) {
3067
+ return null;
2854
3068
  }
2855
- /**
2856
- * Compute the value for `this.base^exponent`, resulting in a big integer that is optimized for
2857
- * further multiplication operations.
2858
- */
2859
- toThePowerOf(exponent) {
2860
- // Compute the results up until the requested exponent, where every value is computed from its
2861
- // predecessor. This is because `this.base^(exponent - 1)` only has to be multiplied by `base`
2862
- // to reach `this.base^exponent`.
2863
- for (let i = this.exponents.length; i <= exponent; i++) {
2864
- const value = this.exponents[i - 1].multiplyBy(this.base);
2865
- this.exponents[i] = new BigIntForMultiplication(value);
3069
+ const body = input.replace(_SINGLE_QUOTE_ESCAPE_STRING_RE, (...match) => {
3070
+ if (match[0] == '$') {
3071
+ return escapeDollar ? '\\$' : '$';
2866
3072
  }
2867
- return this.exponents[exponent];
3073
+ else if (match[0] == '\n') {
3074
+ return '\\n';
3075
+ }
3076
+ else if (match[0] == '\r') {
3077
+ return '\\r';
3078
+ }
3079
+ else {
3080
+ return `\\${match[0]}`;
3081
+ }
3082
+ });
3083
+ const requiresQuotes = alwaysQuote || !_LEGAL_IDENTIFIER_RE.test(body);
3084
+ return requiresQuotes ? `'${body}'` : body;
3085
+ }
3086
+ function _createIndent(count) {
3087
+ let res = '';
3088
+ for (let i = 0; i < count; i++) {
3089
+ res += _INDENT_WITH;
2868
3090
  }
3091
+ return res;
2869
3092
  }
2870
3093
 
2871
3094
  /**
@@ -2875,678 +3098,479 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
2875
3098
  * Use of this source code is governed by an MIT-style license that can be
2876
3099
  * found in the LICENSE file at https://angular.io/license
2877
3100
  */
2878
- /**
2879
- * Compute the message id using the XLIFF1 digest.
2880
- */
2881
- function computeDigest(message) {
2882
- return sha1(serializeNodes(message.nodes).join('') + `[${message.meaning}]`);
3101
+ function typeWithParameters(type, numParams) {
3102
+ if (numParams === 0) {
3103
+ return expressionType(type);
3104
+ }
3105
+ const params = [];
3106
+ for (let i = 0; i < numParams; i++) {
3107
+ params.push(DYNAMIC_TYPE);
3108
+ }
3109
+ return expressionType(type, undefined, params);
2883
3110
  }
2884
- /**
2885
- * Return the message id or compute it using the XLIFF2/XMB/$localize digest.
2886
- */
2887
- function decimalDigest(message) {
2888
- return message.id || computeDecimalDigest(message);
3111
+ const ANIMATE_SYMBOL_PREFIX = '@';
3112
+ function prepareSyntheticPropertyName(name) {
3113
+ return `${ANIMATE_SYMBOL_PREFIX}${name}`;
2889
3114
  }
2890
- /**
2891
- * Compute the message id using the XLIFF2/XMB/$localize digest.
2892
- */
2893
- function computeDecimalDigest(message) {
2894
- const visitor = new _SerializerIgnoreIcuExpVisitor();
2895
- const parts = message.nodes.map(a => a.visit(visitor, null));
2896
- return computeMsgId(parts.join(''), message.meaning);
3115
+ function prepareSyntheticListenerName(name, phase) {
3116
+ return `${ANIMATE_SYMBOL_PREFIX}${name}.${phase}`;
3117
+ }
3118
+ function getSafePropertyAccessString(accessor, name) {
3119
+ const escapedName = escapeIdentifier(name, false, false);
3120
+ return escapedName !== name ? `${accessor}[${escapedName}]` : `${accessor}.${name}`;
3121
+ }
3122
+ function prepareSyntheticListenerFunctionName(name, phase) {
3123
+ return `animation_${name}_${phase}`;
3124
+ }
3125
+ function jitOnlyGuardedExpression(expr) {
3126
+ return guardedExpression('ngJitMode', expr);
3127
+ }
3128
+ function guardedExpression(guard, expr) {
3129
+ const guardExpr = new ExternalExpr({ name: guard, moduleName: null });
3130
+ const guardNotDefined = new BinaryOperatorExpr(BinaryOperator.Identical, new TypeofExpr(guardExpr), literal('undefined'));
3131
+ const guardUndefinedOrTrue = new BinaryOperatorExpr(BinaryOperator.Or, guardNotDefined, guardExpr, /* type */ undefined,
3132
+ /* sourceSpan */ undefined, true);
3133
+ return new BinaryOperatorExpr(BinaryOperator.And, guardUndefinedOrTrue, expr);
3134
+ }
3135
+ function wrapReference(value) {
3136
+ const wrapped = new WrappedNodeExpr(value);
3137
+ return { value: wrapped, type: wrapped };
3138
+ }
3139
+ function refsToArray(refs, shouldForwardDeclare) {
3140
+ const values = literalArr(refs.map(ref => ref.value));
3141
+ return shouldForwardDeclare ? fn([], [new ReturnStatement(values)]) : values;
3142
+ }
3143
+ function createMayBeForwardRefExpression(expression, forwardRef) {
3144
+ return { expression, forwardRef };
2897
3145
  }
2898
3146
  /**
2899
- * Serialize the i18n ast to something xml-like in order to generate an UID.
3147
+ * Convert a `MaybeForwardRefExpression` to an `Expression`, possibly wrapping its expression in a
3148
+ * `forwardRef()` call.
2900
3149
  *
2901
- * The visitor is also used in the i18n parser tests
3150
+ * If `MaybeForwardRefExpression.forwardRef` is `ForwardRefHandling.Unwrapped` then the expression
3151
+ * was originally wrapped in a `forwardRef()` call to prevent the value from being eagerly evaluated
3152
+ * in the code.
2902
3153
  *
2903
- * @internal
3154
+ * See `packages/compiler-cli/src/ngtsc/annotations/src/injectable.ts` and
3155
+ * `packages/compiler/src/jit_compiler_facade.ts` for more information.
2904
3156
  */
2905
- class _SerializerVisitor {
2906
- visitText(text, context) {
2907
- return text.value;
2908
- }
2909
- visitContainer(container, context) {
2910
- return `[${container.children.map(child => child.visit(this)).join(', ')}]`;
2911
- }
2912
- visitIcu(icu, context) {
2913
- const strCases = Object.keys(icu.cases).map((k) => `${k} {${icu.cases[k].visit(this)}}`);
2914
- return `{${icu.expression}, ${icu.type}, ${strCases.join(', ')}}`;
2915
- }
2916
- visitTagPlaceholder(ph, context) {
2917
- return ph.isVoid ?
2918
- `<ph tag name="${ph.startName}"/>` :
2919
- `<ph tag name="${ph.startName}">${ph.children.map(child => child.visit(this)).join(', ')}</ph name="${ph.closeName}">`;
2920
- }
2921
- visitPlaceholder(ph, context) {
2922
- return ph.value ? `<ph name="${ph.name}">${ph.value}</ph>` : `<ph name="${ph.name}"/>`;
2923
- }
2924
- visitIcuPlaceholder(ph, context) {
2925
- return `<ph icu name="${ph.name}">${ph.value.visit(this)}</ph>`;
3157
+ function convertFromMaybeForwardRefExpression({ expression, forwardRef }) {
3158
+ switch (forwardRef) {
3159
+ case 0 /* None */:
3160
+ case 1 /* Wrapped */:
3161
+ return expression;
3162
+ case 2 /* Unwrapped */:
3163
+ return generateForwardRef(expression);
2926
3164
  }
2927
3165
  }
2928
- const serializerVisitor = new _SerializerVisitor();
2929
- function serializeNodes(nodes) {
2930
- return nodes.map(a => a.visit(serializerVisitor, null));
2931
- }
2932
3166
  /**
2933
- * Serialize the i18n ast to something xml-like in order to generate an UID.
2934
- *
2935
- * Ignore the ICU expressions so that message IDs stays identical if only the expression changes.
3167
+ * Generate an expression that has the given `expr` wrapped in the following form:
2936
3168
  *
2937
- * @internal
3169
+ * ```
3170
+ * forwardRef(() => expr)
3171
+ * ```
2938
3172
  */
2939
- class _SerializerIgnoreIcuExpVisitor extends _SerializerVisitor {
2940
- visitIcu(icu, context) {
2941
- let strCases = Object.keys(icu.cases).map((k) => `${k} {${icu.cases[k].visit(this)}}`);
2942
- // Do not take the expression into account
2943
- return `{${icu.type}, ${strCases.join(', ')}}`;
2944
- }
3173
+ function generateForwardRef(expr) {
3174
+ return importExpr(Identifiers.forwardRef).callFn([fn([], [new ReturnStatement(expr)])]);
2945
3175
  }
3176
+
3177
+ var R3FactoryDelegateType;
3178
+ (function (R3FactoryDelegateType) {
3179
+ R3FactoryDelegateType[R3FactoryDelegateType["Class"] = 0] = "Class";
3180
+ R3FactoryDelegateType[R3FactoryDelegateType["Function"] = 1] = "Function";
3181
+ })(R3FactoryDelegateType || (R3FactoryDelegateType = {}));
3182
+ var FactoryTarget;
3183
+ (function (FactoryTarget) {
3184
+ FactoryTarget[FactoryTarget["Directive"] = 0] = "Directive";
3185
+ FactoryTarget[FactoryTarget["Component"] = 1] = "Component";
3186
+ FactoryTarget[FactoryTarget["Injectable"] = 2] = "Injectable";
3187
+ FactoryTarget[FactoryTarget["Pipe"] = 3] = "Pipe";
3188
+ FactoryTarget[FactoryTarget["NgModule"] = 4] = "NgModule";
3189
+ })(FactoryTarget || (FactoryTarget = {}));
2946
3190
  /**
2947
- * Compute the SHA1 of the given string
2948
- *
2949
- * see https://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
2950
- *
2951
- * WARNING: this function has not been designed not tested with security in mind.
2952
- * DO NOT USE IT IN A SECURITY SENSITIVE CONTEXT.
3191
+ * Construct a factory function expression for the given `R3FactoryMetadata`.
2953
3192
  */
2954
- function sha1(str) {
2955
- const utf8 = utf8Encode(str);
2956
- const words32 = bytesToWords32(utf8, Endian.Big);
2957
- const len = utf8.length * 8;
2958
- const w = newArray(80);
2959
- let a = 0x67452301, b = 0xefcdab89, c = 0x98badcfe, d = 0x10325476, e = 0xc3d2e1f0;
2960
- words32[len >> 5] |= 0x80 << (24 - len % 32);
2961
- words32[((len + 64 >> 9) << 4) + 15] = len;
2962
- for (let i = 0; i < words32.length; i += 16) {
2963
- const h0 = a, h1 = b, h2 = c, h3 = d, h4 = e;
2964
- for (let j = 0; j < 80; j++) {
2965
- if (j < 16) {
2966
- w[j] = words32[i + j];
2967
- }
2968
- else {
2969
- w[j] = rol32(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1);
2970
- }
2971
- const fkVal = fk(j, b, c, d);
2972
- const f = fkVal[0];
2973
- const k = fkVal[1];
2974
- const temp = [rol32(a, 5), f, e, k, w[j]].reduce(add32);
2975
- e = d;
2976
- d = c;
2977
- c = rol32(b, 30);
2978
- b = a;
2979
- a = temp;
3193
+ function compileFactoryFunction(meta) {
3194
+ const t = variable('t');
3195
+ let baseFactoryVar = null;
3196
+ // The type to instantiate via constructor invocation. If there is no delegated factory, meaning
3197
+ // this type is always created by constructor invocation, then this is the type-to-create
3198
+ // parameter provided by the user (t) if specified, or the current type if not. If there is a
3199
+ // delegated factory (which is used to create the current type) then this is only the type-to-
3200
+ // create parameter (t).
3201
+ const typeForCtor = !isDelegatedFactoryMetadata(meta) ?
3202
+ new BinaryOperatorExpr(BinaryOperator.Or, t, meta.internalType) :
3203
+ t;
3204
+ let ctorExpr = null;
3205
+ if (meta.deps !== null) {
3206
+ // There is a constructor (either explicitly or implicitly defined).
3207
+ if (meta.deps !== 'invalid') {
3208
+ ctorExpr = new InstantiateExpr(typeForCtor, injectDependencies(meta.deps, meta.target));
2980
3209
  }
2981
- a = add32(a, h0);
2982
- b = add32(b, h1);
2983
- c = add32(c, h2);
2984
- d = add32(d, h3);
2985
- e = add32(e, h4);
2986
3210
  }
2987
- return bytesToHexString(words32ToByteString([a, b, c, d, e]));
2988
- }
2989
- function fk(index, b, c, d) {
2990
- if (index < 20) {
2991
- return [(b & c) | (~b & d), 0x5a827999];
3211
+ else {
3212
+ // There is no constructor, use the base class' factory to construct typeForCtor.
3213
+ baseFactoryVar = variable(`ɵ${meta.name}_BaseFactory`);
3214
+ ctorExpr = baseFactoryVar.callFn([typeForCtor]);
2992
3215
  }
2993
- if (index < 40) {
2994
- return [b ^ c ^ d, 0x6ed9eba1];
3216
+ const body = [];
3217
+ let retExpr = null;
3218
+ function makeConditionalFactory(nonCtorExpr) {
3219
+ const r = variable('r');
3220
+ body.push(r.set(NULL_EXPR).toDeclStmt());
3221
+ const ctorStmt = ctorExpr !== null ? r.set(ctorExpr).toStmt() :
3222
+ importExpr(Identifiers.invalidFactory).callFn([]).toStmt();
3223
+ body.push(ifStmt(t, [ctorStmt], [r.set(nonCtorExpr).toStmt()]));
3224
+ return r;
2995
3225
  }
2996
- if (index < 60) {
2997
- return [(b & c) | (b & d) | (c & d), 0x8f1bbcdc];
3226
+ if (isDelegatedFactoryMetadata(meta)) {
3227
+ // This type is created with a delegated factory. If a type parameter is not specified, call
3228
+ // the factory instead.
3229
+ const delegateArgs = injectDependencies(meta.delegateDeps, meta.target);
3230
+ // Either call `new delegate(...)` or `delegate(...)` depending on meta.delegateType.
3231
+ const factoryExpr = new (meta.delegateType === R3FactoryDelegateType.Class ?
3232
+ InstantiateExpr :
3233
+ InvokeFunctionExpr)(meta.delegate, delegateArgs);
3234
+ retExpr = makeConditionalFactory(factoryExpr);
2998
3235
  }
2999
- return [b ^ c ^ d, 0xca62c1d6];
3000
- }
3001
- /**
3002
- * Compute the fingerprint of the given string
3003
- *
3004
- * The output is 64 bit number encoded as a decimal string
3005
- *
3006
- * based on:
3007
- * https://github.com/google/closure-compiler/blob/master/src/com/google/javascript/jscomp/GoogleJsMessageIdGenerator.java
3008
- */
3009
- function fingerprint(str) {
3010
- const utf8 = utf8Encode(str);
3011
- let hi = hash32(utf8, 0);
3012
- let lo = hash32(utf8, 102072);
3013
- if (hi == 0 && (lo == 0 || lo == 1)) {
3014
- hi = hi ^ 0x130f9bef;
3015
- lo = lo ^ -0x6b5f56d8;
3236
+ else if (isExpressionFactoryMetadata(meta)) {
3237
+ // TODO(alxhub): decide whether to lower the value here or in the caller
3238
+ retExpr = makeConditionalFactory(meta.expression);
3016
3239
  }
3017
- return [hi, lo];
3018
- }
3019
- function computeMsgId(msg, meaning = '') {
3020
- let msgFingerprint = fingerprint(msg);
3021
- if (meaning) {
3022
- const meaningFingerprint = fingerprint(meaning);
3023
- msgFingerprint = add64(rol64(msgFingerprint, 1), meaningFingerprint);
3240
+ else {
3241
+ retExpr = ctorExpr;
3024
3242
  }
3025
- const hi = msgFingerprint[0];
3026
- const lo = msgFingerprint[1];
3027
- return wordsToDecimalString(hi & 0x7fffffff, lo);
3028
- }
3029
- function hash32(bytes, c) {
3030
- let a = 0x9e3779b9, b = 0x9e3779b9;
3031
- let i;
3032
- const len = bytes.length;
3033
- for (i = 0; i + 12 <= len; i += 12) {
3034
- a = add32(a, wordAt(bytes, i, Endian.Little));
3035
- b = add32(b, wordAt(bytes, i + 4, Endian.Little));
3036
- c = add32(c, wordAt(bytes, i + 8, Endian.Little));
3037
- const res = mix(a, b, c);
3038
- a = res[0], b = res[1], c = res[2];
3243
+ if (retExpr === null) {
3244
+ // The expression cannot be formed so render an `ɵɵinvalidFactory()` call.
3245
+ body.push(importExpr(Identifiers.invalidFactory).callFn([]).toStmt());
3039
3246
  }
3040
- a = add32(a, wordAt(bytes, i, Endian.Little));
3041
- b = add32(b, wordAt(bytes, i + 4, Endian.Little));
3042
- // the first byte of c is reserved for the length
3043
- c = add32(c, len);
3044
- c = add32(c, wordAt(bytes, i + 8, Endian.Little) << 8);
3045
- return mix(a, b, c)[2];
3046
- }
3047
- // clang-format off
3048
- function mix(a, b, c) {
3049
- a = sub32(a, b);
3050
- a = sub32(a, c);
3051
- a ^= c >>> 13;
3052
- b = sub32(b, c);
3053
- b = sub32(b, a);
3054
- b ^= a << 8;
3055
- c = sub32(c, a);
3056
- c = sub32(c, b);
3057
- c ^= b >>> 13;
3058
- a = sub32(a, b);
3059
- a = sub32(a, c);
3060
- a ^= c >>> 12;
3061
- b = sub32(b, c);
3062
- b = sub32(b, a);
3063
- b ^= a << 16;
3064
- c = sub32(c, a);
3065
- c = sub32(c, b);
3066
- c ^= b >>> 5;
3067
- a = sub32(a, b);
3068
- a = sub32(a, c);
3069
- a ^= c >>> 3;
3070
- b = sub32(b, c);
3071
- b = sub32(b, a);
3072
- b ^= a << 10;
3073
- c = sub32(c, a);
3074
- c = sub32(c, b);
3075
- c ^= b >>> 15;
3076
- return [a, b, c];
3077
- }
3078
- // clang-format on
3079
- // Utils
3080
- var Endian;
3081
- (function (Endian) {
3082
- Endian[Endian["Little"] = 0] = "Little";
3083
- Endian[Endian["Big"] = 1] = "Big";
3084
- })(Endian || (Endian = {}));
3085
- function add32(a, b) {
3086
- return add32to64(a, b)[1];
3087
- }
3088
- function add32to64(a, b) {
3089
- const low = (a & 0xffff) + (b & 0xffff);
3090
- const high = (a >>> 16) + (b >>> 16) + (low >>> 16);
3091
- return [high >>> 16, (high << 16) | (low & 0xffff)];
3092
- }
3093
- function add64(a, b) {
3094
- const ah = a[0], al = a[1];
3095
- const bh = b[0], bl = b[1];
3096
- const result = add32to64(al, bl);
3097
- const carry = result[0];
3098
- const l = result[1];
3099
- const h = add32(add32(ah, bh), carry);
3100
- return [h, l];
3101
- }
3102
- function sub32(a, b) {
3103
- const low = (a & 0xffff) - (b & 0xffff);
3104
- const high = (a >> 16) - (b >> 16) + (low >> 16);
3105
- return (high << 16) | (low & 0xffff);
3247
+ else if (baseFactoryVar !== null) {
3248
+ // This factory uses a base factory, so call `ɵɵgetInheritedFactory()` to compute it.
3249
+ const getInheritedFactoryCall = importExpr(Identifiers.getInheritedFactory).callFn([meta.internalType]);
3250
+ // Memoize the base factoryFn: `baseFactory || (baseFactory = ɵɵgetInheritedFactory(...))`
3251
+ const baseFactory = new BinaryOperatorExpr(BinaryOperator.Or, baseFactoryVar, baseFactoryVar.set(getInheritedFactoryCall));
3252
+ body.push(new ReturnStatement(baseFactory.callFn([typeForCtor])));
3253
+ }
3254
+ else {
3255
+ // This is straightforward factory, just return it.
3256
+ body.push(new ReturnStatement(retExpr));
3257
+ }
3258
+ let factoryFn = fn([new FnParam('t', DYNAMIC_TYPE)], body, INFERRED_TYPE, undefined, `${meta.name}_Factory`);
3259
+ if (baseFactoryVar !== null) {
3260
+ // There is a base factory variable so wrap its declaration along with the factory function into
3261
+ // an IIFE.
3262
+ factoryFn = fn([], [
3263
+ new DeclareVarStmt(baseFactoryVar.name), new ReturnStatement(factoryFn)
3264
+ ]).callFn([], /* sourceSpan */ undefined, /* pure */ true);
3265
+ }
3266
+ return {
3267
+ expression: factoryFn,
3268
+ statements: [],
3269
+ type: createFactoryType(meta),
3270
+ };
3106
3271
  }
3107
- // Rotate a 32b number left `count` position
3108
- function rol32(a, count) {
3109
- return (a << count) | (a >>> (32 - count));
3272
+ function createFactoryType(meta) {
3273
+ const ctorDepsType = meta.deps !== null && meta.deps !== 'invalid' ? createCtorDepsType(meta.deps) : NONE_TYPE;
3274
+ return expressionType(importExpr(Identifiers.FactoryDeclaration, [typeWithParameters(meta.type.type, meta.typeArgumentCount), ctorDepsType]));
3110
3275
  }
3111
- // Rotate a 64b number left `count` position
3112
- function rol64(num, count) {
3113
- const hi = num[0], lo = num[1];
3114
- const h = (hi << count) | (lo >>> (32 - count));
3115
- const l = (lo << count) | (hi >>> (32 - count));
3116
- return [h, l];
3276
+ function injectDependencies(deps, target) {
3277
+ return deps.map((dep, index) => compileInjectDependency(dep, target, index));
3117
3278
  }
3118
- function bytesToWords32(bytes, endian) {
3119
- const size = (bytes.length + 3) >>> 2;
3120
- const words32 = [];
3121
- for (let i = 0; i < size; i++) {
3122
- words32[i] = wordAt(bytes, i * 4, endian);
3279
+ function compileInjectDependency(dep, target, index) {
3280
+ // Interpret the dependency according to its resolved type.
3281
+ if (dep.token === null) {
3282
+ return importExpr(Identifiers.invalidFactoryDep).callFn([literal(index)]);
3123
3283
  }
3124
- return words32;
3125
- }
3126
- function byteAt(bytes, index) {
3127
- return index >= bytes.length ? 0 : bytes[index];
3128
- }
3129
- function wordAt(bytes, index, endian) {
3130
- let word = 0;
3131
- if (endian === Endian.Big) {
3132
- for (let i = 0; i < 4; i++) {
3133
- word += byteAt(bytes, index + i) << (24 - 8 * i);
3284
+ else if (dep.attributeNameType === null) {
3285
+ // Build up the injection flags according to the metadata.
3286
+ const flags = 0 /* Default */ | (dep.self ? 2 /* Self */ : 0) |
3287
+ (dep.skipSelf ? 4 /* SkipSelf */ : 0) | (dep.host ? 1 /* Host */ : 0) |
3288
+ (dep.optional ? 8 /* Optional */ : 0) |
3289
+ (target === FactoryTarget.Pipe ? 16 /* ForPipe */ : 0);
3290
+ // If this dependency is optional or otherwise has non-default flags, then additional
3291
+ // parameters describing how to inject the dependency must be passed to the inject function
3292
+ // that's being used.
3293
+ let flagsParam = (flags !== 0 /* Default */ || dep.optional) ? literal(flags) : null;
3294
+ // Build up the arguments to the injectFn call.
3295
+ const injectArgs = [dep.token];
3296
+ if (flagsParam) {
3297
+ injectArgs.push(flagsParam);
3134
3298
  }
3299
+ const injectFn = getInjectFn(target);
3300
+ return importExpr(injectFn).callFn(injectArgs);
3135
3301
  }
3136
3302
  else {
3137
- for (let i = 0; i < 4; i++) {
3138
- word += byteAt(bytes, index + i) << 8 * i;
3139
- }
3303
+ // The `dep.attributeTypeName` value is defined, which indicates that this is an `@Attribute()`
3304
+ // type dependency. For the generated JS we still want to use the `dep.token` value in case the
3305
+ // name given for the attribute is not a string literal. For example given `@Attribute(foo())`,
3306
+ // we want to generate `ɵɵinjectAttribute(foo())`.
3307
+ //
3308
+ // The `dep.attributeTypeName` is only actually used (in `createCtorDepType()`) to generate
3309
+ // typings.
3310
+ return importExpr(Identifiers.injectAttribute).callFn([dep.token]);
3140
3311
  }
3141
- return word;
3142
3312
  }
3143
- function words32ToByteString(words32) {
3144
- return words32.reduce((bytes, word) => bytes.concat(word32ToByteString(word)), []);
3313
+ function createCtorDepsType(deps) {
3314
+ let hasTypes = false;
3315
+ const attributeTypes = deps.map(dep => {
3316
+ const type = createCtorDepType(dep);
3317
+ if (type !== null) {
3318
+ hasTypes = true;
3319
+ return type;
3320
+ }
3321
+ else {
3322
+ return literal(null);
3323
+ }
3324
+ });
3325
+ if (hasTypes) {
3326
+ return expressionType(literalArr(attributeTypes));
3327
+ }
3328
+ else {
3329
+ return NONE_TYPE;
3330
+ }
3145
3331
  }
3146
- function word32ToByteString(word) {
3147
- let bytes = [];
3148
- for (let i = 0; i < 4; i++) {
3149
- bytes.push((word >>> 8 * (3 - i)) & 0xff);
3332
+ function createCtorDepType(dep) {
3333
+ const entries = [];
3334
+ if (dep.attributeNameType !== null) {
3335
+ entries.push({ key: 'attribute', value: dep.attributeNameType, quoted: false });
3150
3336
  }
3151
- return bytes;
3337
+ if (dep.optional) {
3338
+ entries.push({ key: 'optional', value: literal(true), quoted: false });
3339
+ }
3340
+ if (dep.host) {
3341
+ entries.push({ key: 'host', value: literal(true), quoted: false });
3342
+ }
3343
+ if (dep.self) {
3344
+ entries.push({ key: 'self', value: literal(true), quoted: false });
3345
+ }
3346
+ if (dep.skipSelf) {
3347
+ entries.push({ key: 'skipSelf', value: literal(true), quoted: false });
3348
+ }
3349
+ return entries.length > 0 ? literalMap(entries) : null;
3152
3350
  }
3153
- function bytesToHexString(bytes) {
3154
- let hex = '';
3155
- for (let i = 0; i < bytes.length; i++) {
3156
- const b = byteAt(bytes, i);
3157
- hex += (b >>> 4).toString(16) + (b & 0x0f).toString(16);
3351
+ function isDelegatedFactoryMetadata(meta) {
3352
+ return meta.delegateType !== undefined;
3353
+ }
3354
+ function isExpressionFactoryMetadata(meta) {
3355
+ return meta.expression !== undefined;
3356
+ }
3357
+ function getInjectFn(target) {
3358
+ switch (target) {
3359
+ case FactoryTarget.Component:
3360
+ case FactoryTarget.Directive:
3361
+ case FactoryTarget.Pipe:
3362
+ return Identifiers.directiveInject;
3363
+ case FactoryTarget.NgModule:
3364
+ case FactoryTarget.Injectable:
3365
+ default:
3366
+ return Identifiers.inject;
3158
3367
  }
3159
- return hex.toLowerCase();
3160
3368
  }
3369
+
3161
3370
  /**
3162
- * Create a shared exponentiation pool for base-256 computations. This shared pool provides memoized
3163
- * power-of-256 results with memoized power-of-two computations for efficient multiplication.
3371
+ * @license
3372
+ * Copyright Google LLC All Rights Reserved.
3164
3373
  *
3165
- * For our purposes, this can be safely stored as a global without memory concerns. The reason is
3166
- * that we encode two words, so only need the 0th (for the low word) and 4th (for the high word)
3167
- * exponent.
3374
+ * Use of this source code is governed by an MIT-style license that can be
3375
+ * found in the LICENSE file at https://angular.io/license
3168
3376
  */
3169
- const base256 = new BigIntExponentiation(256);
3170
3377
  /**
3171
- * Represents two 32-bit words as a single decimal number. This requires a big integer storage
3172
- * model as JS numbers are not accurate enough to represent the 64-bit number.
3173
- *
3174
- * Based on https://www.danvk.org/hex2dec.html
3378
+ * This is an R3 `Node`-like wrapper for a raw `html.Comment` node. We do not currently
3379
+ * require the implementation of a visitor for Comments as they are only collected at
3380
+ * the top-level of the R3 AST, and only if `Render3ParseOptions['collectCommentNodes']`
3381
+ * is true.
3175
3382
  */
3176
- function wordsToDecimalString(hi, lo) {
3177
- // Encode the four bytes in lo in the lower digits of the decimal number.
3178
- // Note: the multiplication results in lo itself but represented by a big integer using its
3179
- // decimal digits.
3180
- const decimal = base256.toThePowerOf(0).multiplyBy(lo);
3181
- // Encode the four bytes in hi above the four lo bytes. lo is a maximum of (2^8)^4, which is why
3182
- // this multiplication factor is applied.
3183
- base256.toThePowerOf(4).multiplyByAndAddTo(hi, decimal);
3184
- return decimal.toString();
3185
- }
3186
-
3187
- /**
3188
- * @license
3189
- * Copyright Google LLC All Rights Reserved.
3190
- *
3191
- * Use of this source code is governed by an MIT-style license that can be
3192
- * found in the LICENSE file at https://angular.io/license
3193
- */
3194
- // XMB/XTB placeholders can only contain A-Z, 0-9 and _
3195
- function toPublicName(internalName) {
3196
- return internalName.toUpperCase().replace(/[^A-Z0-9_]/g, '_');
3197
- }
3198
-
3199
- /**
3200
- * @license
3201
- * Copyright Google LLC All Rights Reserved.
3202
- *
3203
- * Use of this source code is governed by an MIT-style license that can be
3204
- * found in the LICENSE file at https://angular.io/license
3205
- */
3206
- /* Closure variables holding messages must be named `MSG_[A-Z0-9]+` */
3207
- const CLOSURE_TRANSLATION_VAR_PREFIX = 'MSG_';
3208
- /**
3209
- * Prefix for non-`goog.getMsg` i18n-related vars.
3210
- * Note: the prefix uses lowercase characters intentionally due to a Closure behavior that
3211
- * considers variables like `I18N_0` as constants and throws an error when their value changes.
3212
- */
3213
- const TRANSLATION_VAR_PREFIX = 'i18n_';
3214
- /** Name of the i18n attributes **/
3215
- const I18N_ATTR = 'i18n';
3216
- const I18N_ATTR_PREFIX = 'i18n-';
3217
- /** Prefix of var expressions used in ICUs */
3218
- const I18N_ICU_VAR_PREFIX = 'VAR_';
3219
- /** Prefix of ICU expressions for post processing */
3220
- const I18N_ICU_MAPPING_PREFIX = 'I18N_EXP_';
3221
- /** Placeholder wrapper for i18n expressions **/
3222
- const I18N_PLACEHOLDER_SYMBOL = '�';
3223
- function isI18nAttribute(name) {
3224
- return name === I18N_ATTR || name.startsWith(I18N_ATTR_PREFIX);
3225
- }
3226
- function isI18nRootNode(meta) {
3227
- return meta instanceof Message;
3228
- }
3229
- function isSingleI18nIcu(meta) {
3230
- return isI18nRootNode(meta) && meta.nodes.length === 1 && meta.nodes[0] instanceof Icu$1;
3231
- }
3232
- function hasI18nMeta(node) {
3233
- return !!node.i18n;
3234
- }
3235
- function hasI18nAttrs(element) {
3236
- return element.attrs.some((attr) => isI18nAttribute(attr.name));
3237
- }
3238
- function icuFromI18nMessage(message) {
3239
- return message.nodes[0];
3240
- }
3241
- function wrapI18nPlaceholder(content, contextId = 0) {
3242
- const blockId = contextId > 0 ? `:${contextId}` : '';
3243
- return `${I18N_PLACEHOLDER_SYMBOL}${content}${blockId}${I18N_PLACEHOLDER_SYMBOL}`;
3244
- }
3245
- function assembleI18nBoundString(strings, bindingStartIndex = 0, contextId = 0) {
3246
- if (!strings.length)
3247
- return '';
3248
- let acc = '';
3249
- const lastIdx = strings.length - 1;
3250
- for (let i = 0; i < lastIdx; i++) {
3251
- acc += `${strings[i]}${wrapI18nPlaceholder(bindingStartIndex + i, contextId)}`;
3252
- }
3253
- acc += strings[lastIdx];
3254
- return acc;
3255
- }
3256
- function getSeqNumberGenerator(startsAt = 0) {
3257
- let current = startsAt;
3258
- return () => current++;
3259
- }
3260
- function placeholdersToParams(placeholders) {
3261
- const params = {};
3262
- placeholders.forEach((values, key) => {
3263
- params[key] = literal(values.length > 1 ? `[${values.join('|')}]` : values[0]);
3264
- });
3265
- return params;
3266
- }
3267
- function updatePlaceholderMap(map, name, ...values) {
3268
- const current = map.get(name) || [];
3269
- current.push(...values);
3270
- map.set(name, current);
3271
- }
3272
- function assembleBoundTextPlaceholders(meta, bindingStartIndex = 0, contextId = 0) {
3273
- const startIdx = bindingStartIndex;
3274
- const placeholders = new Map();
3275
- const node = meta instanceof Message ? meta.nodes.find(node => node instanceof Container) : meta;
3276
- if (node) {
3277
- node
3278
- .children
3279
- .filter((child) => child instanceof Placeholder)
3280
- .forEach((child, idx) => {
3281
- const content = wrapI18nPlaceholder(startIdx + idx, contextId);
3282
- updatePlaceholderMap(placeholders, child.name, content);
3283
- });
3383
+ class Comment {
3384
+ constructor(value, sourceSpan) {
3385
+ this.value = value;
3386
+ this.sourceSpan = sourceSpan;
3284
3387
  }
3285
- return placeholders;
3286
- }
3287
- /**
3288
- * Format the placeholder names in a map of placeholders to expressions.
3289
- *
3290
- * The placeholder names are converted from "internal" format (e.g. `START_TAG_DIV_1`) to "external"
3291
- * format (e.g. `startTagDiv_1`).
3292
- *
3293
- * @param params A map of placeholder names to expressions.
3294
- * @param useCamelCase whether to camelCase the placeholder name when formatting.
3295
- * @returns A new map of formatted placeholder names to expressions.
3296
- */
3297
- function i18nFormatPlaceholderNames(params = {}, useCamelCase) {
3298
- const _params = {};
3299
- if (params && Object.keys(params).length) {
3300
- Object.keys(params).forEach(key => _params[formatI18nPlaceholderName(key, useCamelCase)] = params[key]);
3388
+ visit(_visitor) {
3389
+ throw new Error('visit() not implemented for Comment');
3301
3390
  }
3302
- return _params;
3303
3391
  }
3304
- /**
3305
- * Converts internal placeholder names to public-facing format
3306
- * (for example to use in goog.getMsg call).
3307
- * Example: `START_TAG_DIV_1` is converted to `startTagDiv_1`.
3308
- *
3309
- * @param name The placeholder name that should be formatted
3310
- * @returns Formatted placeholder name
3311
- */
3312
- function formatI18nPlaceholderName(name, useCamelCase = true) {
3313
- const publicName = toPublicName(name);
3314
- if (!useCamelCase) {
3315
- return publicName;
3392
+ class Text {
3393
+ constructor(value, sourceSpan) {
3394
+ this.value = value;
3395
+ this.sourceSpan = sourceSpan;
3316
3396
  }
3317
- const chunks = publicName.split('_');
3318
- if (chunks.length === 1) {
3319
- // if no "_" found - just lowercase the value
3320
- return name.toLowerCase();
3397
+ visit(visitor) {
3398
+ return visitor.visitText(this);
3321
3399
  }
3322
- let postfix;
3323
- // eject last element if it's a number
3324
- if (/^\d+$/.test(chunks[chunks.length - 1])) {
3325
- postfix = chunks.pop();
3400
+ }
3401
+ class BoundText {
3402
+ constructor(value, sourceSpan, i18n) {
3403
+ this.value = value;
3404
+ this.sourceSpan = sourceSpan;
3405
+ this.i18n = i18n;
3326
3406
  }
3327
- let raw = chunks.shift().toLowerCase();
3328
- if (chunks.length) {
3329
- raw += chunks.map(c => c.charAt(0).toUpperCase() + c.slice(1).toLowerCase()).join('');
3407
+ visit(visitor) {
3408
+ return visitor.visitBoundText(this);
3330
3409
  }
3331
- return postfix ? `${raw}_${postfix}` : raw;
3332
3410
  }
3333
3411
  /**
3334
- * Generates a prefix for translation const name.
3412
+ * Represents a text attribute in the template.
3335
3413
  *
3336
- * @param extra Additional local prefix that should be injected into translation var name
3337
- * @returns Complete translation const prefix
3338
- */
3339
- function getTranslationConstPrefix(extra) {
3340
- return `${CLOSURE_TRANSLATION_VAR_PREFIX}${extra}`.toUpperCase();
3341
- }
3342
- /**
3343
- * Generate AST to declare a variable. E.g. `var I18N_1;`.
3344
- * @param variable the name of the variable to declare.
3414
+ * `valueSpan` may not be present in cases where there is no value `<div a></div>`.
3415
+ * `keySpan` may also not be present for synthetic attributes from ICU expansions.
3345
3416
  */
3346
- function declareI18nVariable(variable) {
3347
- return new DeclareVarStmt(variable.name, undefined, INFERRED_TYPE, undefined, variable.sourceSpan);
3417
+ class TextAttribute {
3418
+ constructor(name, value, sourceSpan, keySpan, valueSpan, i18n) {
3419
+ this.name = name;
3420
+ this.value = value;
3421
+ this.sourceSpan = sourceSpan;
3422
+ this.keySpan = keySpan;
3423
+ this.valueSpan = valueSpan;
3424
+ this.i18n = i18n;
3425
+ }
3426
+ visit(visitor) {
3427
+ return visitor.visitTextAttribute(this);
3428
+ }
3348
3429
  }
3349
-
3350
- /**
3351
- * @license
3352
- * Copyright Google LLC All Rights Reserved.
3353
- *
3354
- * Use of this source code is governed by an MIT-style license that can be
3355
- * found in the LICENSE file at https://angular.io/license
3356
- */
3357
- /**
3358
- * Checks whether an object key contains potentially unsafe chars, thus the key should be wrapped in
3359
- * quotes. Note: we do not wrap all keys into quotes, as it may have impact on minification and may
3360
- * bot work in some cases when object keys are mangled by minifier.
3361
- *
3362
- * TODO(FW-1136): this is a temporary solution, we need to come up with a better way of working with
3363
- * inputs that contain potentially unsafe chars.
3364
- */
3365
- const UNSAFE_OBJECT_KEY_NAME_REGEXP = /[-.]/;
3366
- /** Name of the temporary to use during data binding */
3367
- const TEMPORARY_NAME = '_t';
3368
- /** Name of the context parameter passed into a template function */
3369
- const CONTEXT_NAME = 'ctx';
3370
- /** Name of the RenderFlag passed into a template function */
3371
- const RENDER_FLAGS = 'rf';
3372
- /** The prefix reference variables */
3373
- const REFERENCE_PREFIX = '_r';
3374
- /** The name of the implicit context reference */
3375
- const IMPLICIT_REFERENCE = '$implicit';
3376
- /** Non bindable attribute name **/
3377
- const NON_BINDABLE_ATTR = 'ngNonBindable';
3378
- /** Name for the variable keeping track of the context returned by `ɵɵrestoreView`. */
3379
- const RESTORED_VIEW_CONTEXT_NAME = 'restoredCtx';
3380
- /**
3381
- * Creates an allocator for a temporary variable.
3382
- *
3383
- * A variable declaration is added to the statements the first time the allocator is invoked.
3384
- */
3385
- function temporaryAllocator(statements, name) {
3386
- let temp = null;
3387
- return () => {
3388
- if (!temp) {
3389
- statements.push(new DeclareVarStmt(TEMPORARY_NAME, undefined, DYNAMIC_TYPE));
3390
- temp = variable(name);
3430
+ class BoundAttribute {
3431
+ constructor(name, type, securityContext, value, unit, sourceSpan, keySpan, valueSpan, i18n) {
3432
+ this.name = name;
3433
+ this.type = type;
3434
+ this.securityContext = securityContext;
3435
+ this.value = value;
3436
+ this.unit = unit;
3437
+ this.sourceSpan = sourceSpan;
3438
+ this.keySpan = keySpan;
3439
+ this.valueSpan = valueSpan;
3440
+ this.i18n = i18n;
3441
+ }
3442
+ static fromBoundElementProperty(prop, i18n) {
3443
+ if (prop.keySpan === undefined) {
3444
+ throw new Error(`Unexpected state: keySpan must be defined for bound attributes but was not for ${prop.name}: ${prop.sourceSpan}`);
3391
3445
  }
3392
- return temp;
3393
- };
3394
- }
3395
- function unsupported(feature) {
3396
- if (this) {
3397
- throw new Error(`Builder ${this.constructor.name} doesn't support ${feature} yet`);
3446
+ return new BoundAttribute(prop.name, prop.type, prop.securityContext, prop.value, prop.unit, prop.sourceSpan, prop.keySpan, prop.valueSpan, i18n);
3398
3447
  }
3399
- throw new Error(`Feature ${feature} is not supported yet`);
3400
- }
3401
- function invalid$1(arg) {
3402
- throw new Error(`Invalid state: Visitor ${this.constructor.name} doesn't handle ${arg.constructor.name}`);
3403
- }
3404
- function asLiteral(value) {
3405
- if (Array.isArray(value)) {
3406
- return literalArr(value.map(asLiteral));
3448
+ visit(visitor) {
3449
+ return visitor.visitBoundAttribute(this);
3407
3450
  }
3408
- return literal(value, INFERRED_TYPE);
3409
3451
  }
3410
- function conditionallyCreateMapObjectLiteral(keys, keepDeclared) {
3411
- if (Object.getOwnPropertyNames(keys).length > 0) {
3412
- return mapToExpression(keys, keepDeclared);
3452
+ class BoundEvent {
3453
+ constructor(name, type, handler, target, phase, sourceSpan, handlerSpan, keySpan) {
3454
+ this.name = name;
3455
+ this.type = type;
3456
+ this.handler = handler;
3457
+ this.target = target;
3458
+ this.phase = phase;
3459
+ this.sourceSpan = sourceSpan;
3460
+ this.handlerSpan = handlerSpan;
3461
+ this.keySpan = keySpan;
3413
3462
  }
3414
- return null;
3415
- }
3416
- function mapToExpression(map, keepDeclared) {
3417
- return literalMap(Object.getOwnPropertyNames(map).map(key => {
3418
- // canonical syntax: `dirProp: publicProp`
3419
- // if there is no `:`, use dirProp = elProp
3420
- const value = map[key];
3421
- let declaredName;
3422
- let publicName;
3423
- let minifiedName;
3424
- let needsDeclaredName;
3425
- if (Array.isArray(value)) {
3426
- [publicName, declaredName] = value;
3427
- minifiedName = key;
3428
- needsDeclaredName = publicName !== declaredName;
3429
- }
3430
- else {
3431
- [declaredName, publicName] = splitAtColon(key, [key, value]);
3432
- minifiedName = declaredName;
3433
- // Only include the declared name if extracted from the key, i.e. the key contains a colon.
3434
- // Otherwise the declared name should be omitted even if it is different from the public name,
3435
- // as it may have already been minified.
3436
- needsDeclaredName = publicName !== declaredName && key.includes(':');
3463
+ static fromParsedEvent(event) {
3464
+ const target = event.type === 0 /* Regular */ ? event.targetOrPhase : null;
3465
+ const phase = event.type === 1 /* Animation */ ? event.targetOrPhase : null;
3466
+ if (event.keySpan === undefined) {
3467
+ throw new Error(`Unexpected state: keySpan must be defined for bound event but was not for ${event.name}: ${event.sourceSpan}`);
3437
3468
  }
3438
- return {
3439
- key: minifiedName,
3440
- // put quotes around keys that contain potentially unsafe characters
3441
- quoted: UNSAFE_OBJECT_KEY_NAME_REGEXP.test(minifiedName),
3442
- value: (keepDeclared && needsDeclaredName) ?
3443
- literalArr([asLiteral(publicName), asLiteral(declaredName)]) :
3444
- asLiteral(publicName)
3445
- };
3446
- }));
3469
+ return new BoundEvent(event.name, event.type, event.handler, target, phase, event.sourceSpan, event.handlerSpan, event.keySpan);
3470
+ }
3471
+ visit(visitor) {
3472
+ return visitor.visitBoundEvent(this);
3473
+ }
3447
3474
  }
3448
- /**
3449
- * Remove trailing null nodes as they are implied.
3450
- */
3451
- function trimTrailingNulls(parameters) {
3452
- while (isNull(parameters[parameters.length - 1])) {
3453
- parameters.pop();
3475
+ class Element {
3476
+ constructor(name, attributes, inputs, outputs, children, references, sourceSpan, startSourceSpan, endSourceSpan, i18n) {
3477
+ this.name = name;
3478
+ this.attributes = attributes;
3479
+ this.inputs = inputs;
3480
+ this.outputs = outputs;
3481
+ this.children = children;
3482
+ this.references = references;
3483
+ this.sourceSpan = sourceSpan;
3484
+ this.startSourceSpan = startSourceSpan;
3485
+ this.endSourceSpan = endSourceSpan;
3486
+ this.i18n = i18n;
3487
+ }
3488
+ visit(visitor) {
3489
+ return visitor.visitElement(this);
3454
3490
  }
3455
- return parameters;
3456
3491
  }
3457
- function getQueryPredicate(query, constantPool) {
3458
- if (Array.isArray(query.predicate)) {
3459
- let predicate = [];
3460
- query.predicate.forEach((selector) => {
3461
- // Each item in predicates array may contain strings with comma-separated refs
3462
- // (for ex. 'ref, ref1, ..., refN'), thus we extract individual refs and store them
3463
- // as separate array entities
3464
- const selectors = selector.split(',').map(token => literal(token.trim()));
3465
- predicate.push(...selectors);
3466
- });
3467
- return constantPool.getConstLiteral(literalArr(predicate), true);
3492
+ class Template {
3493
+ constructor(tagName, attributes, inputs, outputs, templateAttrs, children, references, variables, sourceSpan, startSourceSpan, endSourceSpan, i18n) {
3494
+ this.tagName = tagName;
3495
+ this.attributes = attributes;
3496
+ this.inputs = inputs;
3497
+ this.outputs = outputs;
3498
+ this.templateAttrs = templateAttrs;
3499
+ this.children = children;
3500
+ this.references = references;
3501
+ this.variables = variables;
3502
+ this.sourceSpan = sourceSpan;
3503
+ this.startSourceSpan = startSourceSpan;
3504
+ this.endSourceSpan = endSourceSpan;
3505
+ this.i18n = i18n;
3468
3506
  }
3469
- else {
3470
- return query.predicate;
3507
+ visit(visitor) {
3508
+ return visitor.visitTemplate(this);
3471
3509
  }
3472
3510
  }
3473
- /**
3474
- * A representation for an object literal used during codegen of definition objects. The generic
3475
- * type `T` allows to reference a documented type of the generated structure, such that the
3476
- * property names that are set can be resolved to their documented declaration.
3477
- */
3478
- class DefinitionMap {
3479
- constructor() {
3480
- this.values = [];
3511
+ class Content {
3512
+ constructor(selector, attributes, sourceSpan, i18n) {
3513
+ this.selector = selector;
3514
+ this.attributes = attributes;
3515
+ this.sourceSpan = sourceSpan;
3516
+ this.i18n = i18n;
3517
+ this.name = 'ng-content';
3481
3518
  }
3482
- set(key, value) {
3483
- if (value) {
3484
- this.values.push({ key: key, value, quoted: false });
3485
- }
3519
+ visit(visitor) {
3520
+ return visitor.visitContent(this);
3486
3521
  }
3487
- toLiteralMap() {
3488
- return literalMap(this.values);
3522
+ }
3523
+ class Variable {
3524
+ constructor(name, value, sourceSpan, keySpan, valueSpan) {
3525
+ this.name = name;
3526
+ this.value = value;
3527
+ this.sourceSpan = sourceSpan;
3528
+ this.keySpan = keySpan;
3529
+ this.valueSpan = valueSpan;
3530
+ }
3531
+ visit(visitor) {
3532
+ return visitor.visitVariable(this);
3489
3533
  }
3490
3534
  }
3491
- /**
3492
- * Extract a map of properties to values for a given element or template node, which can be used
3493
- * by the directive matching machinery.
3494
- *
3495
- * @param elOrTpl the element or template in question
3496
- * @return an object set up for directive matching. For attributes on the element/template, this
3497
- * object maps a property name to its (static) value. For any bindings, this map simply maps the
3498
- * property name to an empty string.
3499
- */
3500
- function getAttrsForDirectiveMatching(elOrTpl) {
3501
- const attributesMap = {};
3502
- if (elOrTpl instanceof Template && elOrTpl.tagName !== 'ng-template') {
3503
- elOrTpl.templateAttrs.forEach(a => attributesMap[a.name] = '');
3535
+ class Reference {
3536
+ constructor(name, value, sourceSpan, keySpan, valueSpan) {
3537
+ this.name = name;
3538
+ this.value = value;
3539
+ this.sourceSpan = sourceSpan;
3540
+ this.keySpan = keySpan;
3541
+ this.valueSpan = valueSpan;
3504
3542
  }
3505
- else {
3506
- elOrTpl.attributes.forEach(a => {
3507
- if (!isI18nAttribute(a.name)) {
3508
- attributesMap[a.name] = a.value;
3509
- }
3510
- });
3511
- elOrTpl.inputs.forEach(i => {
3512
- attributesMap[i.name] = '';
3513
- });
3514
- elOrTpl.outputs.forEach(o => {
3515
- attributesMap[o.name] = '';
3516
- });
3543
+ visit(visitor) {
3544
+ return visitor.visitReference(this);
3517
3545
  }
3518
- return attributesMap;
3519
3546
  }
3520
- /** Returns a call expression to a chained instruction, e.g. `property(params[0])(params[1])`. */
3521
- function chainedInstruction(reference, calls, span) {
3522
- let expression = importExpr(reference, null, span);
3523
- if (calls.length > 0) {
3524
- for (let i = 0; i < calls.length; i++) {
3525
- expression = expression.callFn(calls[i], span);
3526
- }
3547
+ class Icu {
3548
+ constructor(vars, placeholders, sourceSpan, i18n) {
3549
+ this.vars = vars;
3550
+ this.placeholders = placeholders;
3551
+ this.sourceSpan = sourceSpan;
3552
+ this.i18n = i18n;
3527
3553
  }
3528
- else {
3529
- // Add a blank invocation, in case the `calls` array is empty.
3530
- expression = expression.callFn([], span);
3554
+ visit(visitor) {
3555
+ return visitor.visitIcu(this);
3531
3556
  }
3532
- return expression;
3533
3557
  }
3534
- /**
3535
- * Gets the number of arguments expected to be passed to a generated instruction in the case of
3536
- * interpolation instructions.
3537
- * @param interpolation An interpolation ast
3538
- */
3539
- function getInterpolationArgsLength(interpolation) {
3540
- const { expressions, strings } = interpolation;
3541
- if (expressions.length === 1 && strings.length === 2 && strings[0] === '' && strings[1] === '') {
3542
- // If the interpolation has one interpolated value, but the prefix and suffix are both empty
3543
- // strings, we only pass one argument, to a special instruction like `propertyInterpolate` or
3544
- // `textInterpolate`.
3545
- return 1;
3558
+ function visitAll(visitor, nodes) {
3559
+ const result = [];
3560
+ if (visitor.visit) {
3561
+ for (const node of nodes) {
3562
+ const newNode = visitor.visit(node) || node.visit(visitor);
3563
+ }
3546
3564
  }
3547
3565
  else {
3548
- return expressions.length + strings.length;
3566
+ for (const node of nodes) {
3567
+ const newNode = node.visit(visitor);
3568
+ if (newNode) {
3569
+ result.push(newNode);
3570
+ }
3571
+ }
3549
3572
  }
3573
+ return result;
3550
3574
  }
3551
3575
 
3552
3576
  /**
@@ -3556,164 +3580,106 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
3556
3580
  * Use of this source code is governed by an MIT-style license that can be
3557
3581
  * found in the LICENSE file at https://angular.io/license
3558
3582
  */
3559
- /**
3560
- * Generate an expression that has the given `expr` wrapped in the following form:
3561
- *
3562
- * ```
3563
- * forwardRef(() => expr)
3564
- * ```
3565
- */
3566
- function generateForwardRef(expr) {
3567
- return importExpr(Identifiers.forwardRef).callFn([fn([], [new ReturnStatement(expr)])]);
3568
- }
3569
-
3570
- /**
3571
- * @license
3572
- * Copyright Google LLC All Rights Reserved.
3573
- *
3574
- * Use of this source code is governed by an MIT-style license that can be
3575
- * found in the LICENSE file at https://angular.io/license
3576
- */
3577
- // https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit
3578
- const VERSION = 3;
3579
- const JS_B64_PREFIX = '# sourceMappingURL=data:application/json;base64,';
3580
- class SourceMapGenerator {
3581
- constructor(file = null) {
3582
- this.file = file;
3583
- this.sourcesContent = new Map();
3584
- this.lines = [];
3585
- this.lastCol0 = 0;
3586
- this.hasMappings = false;
3587
- }
3588
- // The content is `null` when the content is expected to be loaded using the URL
3589
- addSource(url, content = null) {
3590
- if (!this.sourcesContent.has(url)) {
3591
- this.sourcesContent.set(url, content);
3583
+ class Message {
3584
+ /**
3585
+ * @param nodes message AST
3586
+ * @param placeholders maps placeholder names to static content and their source spans
3587
+ * @param placeholderToMessage maps placeholder names to messages (used for nested ICU messages)
3588
+ * @param meaning
3589
+ * @param description
3590
+ * @param customId
3591
+ */
3592
+ constructor(nodes, placeholders, placeholderToMessage, meaning, description, customId) {
3593
+ this.nodes = nodes;
3594
+ this.placeholders = placeholders;
3595
+ this.placeholderToMessage = placeholderToMessage;
3596
+ this.meaning = meaning;
3597
+ this.description = description;
3598
+ this.customId = customId;
3599
+ this.id = this.customId;
3600
+ /** The ids to use if there are no custom id and if `i18nLegacyMessageIdFormat` is not empty */
3601
+ this.legacyIds = [];
3602
+ if (nodes.length) {
3603
+ this.sources = [{
3604
+ filePath: nodes[0].sourceSpan.start.file.url,
3605
+ startLine: nodes[0].sourceSpan.start.line + 1,
3606
+ startCol: nodes[0].sourceSpan.start.col + 1,
3607
+ endLine: nodes[nodes.length - 1].sourceSpan.end.line + 1,
3608
+ endCol: nodes[0].sourceSpan.start.col + 1
3609
+ }];
3610
+ }
3611
+ else {
3612
+ this.sources = [];
3592
3613
  }
3593
- return this;
3594
3614
  }
3595
- addLine() {
3596
- this.lines.push([]);
3597
- this.lastCol0 = 0;
3598
- return this;
3615
+ }
3616
+ class Text$1 {
3617
+ constructor(value, sourceSpan) {
3618
+ this.value = value;
3619
+ this.sourceSpan = sourceSpan;
3599
3620
  }
3600
- addMapping(col0, sourceUrl, sourceLine0, sourceCol0) {
3601
- if (!this.currentLine) {
3602
- throw new Error(`A line must be added before mappings can be added`);
3603
- }
3604
- if (sourceUrl != null && !this.sourcesContent.has(sourceUrl)) {
3605
- throw new Error(`Unknown source file "${sourceUrl}"`);
3606
- }
3607
- if (col0 == null) {
3608
- throw new Error(`The column in the generated code must be provided`);
3609
- }
3610
- if (col0 < this.lastCol0) {
3611
- throw new Error(`Mapping should be added in output order`);
3612
- }
3613
- if (sourceUrl && (sourceLine0 == null || sourceCol0 == null)) {
3614
- throw new Error(`The source location must be provided when a source url is provided`);
3615
- }
3616
- this.hasMappings = true;
3617
- this.lastCol0 = col0;
3618
- this.currentLine.push({ col0, sourceUrl, sourceLine0, sourceCol0 });
3619
- return this;
3621
+ visit(visitor, context) {
3622
+ return visitor.visitText(this, context);
3620
3623
  }
3621
- /**
3622
- * @internal strip this from published d.ts files due to
3623
- * https://github.com/microsoft/TypeScript/issues/36216
3624
- */
3625
- get currentLine() {
3626
- return this.lines.slice(-1)[0];
3624
+ }
3625
+ // TODO(vicb): do we really need this node (vs an array) ?
3626
+ class Container {
3627
+ constructor(children, sourceSpan) {
3628
+ this.children = children;
3629
+ this.sourceSpan = sourceSpan;
3627
3630
  }
3628
- toJSON() {
3629
- if (!this.hasMappings) {
3630
- return null;
3631
- }
3632
- const sourcesIndex = new Map();
3633
- const sources = [];
3634
- const sourcesContent = [];
3635
- Array.from(this.sourcesContent.keys()).forEach((url, i) => {
3636
- sourcesIndex.set(url, i);
3637
- sources.push(url);
3638
- sourcesContent.push(this.sourcesContent.get(url) || null);
3639
- });
3640
- let mappings = '';
3641
- let lastCol0 = 0;
3642
- let lastSourceIndex = 0;
3643
- let lastSourceLine0 = 0;
3644
- let lastSourceCol0 = 0;
3645
- this.lines.forEach(segments => {
3646
- lastCol0 = 0;
3647
- mappings += segments
3648
- .map(segment => {
3649
- // zero-based starting column of the line in the generated code
3650
- let segAsStr = toBase64VLQ(segment.col0 - lastCol0);
3651
- lastCol0 = segment.col0;
3652
- if (segment.sourceUrl != null) {
3653
- // zero-based index into the “sources” list
3654
- segAsStr +=
3655
- toBase64VLQ(sourcesIndex.get(segment.sourceUrl) - lastSourceIndex);
3656
- lastSourceIndex = sourcesIndex.get(segment.sourceUrl);
3657
- // the zero-based starting line in the original source
3658
- segAsStr += toBase64VLQ(segment.sourceLine0 - lastSourceLine0);
3659
- lastSourceLine0 = segment.sourceLine0;
3660
- // the zero-based starting column in the original source
3661
- segAsStr += toBase64VLQ(segment.sourceCol0 - lastSourceCol0);
3662
- lastSourceCol0 = segment.sourceCol0;
3663
- }
3664
- return segAsStr;
3665
- })
3666
- .join(',');
3667
- mappings += ';';
3668
- });
3669
- mappings = mappings.slice(0, -1);
3670
- return {
3671
- 'file': this.file || '',
3672
- 'version': VERSION,
3673
- 'sourceRoot': '',
3674
- 'sources': sources,
3675
- 'sourcesContent': sourcesContent,
3676
- 'mappings': mappings,
3677
- };
3631
+ visit(visitor, context) {
3632
+ return visitor.visitContainer(this, context);
3678
3633
  }
3679
- toJsComment() {
3680
- return this.hasMappings ? '//' + JS_B64_PREFIX + toBase64String(JSON.stringify(this, null, 0)) :
3681
- '';
3634
+ }
3635
+ class Icu$1 {
3636
+ constructor(expression, type, cases, sourceSpan) {
3637
+ this.expression = expression;
3638
+ this.type = type;
3639
+ this.cases = cases;
3640
+ this.sourceSpan = sourceSpan;
3641
+ }
3642
+ visit(visitor, context) {
3643
+ return visitor.visitIcu(this, context);
3682
3644
  }
3683
3645
  }
3684
- function toBase64String(value) {
3685
- let b64 = '';
3686
- const encoded = utf8Encode(value);
3687
- for (let i = 0; i < encoded.length;) {
3688
- const i1 = encoded[i++];
3689
- const i2 = i < encoded.length ? encoded[i++] : null;
3690
- const i3 = i < encoded.length ? encoded[i++] : null;
3691
- b64 += toBase64Digit(i1 >> 2);
3692
- b64 += toBase64Digit(((i1 & 3) << 4) | (i2 === null ? 0 : i2 >> 4));
3693
- b64 += i2 === null ? '=' : toBase64Digit(((i2 & 15) << 2) | (i3 === null ? 0 : i3 >> 6));
3694
- b64 += i2 === null || i3 === null ? '=' : toBase64Digit(i3 & 63);
3646
+ class TagPlaceholder {
3647
+ constructor(tag, attrs, startName, closeName, children, isVoid,
3648
+ // TODO sourceSpan should cover all (we need a startSourceSpan and endSourceSpan)
3649
+ sourceSpan, startSourceSpan, endSourceSpan) {
3650
+ this.tag = tag;
3651
+ this.attrs = attrs;
3652
+ this.startName = startName;
3653
+ this.closeName = closeName;
3654
+ this.children = children;
3655
+ this.isVoid = isVoid;
3656
+ this.sourceSpan = sourceSpan;
3657
+ this.startSourceSpan = startSourceSpan;
3658
+ this.endSourceSpan = endSourceSpan;
3659
+ }
3660
+ visit(visitor, context) {
3661
+ return visitor.visitTagPlaceholder(this, context);
3695
3662
  }
3696
- return b64;
3697
3663
  }
3698
- function toBase64VLQ(value) {
3699
- value = value < 0 ? ((-value) << 1) + 1 : value << 1;
3700
- let out = '';
3701
- do {
3702
- let digit = value & 31;
3703
- value = value >> 5;
3704
- if (value > 0) {
3705
- digit = digit | 32;
3706
- }
3707
- out += toBase64Digit(digit);
3708
- } while (value > 0);
3709
- return out;
3664
+ class Placeholder {
3665
+ constructor(value, name, sourceSpan) {
3666
+ this.value = value;
3667
+ this.name = name;
3668
+ this.sourceSpan = sourceSpan;
3669
+ }
3670
+ visit(visitor, context) {
3671
+ return visitor.visitPlaceholder(this, context);
3672
+ }
3710
3673
  }
3711
- const B64_DIGITS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
3712
- function toBase64Digit(value) {
3713
- if (value < 0 || value >= 64) {
3714
- throw new Error(`Can only encode value in the range [0, 63]`);
3674
+ class IcuPlaceholder {
3675
+ constructor(value, name, sourceSpan) {
3676
+ this.value = value;
3677
+ this.name = name;
3678
+ this.sourceSpan = sourceSpan;
3679
+ }
3680
+ visit(visitor, context) {
3681
+ return visitor.visitIcuPlaceholder(this, context);
3715
3682
  }
3716
- return B64_DIGITS[value];
3717
3683
  }
3718
3684
 
3719
3685
  /**
@@ -3723,566 +3689,656 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
3723
3689
  * Use of this source code is governed by an MIT-style license that can be
3724
3690
  * found in the LICENSE file at https://angular.io/license
3725
3691
  */
3726
- const _SINGLE_QUOTE_ESCAPE_STRING_RE = /'|\\|\n|\r|\$/g;
3727
- const _LEGAL_IDENTIFIER_RE = /^[$A-Z_][0-9A-Z_$]*$/i;
3728
- const _INDENT_WITH = ' ';
3729
- const CATCH_ERROR_VAR$1 = variable('error', null, null);
3730
- const CATCH_STACK_VAR$1 = variable('stack', null, null);
3731
- class _EmittedLine {
3732
- constructor(indent) {
3733
- this.indent = indent;
3734
- this.partsLength = 0;
3735
- this.parts = [];
3736
- this.srcSpans = [];
3737
- }
3738
- }
3739
- class EmitterVisitorContext {
3740
- constructor(_indent) {
3741
- this._indent = _indent;
3742
- this._classes = [];
3743
- this._preambleLineCount = 0;
3744
- this._lines = [new _EmittedLine(_indent)];
3745
- }
3746
- static createRoot() {
3747
- return new EmitterVisitorContext(0);
3748
- }
3692
+ /**
3693
+ * Represents a big integer using a buffer of its individual digits, with the least significant
3694
+ * digit stored at the beginning of the array (little endian).
3695
+ *
3696
+ * For performance reasons, each instance is mutable. The addition operation can be done in-place
3697
+ * to reduce memory pressure of allocation for the digits array.
3698
+ */
3699
+ class BigInteger {
3749
3700
  /**
3750
- * @internal strip this from published d.ts files due to
3751
- * https://github.com/microsoft/TypeScript/issues/36216
3701
+ * Creates a big integer using its individual digits in little endian storage.
3752
3702
  */
3753
- get _currentLine() {
3754
- return this._lines[this._lines.length - 1];
3703
+ constructor(digits) {
3704
+ this.digits = digits;
3755
3705
  }
3756
- println(from, lastPart = '') {
3757
- this.print(from || null, lastPart, true);
3706
+ static zero() {
3707
+ return new BigInteger([0]);
3758
3708
  }
3759
- lineIsEmpty() {
3760
- return this._currentLine.parts.length === 0;
3709
+ static one() {
3710
+ return new BigInteger([1]);
3761
3711
  }
3762
- lineLength() {
3763
- return this._currentLine.indent * _INDENT_WITH.length + this._currentLine.partsLength;
3712
+ /**
3713
+ * Creates a clone of this instance.
3714
+ */
3715
+ clone() {
3716
+ return new BigInteger(this.digits.slice());
3764
3717
  }
3765
- print(from, part, newLine = false) {
3766
- if (part.length > 0) {
3767
- this._currentLine.parts.push(part);
3768
- this._currentLine.partsLength += part.length;
3769
- this._currentLine.srcSpans.push(from && from.sourceSpan || null);
3770
- }
3771
- if (newLine) {
3772
- this._lines.push(new _EmittedLine(this._indent));
3773
- }
3718
+ /**
3719
+ * Returns a new big integer with the sum of `this` and `other` as its value. This does not mutate
3720
+ * `this` but instead returns a new instance, unlike `addToSelf`.
3721
+ */
3722
+ add(other) {
3723
+ const result = this.clone();
3724
+ result.addToSelf(other);
3725
+ return result;
3774
3726
  }
3775
- removeEmptyLastLine() {
3776
- if (this.lineIsEmpty()) {
3777
- this._lines.pop();
3727
+ /**
3728
+ * Adds `other` to the instance itself, thereby mutating its value.
3729
+ */
3730
+ addToSelf(other) {
3731
+ const maxNrOfDigits = Math.max(this.digits.length, other.digits.length);
3732
+ let carry = 0;
3733
+ for (let i = 0; i < maxNrOfDigits; i++) {
3734
+ let digitSum = carry;
3735
+ if (i < this.digits.length) {
3736
+ digitSum += this.digits[i];
3737
+ }
3738
+ if (i < other.digits.length) {
3739
+ digitSum += other.digits[i];
3740
+ }
3741
+ if (digitSum >= 10) {
3742
+ this.digits[i] = digitSum - 10;
3743
+ carry = 1;
3744
+ }
3745
+ else {
3746
+ this.digits[i] = digitSum;
3747
+ carry = 0;
3748
+ }
3778
3749
  }
3779
- }
3780
- incIndent() {
3781
- this._indent++;
3782
- if (this.lineIsEmpty()) {
3783
- this._currentLine.indent = this._indent;
3750
+ // Apply a remaining carry if needed.
3751
+ if (carry > 0) {
3752
+ this.digits[maxNrOfDigits] = 1;
3784
3753
  }
3785
3754
  }
3786
- decIndent() {
3787
- this._indent--;
3788
- if (this.lineIsEmpty()) {
3789
- this._currentLine.indent = this._indent;
3755
+ /**
3756
+ * Builds the decimal string representation of the big integer. As this is stored in
3757
+ * little endian, the digits are concatenated in reverse order.
3758
+ */
3759
+ toString() {
3760
+ let res = '';
3761
+ for (let i = this.digits.length - 1; i >= 0; i--) {
3762
+ res += this.digits[i];
3790
3763
  }
3764
+ return res;
3791
3765
  }
3792
- pushClass(clazz) {
3793
- this._classes.push(clazz);
3794
- }
3795
- popClass() {
3796
- return this._classes.pop();
3797
- }
3798
- get currentClass() {
3799
- return this._classes.length > 0 ? this._classes[this._classes.length - 1] : null;
3800
- }
3801
- toSource() {
3802
- return this.sourceLines
3803
- .map(l => l.parts.length > 0 ? _createIndent(l.indent) + l.parts.join('') : '')
3804
- .join('\n');
3766
+ }
3767
+ /**
3768
+ * Represents a big integer which is optimized for multiplication operations, as its power-of-twos
3769
+ * are memoized. See `multiplyBy()` for details on the multiplication algorithm.
3770
+ */
3771
+ class BigIntForMultiplication {
3772
+ constructor(value) {
3773
+ this.powerOfTwos = [value];
3805
3774
  }
3806
- toSourceMapGenerator(genFilePath, startsAtLine = 0) {
3807
- const map = new SourceMapGenerator(genFilePath);
3808
- let firstOffsetMapped = false;
3809
- const mapFirstOffsetIfNeeded = () => {
3810
- if (!firstOffsetMapped) {
3811
- // Add a single space so that tools won't try to load the file from disk.
3812
- // Note: We are using virtual urls like `ng:///`, so we have to
3813
- // provide a content here.
3814
- map.addSource(genFilePath, ' ').addMapping(0, genFilePath, 0, 0);
3815
- firstOffsetMapped = true;
3816
- }
3817
- };
3818
- for (let i = 0; i < startsAtLine; i++) {
3819
- map.addLine();
3820
- mapFirstOffsetIfNeeded();
3821
- }
3822
- this.sourceLines.forEach((line, lineIdx) => {
3823
- map.addLine();
3824
- const spans = line.srcSpans;
3825
- const parts = line.parts;
3826
- let col0 = line.indent * _INDENT_WITH.length;
3827
- let spanIdx = 0;
3828
- // skip leading parts without source spans
3829
- while (spanIdx < spans.length && !spans[spanIdx]) {
3830
- col0 += parts[spanIdx].length;
3831
- spanIdx++;
3832
- }
3833
- if (spanIdx < spans.length && lineIdx === 0 && col0 === 0) {
3834
- firstOffsetMapped = true;
3835
- }
3836
- else {
3837
- mapFirstOffsetIfNeeded();
3838
- }
3839
- while (spanIdx < spans.length) {
3840
- const span = spans[spanIdx];
3841
- const source = span.start.file;
3842
- const sourceLine = span.start.line;
3843
- const sourceCol = span.start.col;
3844
- map.addSource(source.url, source.content)
3845
- .addMapping(col0, source.url, sourceLine, sourceCol);
3846
- col0 += parts[spanIdx].length;
3847
- spanIdx++;
3848
- // assign parts without span or the same span to the previous segment
3849
- while (spanIdx < spans.length && (span === spans[spanIdx] || !spans[spanIdx])) {
3850
- col0 += parts[spanIdx].length;
3851
- spanIdx++;
3852
- }
3853
- }
3854
- });
3855
- return map;
3775
+ /**
3776
+ * Returns the big integer itself.
3777
+ */
3778
+ getValue() {
3779
+ return this.powerOfTwos[0];
3856
3780
  }
3857
- setPreambleLineCount(count) {
3858
- return this._preambleLineCount = count;
3781
+ /**
3782
+ * Computes the value for `num * b`, where `num` is a JS number and `b` is a big integer. The
3783
+ * value for `b` is represented by a storage model that is optimized for this computation.
3784
+ *
3785
+ * This operation is implemented in N(log2(num)) by continuous halving of the number, where the
3786
+ * least-significant bit (LSB) is tested in each iteration. If the bit is set, the bit's index is
3787
+ * used as exponent into the power-of-two multiplication of `b`.
3788
+ *
3789
+ * As an example, consider the multiplication num=42, b=1337. In binary 42 is 0b00101010 and the
3790
+ * algorithm unrolls into the following iterations:
3791
+ *
3792
+ * Iteration | num | LSB | b * 2^iter | Add? | product
3793
+ * -----------|------------|------|------------|------|--------
3794
+ * 0 | 0b00101010 | 0 | 1337 | No | 0
3795
+ * 1 | 0b00010101 | 1 | 2674 | Yes | 2674
3796
+ * 2 | 0b00001010 | 0 | 5348 | No | 2674
3797
+ * 3 | 0b00000101 | 1 | 10696 | Yes | 13370
3798
+ * 4 | 0b00000010 | 0 | 21392 | No | 13370
3799
+ * 5 | 0b00000001 | 1 | 42784 | Yes | 56154
3800
+ * 6 | 0b00000000 | 0 | 85568 | No | 56154
3801
+ *
3802
+ * The computed product of 56154 is indeed the correct result.
3803
+ *
3804
+ * The `BigIntForMultiplication` representation for a big integer provides memoized access to the
3805
+ * power-of-two values to reduce the workload in computing those values.
3806
+ */
3807
+ multiplyBy(num) {
3808
+ const product = BigInteger.zero();
3809
+ this.multiplyByAndAddTo(num, product);
3810
+ return product;
3859
3811
  }
3860
- spanOf(line, column) {
3861
- const emittedLine = this._lines[line - this._preambleLineCount];
3862
- if (emittedLine) {
3863
- let columnsLeft = column - _createIndent(emittedLine.indent).length;
3864
- for (let partIndex = 0; partIndex < emittedLine.parts.length; partIndex++) {
3865
- const part = emittedLine.parts[partIndex];
3866
- if (part.length > columnsLeft) {
3867
- return emittedLine.srcSpans[partIndex];
3868
- }
3869
- columnsLeft -= part.length;
3812
+ /**
3813
+ * See `multiplyBy()` for details. This function allows for the computed product to be added
3814
+ * directly to the provided result big integer.
3815
+ */
3816
+ multiplyByAndAddTo(num, result) {
3817
+ for (let exponent = 0; num !== 0; num = num >>> 1, exponent++) {
3818
+ if (num & 1) {
3819
+ const value = this.getMultipliedByPowerOfTwo(exponent);
3820
+ result.addToSelf(value);
3870
3821
  }
3871
3822
  }
3872
- return null;
3873
3823
  }
3874
3824
  /**
3875
- * @internal strip this from published d.ts files due to
3876
- * https://github.com/microsoft/TypeScript/issues/36216
3825
+ * Computes and memoizes the big integer value for `this.number * 2^exponent`.
3877
3826
  */
3878
- get sourceLines() {
3879
- if (this._lines.length && this._lines[this._lines.length - 1].parts.length === 0) {
3880
- return this._lines.slice(0, -1);
3827
+ getMultipliedByPowerOfTwo(exponent) {
3828
+ // Compute the powers up until the requested exponent, where each value is computed from its
3829
+ // predecessor. This is simple as `this.number * 2^(exponent - 1)` only has to be doubled (i.e.
3830
+ // added to itself) to reach `this.number * 2^exponent`.
3831
+ for (let i = this.powerOfTwos.length; i <= exponent; i++) {
3832
+ const previousPower = this.powerOfTwos[i - 1];
3833
+ this.powerOfTwos[i] = previousPower.add(previousPower);
3881
3834
  }
3882
- return this._lines;
3835
+ return this.powerOfTwos[exponent];
3883
3836
  }
3884
3837
  }
3885
- class AbstractEmitterVisitor {
3886
- constructor(_escapeDollarInStrings) {
3887
- this._escapeDollarInStrings = _escapeDollarInStrings;
3838
+ /**
3839
+ * Represents an exponentiation operation for the provided base, of which exponents are computed and
3840
+ * memoized. The results are represented by a `BigIntForMultiplication` which is tailored for
3841
+ * multiplication operations by memoizing the power-of-twos. This effectively results in a matrix
3842
+ * representation that is lazily computed upon request.
3843
+ */
3844
+ class BigIntExponentiation {
3845
+ constructor(base) {
3846
+ this.base = base;
3847
+ this.exponents = [new BigIntForMultiplication(BigInteger.one())];
3888
3848
  }
3889
- printLeadingComments(stmt, ctx) {
3890
- if (stmt.leadingComments === undefined) {
3891
- return;
3892
- }
3893
- for (const comment of stmt.leadingComments) {
3894
- if (comment instanceof JSDocComment) {
3895
- ctx.print(stmt, `/*${comment.toString()}*/`, comment.trailingNewline);
3896
- }
3897
- else {
3898
- if (comment.multiline) {
3899
- ctx.print(stmt, `/* ${comment.text} */`, comment.trailingNewline);
3900
- }
3901
- else {
3902
- comment.text.split('\n').forEach((line) => {
3903
- ctx.println(stmt, `// ${line}`);
3904
- });
3905
- }
3906
- }
3849
+ /**
3850
+ * Compute the value for `this.base^exponent`, resulting in a big integer that is optimized for
3851
+ * further multiplication operations.
3852
+ */
3853
+ toThePowerOf(exponent) {
3854
+ // Compute the results up until the requested exponent, where every value is computed from its
3855
+ // predecessor. This is because `this.base^(exponent - 1)` only has to be multiplied by `base`
3856
+ // to reach `this.base^exponent`.
3857
+ for (let i = this.exponents.length; i <= exponent; i++) {
3858
+ const value = this.exponents[i - 1].multiplyBy(this.base);
3859
+ this.exponents[i] = new BigIntForMultiplication(value);
3907
3860
  }
3861
+ return this.exponents[exponent];
3908
3862
  }
3909
- visitExpressionStmt(stmt, ctx) {
3910
- this.printLeadingComments(stmt, ctx);
3911
- stmt.expr.visitExpression(this, ctx);
3912
- ctx.println(stmt, ';');
3913
- return null;
3863
+ }
3864
+
3865
+ /**
3866
+ * @license
3867
+ * Copyright Google LLC All Rights Reserved.
3868
+ *
3869
+ * Use of this source code is governed by an MIT-style license that can be
3870
+ * found in the LICENSE file at https://angular.io/license
3871
+ */
3872
+ /**
3873
+ * Compute the message id using the XLIFF1 digest.
3874
+ */
3875
+ function computeDigest(message) {
3876
+ return sha1(serializeNodes(message.nodes).join('') + `[${message.meaning}]`);
3877
+ }
3878
+ /**
3879
+ * Return the message id or compute it using the XLIFF2/XMB/$localize digest.
3880
+ */
3881
+ function decimalDigest(message) {
3882
+ return message.id || computeDecimalDigest(message);
3883
+ }
3884
+ /**
3885
+ * Compute the message id using the XLIFF2/XMB/$localize digest.
3886
+ */
3887
+ function computeDecimalDigest(message) {
3888
+ const visitor = new _SerializerIgnoreIcuExpVisitor();
3889
+ const parts = message.nodes.map(a => a.visit(visitor, null));
3890
+ return computeMsgId(parts.join(''), message.meaning);
3891
+ }
3892
+ /**
3893
+ * Serialize the i18n ast to something xml-like in order to generate an UID.
3894
+ *
3895
+ * The visitor is also used in the i18n parser tests
3896
+ *
3897
+ * @internal
3898
+ */
3899
+ class _SerializerVisitor {
3900
+ visitText(text, context) {
3901
+ return text.value;
3914
3902
  }
3915
- visitReturnStmt(stmt, ctx) {
3916
- this.printLeadingComments(stmt, ctx);
3917
- ctx.print(stmt, `return `);
3918
- stmt.value.visitExpression(this, ctx);
3919
- ctx.println(stmt, ';');
3920
- return null;
3903
+ visitContainer(container, context) {
3904
+ return `[${container.children.map(child => child.visit(this)).join(', ')}]`;
3921
3905
  }
3922
- visitIfStmt(stmt, ctx) {
3923
- this.printLeadingComments(stmt, ctx);
3924
- ctx.print(stmt, `if (`);
3925
- stmt.condition.visitExpression(this, ctx);
3926
- ctx.print(stmt, `) {`);
3927
- const hasElseCase = stmt.falseCase != null && stmt.falseCase.length > 0;
3928
- if (stmt.trueCase.length <= 1 && !hasElseCase) {
3929
- ctx.print(stmt, ` `);
3930
- this.visitAllStatements(stmt.trueCase, ctx);
3931
- ctx.removeEmptyLastLine();
3932
- ctx.print(stmt, ` `);
3933
- }
3934
- else {
3935
- ctx.println();
3936
- ctx.incIndent();
3937
- this.visitAllStatements(stmt.trueCase, ctx);
3938
- ctx.decIndent();
3939
- if (hasElseCase) {
3940
- ctx.println(stmt, `} else {`);
3941
- ctx.incIndent();
3942
- this.visitAllStatements(stmt.falseCase, ctx);
3943
- ctx.decIndent();
3944
- }
3945
- }
3946
- ctx.println(stmt, `}`);
3947
- return null;
3906
+ visitIcu(icu, context) {
3907
+ const strCases = Object.keys(icu.cases).map((k) => `${k} {${icu.cases[k].visit(this)}}`);
3908
+ return `{${icu.expression}, ${icu.type}, ${strCases.join(', ')}}`;
3948
3909
  }
3949
- visitThrowStmt(stmt, ctx) {
3950
- this.printLeadingComments(stmt, ctx);
3951
- ctx.print(stmt, `throw `);
3952
- stmt.error.visitExpression(this, ctx);
3953
- ctx.println(stmt, `;`);
3954
- return null;
3910
+ visitTagPlaceholder(ph, context) {
3911
+ return ph.isVoid ?
3912
+ `<ph tag name="${ph.startName}"/>` :
3913
+ `<ph tag name="${ph.startName}">${ph.children.map(child => child.visit(this)).join(', ')}</ph name="${ph.closeName}">`;
3955
3914
  }
3956
- visitWriteVarExpr(expr, ctx) {
3957
- const lineWasEmpty = ctx.lineIsEmpty();
3958
- if (!lineWasEmpty) {
3959
- ctx.print(expr, '(');
3960
- }
3961
- ctx.print(expr, `${expr.name} = `);
3962
- expr.value.visitExpression(this, ctx);
3963
- if (!lineWasEmpty) {
3964
- ctx.print(expr, ')');
3965
- }
3966
- return null;
3915
+ visitPlaceholder(ph, context) {
3916
+ return ph.value ? `<ph name="${ph.name}">${ph.value}</ph>` : `<ph name="${ph.name}"/>`;
3967
3917
  }
3968
- visitWriteKeyExpr(expr, ctx) {
3969
- const lineWasEmpty = ctx.lineIsEmpty();
3970
- if (!lineWasEmpty) {
3971
- ctx.print(expr, '(');
3972
- }
3973
- expr.receiver.visitExpression(this, ctx);
3974
- ctx.print(expr, `[`);
3975
- expr.index.visitExpression(this, ctx);
3976
- ctx.print(expr, `] = `);
3977
- expr.value.visitExpression(this, ctx);
3978
- if (!lineWasEmpty) {
3979
- ctx.print(expr, ')');
3980
- }
3981
- return null;
3918
+ visitIcuPlaceholder(ph, context) {
3919
+ return `<ph icu name="${ph.name}">${ph.value.visit(this)}</ph>`;
3982
3920
  }
3983
- visitWritePropExpr(expr, ctx) {
3984
- const lineWasEmpty = ctx.lineIsEmpty();
3985
- if (!lineWasEmpty) {
3986
- ctx.print(expr, '(');
3987
- }
3988
- expr.receiver.visitExpression(this, ctx);
3989
- ctx.print(expr, `.${expr.name} = `);
3990
- expr.value.visitExpression(this, ctx);
3991
- if (!lineWasEmpty) {
3992
- ctx.print(expr, ')');
3993
- }
3994
- return null;
3921
+ }
3922
+ const serializerVisitor = new _SerializerVisitor();
3923
+ function serializeNodes(nodes) {
3924
+ return nodes.map(a => a.visit(serializerVisitor, null));
3925
+ }
3926
+ /**
3927
+ * Serialize the i18n ast to something xml-like in order to generate an UID.
3928
+ *
3929
+ * Ignore the ICU expressions so that message IDs stays identical if only the expression changes.
3930
+ *
3931
+ * @internal
3932
+ */
3933
+ class _SerializerIgnoreIcuExpVisitor extends _SerializerVisitor {
3934
+ visitIcu(icu, context) {
3935
+ let strCases = Object.keys(icu.cases).map((k) => `${k} {${icu.cases[k].visit(this)}}`);
3936
+ // Do not take the expression into account
3937
+ return `{${icu.type}, ${strCases.join(', ')}}`;
3995
3938
  }
3996
- visitInvokeMethodExpr(expr, ctx) {
3997
- expr.receiver.visitExpression(this, ctx);
3998
- let name = expr.name;
3999
- if (expr.builtin != null) {
4000
- name = this.getBuiltinMethodName(expr.builtin);
4001
- if (name == null) {
4002
- // some builtins just mean to skip the call.
4003
- return null;
3939
+ }
3940
+ /**
3941
+ * Compute the SHA1 of the given string
3942
+ *
3943
+ * see https://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
3944
+ *
3945
+ * WARNING: this function has not been designed not tested with security in mind.
3946
+ * DO NOT USE IT IN A SECURITY SENSITIVE CONTEXT.
3947
+ */
3948
+ function sha1(str) {
3949
+ const utf8 = utf8Encode(str);
3950
+ const words32 = bytesToWords32(utf8, Endian.Big);
3951
+ const len = utf8.length * 8;
3952
+ const w = newArray(80);
3953
+ let a = 0x67452301, b = 0xefcdab89, c = 0x98badcfe, d = 0x10325476, e = 0xc3d2e1f0;
3954
+ words32[len >> 5] |= 0x80 << (24 - len % 32);
3955
+ words32[((len + 64 >> 9) << 4) + 15] = len;
3956
+ for (let i = 0; i < words32.length; i += 16) {
3957
+ const h0 = a, h1 = b, h2 = c, h3 = d, h4 = e;
3958
+ for (let j = 0; j < 80; j++) {
3959
+ if (j < 16) {
3960
+ w[j] = words32[i + j];
3961
+ }
3962
+ else {
3963
+ w[j] = rol32(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1);
4004
3964
  }
3965
+ const fkVal = fk(j, b, c, d);
3966
+ const f = fkVal[0];
3967
+ const k = fkVal[1];
3968
+ const temp = [rol32(a, 5), f, e, k, w[j]].reduce(add32);
3969
+ e = d;
3970
+ d = c;
3971
+ c = rol32(b, 30);
3972
+ b = a;
3973
+ a = temp;
4005
3974
  }
4006
- ctx.print(expr, `.${name}(`);
4007
- this.visitAllExpressions(expr.args, ctx, `,`);
4008
- ctx.print(expr, `)`);
4009
- return null;
3975
+ a = add32(a, h0);
3976
+ b = add32(b, h1);
3977
+ c = add32(c, h2);
3978
+ d = add32(d, h3);
3979
+ e = add32(e, h4);
4010
3980
  }
4011
- visitInvokeFunctionExpr(expr, ctx) {
4012
- expr.fn.visitExpression(this, ctx);
4013
- ctx.print(expr, `(`);
4014
- this.visitAllExpressions(expr.args, ctx, ',');
4015
- ctx.print(expr, `)`);
4016
- return null;
3981
+ return bytesToHexString(words32ToByteString([a, b, c, d, e]));
3982
+ }
3983
+ function fk(index, b, c, d) {
3984
+ if (index < 20) {
3985
+ return [(b & c) | (~b & d), 0x5a827999];
4017
3986
  }
4018
- visitTaggedTemplateExpr(expr, ctx) {
4019
- expr.tag.visitExpression(this, ctx);
4020
- ctx.print(expr, '`' + expr.template.elements[0].rawText);
4021
- for (let i = 1; i < expr.template.elements.length; i++) {
4022
- ctx.print(expr, '${');
4023
- expr.template.expressions[i - 1].visitExpression(this, ctx);
4024
- ctx.print(expr, `}${expr.template.elements[i].rawText}`);
4025
- }
4026
- ctx.print(expr, '`');
4027
- return null;
3987
+ if (index < 40) {
3988
+ return [b ^ c ^ d, 0x6ed9eba1];
4028
3989
  }
4029
- visitWrappedNodeExpr(ast, ctx) {
4030
- throw new Error('Abstract emitter cannot visit WrappedNodeExpr.');
3990
+ if (index < 60) {
3991
+ return [(b & c) | (b & d) | (c & d), 0x8f1bbcdc];
4031
3992
  }
4032
- visitTypeofExpr(expr, ctx) {
4033
- ctx.print(expr, 'typeof ');
4034
- expr.expr.visitExpression(this, ctx);
3993
+ return [b ^ c ^ d, 0xca62c1d6];
3994
+ }
3995
+ /**
3996
+ * Compute the fingerprint of the given string
3997
+ *
3998
+ * The output is 64 bit number encoded as a decimal string
3999
+ *
4000
+ * based on:
4001
+ * https://github.com/google/closure-compiler/blob/master/src/com/google/javascript/jscomp/GoogleJsMessageIdGenerator.java
4002
+ */
4003
+ function fingerprint(str) {
4004
+ const utf8 = utf8Encode(str);
4005
+ let hi = hash32(utf8, 0);
4006
+ let lo = hash32(utf8, 102072);
4007
+ if (hi == 0 && (lo == 0 || lo == 1)) {
4008
+ hi = hi ^ 0x130f9bef;
4009
+ lo = lo ^ -0x6b5f56d8;
4035
4010
  }
4036
- visitReadVarExpr(ast, ctx) {
4037
- let varName = ast.name;
4038
- if (ast.builtin != null) {
4039
- switch (ast.builtin) {
4040
- case BuiltinVar.Super:
4041
- varName = 'super';
4042
- break;
4043
- case BuiltinVar.This:
4044
- varName = 'this';
4045
- break;
4046
- case BuiltinVar.CatchError:
4047
- varName = CATCH_ERROR_VAR$1.name;
4048
- break;
4049
- case BuiltinVar.CatchStack:
4050
- varName = CATCH_STACK_VAR$1.name;
4051
- break;
4052
- default:
4053
- throw new Error(`Unknown builtin variable ${ast.builtin}`);
4054
- }
4055
- }
4056
- ctx.print(ast, varName);
4057
- return null;
4011
+ return [hi, lo];
4012
+ }
4013
+ function computeMsgId(msg, meaning = '') {
4014
+ let msgFingerprint = fingerprint(msg);
4015
+ if (meaning) {
4016
+ const meaningFingerprint = fingerprint(meaning);
4017
+ msgFingerprint = add64(rol64(msgFingerprint, 1), meaningFingerprint);
4058
4018
  }
4059
- visitInstantiateExpr(ast, ctx) {
4060
- ctx.print(ast, `new `);
4061
- ast.classExpr.visitExpression(this, ctx);
4062
- ctx.print(ast, `(`);
4063
- this.visitAllExpressions(ast.args, ctx, ',');
4064
- ctx.print(ast, `)`);
4065
- return null;
4019
+ const hi = msgFingerprint[0];
4020
+ const lo = msgFingerprint[1];
4021
+ return wordsToDecimalString(hi & 0x7fffffff, lo);
4022
+ }
4023
+ function hash32(bytes, c) {
4024
+ let a = 0x9e3779b9, b = 0x9e3779b9;
4025
+ let i;
4026
+ const len = bytes.length;
4027
+ for (i = 0; i + 12 <= len; i += 12) {
4028
+ a = add32(a, wordAt(bytes, i, Endian.Little));
4029
+ b = add32(b, wordAt(bytes, i + 4, Endian.Little));
4030
+ c = add32(c, wordAt(bytes, i + 8, Endian.Little));
4031
+ const res = mix(a, b, c);
4032
+ a = res[0], b = res[1], c = res[2];
4066
4033
  }
4067
- visitLiteralExpr(ast, ctx) {
4068
- const value = ast.value;
4069
- if (typeof value === 'string') {
4070
- ctx.print(ast, escapeIdentifier(value, this._escapeDollarInStrings));
4071
- }
4072
- else {
4073
- ctx.print(ast, `${value}`);
4074
- }
4075
- return null;
4034
+ a = add32(a, wordAt(bytes, i, Endian.Little));
4035
+ b = add32(b, wordAt(bytes, i + 4, Endian.Little));
4036
+ // the first byte of c is reserved for the length
4037
+ c = add32(c, len);
4038
+ c = add32(c, wordAt(bytes, i + 8, Endian.Little) << 8);
4039
+ return mix(a, b, c)[2];
4040
+ }
4041
+ // clang-format off
4042
+ function mix(a, b, c) {
4043
+ a = sub32(a, b);
4044
+ a = sub32(a, c);
4045
+ a ^= c >>> 13;
4046
+ b = sub32(b, c);
4047
+ b = sub32(b, a);
4048
+ b ^= a << 8;
4049
+ c = sub32(c, a);
4050
+ c = sub32(c, b);
4051
+ c ^= b >>> 13;
4052
+ a = sub32(a, b);
4053
+ a = sub32(a, c);
4054
+ a ^= c >>> 12;
4055
+ b = sub32(b, c);
4056
+ b = sub32(b, a);
4057
+ b ^= a << 16;
4058
+ c = sub32(c, a);
4059
+ c = sub32(c, b);
4060
+ c ^= b >>> 5;
4061
+ a = sub32(a, b);
4062
+ a = sub32(a, c);
4063
+ a ^= c >>> 3;
4064
+ b = sub32(b, c);
4065
+ b = sub32(b, a);
4066
+ b ^= a << 10;
4067
+ c = sub32(c, a);
4068
+ c = sub32(c, b);
4069
+ c ^= b >>> 15;
4070
+ return [a, b, c];
4071
+ }
4072
+ // clang-format on
4073
+ // Utils
4074
+ var Endian;
4075
+ (function (Endian) {
4076
+ Endian[Endian["Little"] = 0] = "Little";
4077
+ Endian[Endian["Big"] = 1] = "Big";
4078
+ })(Endian || (Endian = {}));
4079
+ function add32(a, b) {
4080
+ return add32to64(a, b)[1];
4081
+ }
4082
+ function add32to64(a, b) {
4083
+ const low = (a & 0xffff) + (b & 0xffff);
4084
+ const high = (a >>> 16) + (b >>> 16) + (low >>> 16);
4085
+ return [high >>> 16, (high << 16) | (low & 0xffff)];
4086
+ }
4087
+ function add64(a, b) {
4088
+ const ah = a[0], al = a[1];
4089
+ const bh = b[0], bl = b[1];
4090
+ const result = add32to64(al, bl);
4091
+ const carry = result[0];
4092
+ const l = result[1];
4093
+ const h = add32(add32(ah, bh), carry);
4094
+ return [h, l];
4095
+ }
4096
+ function sub32(a, b) {
4097
+ const low = (a & 0xffff) - (b & 0xffff);
4098
+ const high = (a >> 16) - (b >> 16) + (low >> 16);
4099
+ return (high << 16) | (low & 0xffff);
4100
+ }
4101
+ // Rotate a 32b number left `count` position
4102
+ function rol32(a, count) {
4103
+ return (a << count) | (a >>> (32 - count));
4104
+ }
4105
+ // Rotate a 64b number left `count` position
4106
+ function rol64(num, count) {
4107
+ const hi = num[0], lo = num[1];
4108
+ const h = (hi << count) | (lo >>> (32 - count));
4109
+ const l = (lo << count) | (hi >>> (32 - count));
4110
+ return [h, l];
4111
+ }
4112
+ function bytesToWords32(bytes, endian) {
4113
+ const size = (bytes.length + 3) >>> 2;
4114
+ const words32 = [];
4115
+ for (let i = 0; i < size; i++) {
4116
+ words32[i] = wordAt(bytes, i * 4, endian);
4076
4117
  }
4077
- visitLocalizedString(ast, ctx) {
4078
- const head = ast.serializeI18nHead();
4079
- ctx.print(ast, '$localize `' + head.raw);
4080
- for (let i = 1; i < ast.messageParts.length; i++) {
4081
- ctx.print(ast, '${');
4082
- ast.expressions[i - 1].visitExpression(this, ctx);
4083
- ctx.print(ast, `}${ast.serializeI18nTemplatePart(i).raw}`);
4118
+ return words32;
4119
+ }
4120
+ function byteAt(bytes, index) {
4121
+ return index >= bytes.length ? 0 : bytes[index];
4122
+ }
4123
+ function wordAt(bytes, index, endian) {
4124
+ let word = 0;
4125
+ if (endian === Endian.Big) {
4126
+ for (let i = 0; i < 4; i++) {
4127
+ word += byteAt(bytes, index + i) << (24 - 8 * i);
4084
4128
  }
4085
- ctx.print(ast, '`');
4086
- return null;
4087
4129
  }
4088
- visitConditionalExpr(ast, ctx) {
4089
- ctx.print(ast, `(`);
4090
- ast.condition.visitExpression(this, ctx);
4091
- ctx.print(ast, '? ');
4092
- ast.trueCase.visitExpression(this, ctx);
4093
- ctx.print(ast, ': ');
4094
- ast.falseCase.visitExpression(this, ctx);
4095
- ctx.print(ast, `)`);
4096
- return null;
4097
- }
4098
- visitNotExpr(ast, ctx) {
4099
- ctx.print(ast, '!');
4100
- ast.condition.visitExpression(this, ctx);
4101
- return null;
4102
- }
4103
- visitAssertNotNullExpr(ast, ctx) {
4104
- ast.condition.visitExpression(this, ctx);
4105
- return null;
4106
- }
4107
- visitUnaryOperatorExpr(ast, ctx) {
4108
- let opStr;
4109
- switch (ast.operator) {
4110
- case UnaryOperator.Plus:
4111
- opStr = '+';
4112
- break;
4113
- case UnaryOperator.Minus:
4114
- opStr = '-';
4115
- break;
4116
- default:
4117
- throw new Error(`Unknown operator ${ast.operator}`);
4130
+ else {
4131
+ for (let i = 0; i < 4; i++) {
4132
+ word += byteAt(bytes, index + i) << 8 * i;
4118
4133
  }
4119
- if (ast.parens)
4120
- ctx.print(ast, `(`);
4121
- ctx.print(ast, opStr);
4122
- ast.expr.visitExpression(this, ctx);
4123
- if (ast.parens)
4124
- ctx.print(ast, `)`);
4125
- return null;
4126
4134
  }
4127
- visitBinaryOperatorExpr(ast, ctx) {
4128
- let opStr;
4129
- switch (ast.operator) {
4130
- case BinaryOperator.Equals:
4131
- opStr = '==';
4132
- break;
4133
- case BinaryOperator.Identical:
4134
- opStr = '===';
4135
- break;
4136
- case BinaryOperator.NotEquals:
4137
- opStr = '!=';
4138
- break;
4139
- case BinaryOperator.NotIdentical:
4140
- opStr = '!==';
4141
- break;
4142
- case BinaryOperator.And:
4143
- opStr = '&&';
4144
- break;
4145
- case BinaryOperator.BitwiseAnd:
4146
- opStr = '&';
4147
- break;
4148
- case BinaryOperator.Or:
4149
- opStr = '||';
4150
- break;
4151
- case BinaryOperator.Plus:
4152
- opStr = '+';
4153
- break;
4154
- case BinaryOperator.Minus:
4155
- opStr = '-';
4156
- break;
4157
- case BinaryOperator.Divide:
4158
- opStr = '/';
4159
- break;
4160
- case BinaryOperator.Multiply:
4161
- opStr = '*';
4162
- break;
4163
- case BinaryOperator.Modulo:
4164
- opStr = '%';
4165
- break;
4166
- case BinaryOperator.Lower:
4167
- opStr = '<';
4168
- break;
4169
- case BinaryOperator.LowerEquals:
4170
- opStr = '<=';
4171
- break;
4172
- case BinaryOperator.Bigger:
4173
- opStr = '>';
4174
- break;
4175
- case BinaryOperator.BiggerEquals:
4176
- opStr = '>=';
4177
- break;
4178
- case BinaryOperator.NullishCoalesce:
4179
- opStr = '??';
4180
- break;
4181
- default:
4182
- throw new Error(`Unknown operator ${ast.operator}`);
4183
- }
4184
- if (ast.parens)
4185
- ctx.print(ast, `(`);
4186
- ast.lhs.visitExpression(this, ctx);
4187
- ctx.print(ast, ` ${opStr} `);
4188
- ast.rhs.visitExpression(this, ctx);
4189
- if (ast.parens)
4190
- ctx.print(ast, `)`);
4191
- return null;
4135
+ return word;
4136
+ }
4137
+ function words32ToByteString(words32) {
4138
+ return words32.reduce((bytes, word) => bytes.concat(word32ToByteString(word)), []);
4139
+ }
4140
+ function word32ToByteString(word) {
4141
+ let bytes = [];
4142
+ for (let i = 0; i < 4; i++) {
4143
+ bytes.push((word >>> 8 * (3 - i)) & 0xff);
4192
4144
  }
4193
- visitReadPropExpr(ast, ctx) {
4194
- ast.receiver.visitExpression(this, ctx);
4195
- ctx.print(ast, `.`);
4196
- ctx.print(ast, ast.name);
4197
- return null;
4145
+ return bytes;
4146
+ }
4147
+ function bytesToHexString(bytes) {
4148
+ let hex = '';
4149
+ for (let i = 0; i < bytes.length; i++) {
4150
+ const b = byteAt(bytes, i);
4151
+ hex += (b >>> 4).toString(16) + (b & 0x0f).toString(16);
4198
4152
  }
4199
- visitReadKeyExpr(ast, ctx) {
4200
- ast.receiver.visitExpression(this, ctx);
4201
- ctx.print(ast, `[`);
4202
- ast.index.visitExpression(this, ctx);
4203
- ctx.print(ast, `]`);
4204
- return null;
4153
+ return hex.toLowerCase();
4154
+ }
4155
+ /**
4156
+ * Create a shared exponentiation pool for base-256 computations. This shared pool provides memoized
4157
+ * power-of-256 results with memoized power-of-two computations for efficient multiplication.
4158
+ *
4159
+ * For our purposes, this can be safely stored as a global without memory concerns. The reason is
4160
+ * that we encode two words, so only need the 0th (for the low word) and 4th (for the high word)
4161
+ * exponent.
4162
+ */
4163
+ const base256 = new BigIntExponentiation(256);
4164
+ /**
4165
+ * Represents two 32-bit words as a single decimal number. This requires a big integer storage
4166
+ * model as JS numbers are not accurate enough to represent the 64-bit number.
4167
+ *
4168
+ * Based on https://www.danvk.org/hex2dec.html
4169
+ */
4170
+ function wordsToDecimalString(hi, lo) {
4171
+ // Encode the four bytes in lo in the lower digits of the decimal number.
4172
+ // Note: the multiplication results in lo itself but represented by a big integer using its
4173
+ // decimal digits.
4174
+ const decimal = base256.toThePowerOf(0).multiplyBy(lo);
4175
+ // Encode the four bytes in hi above the four lo bytes. lo is a maximum of (2^8)^4, which is why
4176
+ // this multiplication factor is applied.
4177
+ base256.toThePowerOf(4).multiplyByAndAddTo(hi, decimal);
4178
+ return decimal.toString();
4179
+ }
4180
+
4181
+ /**
4182
+ * @license
4183
+ * Copyright Google LLC All Rights Reserved.
4184
+ *
4185
+ * Use of this source code is governed by an MIT-style license that can be
4186
+ * found in the LICENSE file at https://angular.io/license
4187
+ */
4188
+ // XMB/XTB placeholders can only contain A-Z, 0-9 and _
4189
+ function toPublicName(internalName) {
4190
+ return internalName.toUpperCase().replace(/[^A-Z0-9_]/g, '_');
4191
+ }
4192
+
4193
+ /**
4194
+ * @license
4195
+ * Copyright Google LLC All Rights Reserved.
4196
+ *
4197
+ * Use of this source code is governed by an MIT-style license that can be
4198
+ * found in the LICENSE file at https://angular.io/license
4199
+ */
4200
+ /* Closure variables holding messages must be named `MSG_[A-Z0-9]+` */
4201
+ const CLOSURE_TRANSLATION_VAR_PREFIX = 'MSG_';
4202
+ /**
4203
+ * Prefix for non-`goog.getMsg` i18n-related vars.
4204
+ * Note: the prefix uses lowercase characters intentionally due to a Closure behavior that
4205
+ * considers variables like `I18N_0` as constants and throws an error when their value changes.
4206
+ */
4207
+ const TRANSLATION_VAR_PREFIX = 'i18n_';
4208
+ /** Name of the i18n attributes **/
4209
+ const I18N_ATTR = 'i18n';
4210
+ const I18N_ATTR_PREFIX = 'i18n-';
4211
+ /** Prefix of var expressions used in ICUs */
4212
+ const I18N_ICU_VAR_PREFIX = 'VAR_';
4213
+ /** Prefix of ICU expressions for post processing */
4214
+ const I18N_ICU_MAPPING_PREFIX = 'I18N_EXP_';
4215
+ /** Placeholder wrapper for i18n expressions **/
4216
+ const I18N_PLACEHOLDER_SYMBOL = '�';
4217
+ function isI18nAttribute(name) {
4218
+ return name === I18N_ATTR || name.startsWith(I18N_ATTR_PREFIX);
4219
+ }
4220
+ function isI18nRootNode(meta) {
4221
+ return meta instanceof Message;
4222
+ }
4223
+ function isSingleI18nIcu(meta) {
4224
+ return isI18nRootNode(meta) && meta.nodes.length === 1 && meta.nodes[0] instanceof Icu$1;
4225
+ }
4226
+ function hasI18nMeta(node) {
4227
+ return !!node.i18n;
4228
+ }
4229
+ function hasI18nAttrs(element) {
4230
+ return element.attrs.some((attr) => isI18nAttribute(attr.name));
4231
+ }
4232
+ function icuFromI18nMessage(message) {
4233
+ return message.nodes[0];
4234
+ }
4235
+ function wrapI18nPlaceholder(content, contextId = 0) {
4236
+ const blockId = contextId > 0 ? `:${contextId}` : '';
4237
+ return `${I18N_PLACEHOLDER_SYMBOL}${content}${blockId}${I18N_PLACEHOLDER_SYMBOL}`;
4238
+ }
4239
+ function assembleI18nBoundString(strings, bindingStartIndex = 0, contextId = 0) {
4240
+ if (!strings.length)
4241
+ return '';
4242
+ let acc = '';
4243
+ const lastIdx = strings.length - 1;
4244
+ for (let i = 0; i < lastIdx; i++) {
4245
+ acc += `${strings[i]}${wrapI18nPlaceholder(bindingStartIndex + i, contextId)}`;
4205
4246
  }
4206
- visitLiteralArrayExpr(ast, ctx) {
4207
- ctx.print(ast, `[`);
4208
- this.visitAllExpressions(ast.entries, ctx, ',');
4209
- ctx.print(ast, `]`);
4210
- return null;
4247
+ acc += strings[lastIdx];
4248
+ return acc;
4249
+ }
4250
+ function getSeqNumberGenerator(startsAt = 0) {
4251
+ let current = startsAt;
4252
+ return () => current++;
4253
+ }
4254
+ function placeholdersToParams(placeholders) {
4255
+ const params = {};
4256
+ placeholders.forEach((values, key) => {
4257
+ params[key] = literal(values.length > 1 ? `[${values.join('|')}]` : values[0]);
4258
+ });
4259
+ return params;
4260
+ }
4261
+ function updatePlaceholderMap(map, name, ...values) {
4262
+ const current = map.get(name) || [];
4263
+ current.push(...values);
4264
+ map.set(name, current);
4265
+ }
4266
+ function assembleBoundTextPlaceholders(meta, bindingStartIndex = 0, contextId = 0) {
4267
+ const startIdx = bindingStartIndex;
4268
+ const placeholders = new Map();
4269
+ const node = meta instanceof Message ? meta.nodes.find(node => node instanceof Container) : meta;
4270
+ if (node) {
4271
+ node
4272
+ .children
4273
+ .filter((child) => child instanceof Placeholder)
4274
+ .forEach((child, idx) => {
4275
+ const content = wrapI18nPlaceholder(startIdx + idx, contextId);
4276
+ updatePlaceholderMap(placeholders, child.name, content);
4277
+ });
4211
4278
  }
4212
- visitLiteralMapExpr(ast, ctx) {
4213
- ctx.print(ast, `{`);
4214
- this.visitAllObjects(entry => {
4215
- ctx.print(ast, `${escapeIdentifier(entry.key, this._escapeDollarInStrings, entry.quoted)}:`);
4216
- entry.value.visitExpression(this, ctx);
4217
- }, ast.entries, ctx, ',');
4218
- ctx.print(ast, `}`);
4219
- return null;
4279
+ return placeholders;
4280
+ }
4281
+ /**
4282
+ * Format the placeholder names in a map of placeholders to expressions.
4283
+ *
4284
+ * The placeholder names are converted from "internal" format (e.g. `START_TAG_DIV_1`) to "external"
4285
+ * format (e.g. `startTagDiv_1`).
4286
+ *
4287
+ * @param params A map of placeholder names to expressions.
4288
+ * @param useCamelCase whether to camelCase the placeholder name when formatting.
4289
+ * @returns A new map of formatted placeholder names to expressions.
4290
+ */
4291
+ function i18nFormatPlaceholderNames(params = {}, useCamelCase) {
4292
+ const _params = {};
4293
+ if (params && Object.keys(params).length) {
4294
+ Object.keys(params).forEach(key => _params[formatI18nPlaceholderName(key, useCamelCase)] = params[key]);
4220
4295
  }
4221
- visitCommaExpr(ast, ctx) {
4222
- ctx.print(ast, '(');
4223
- this.visitAllExpressions(ast.parts, ctx, ',');
4224
- ctx.print(ast, ')');
4225
- return null;
4296
+ return _params;
4297
+ }
4298
+ /**
4299
+ * Converts internal placeholder names to public-facing format
4300
+ * (for example to use in goog.getMsg call).
4301
+ * Example: `START_TAG_DIV_1` is converted to `startTagDiv_1`.
4302
+ *
4303
+ * @param name The placeholder name that should be formatted
4304
+ * @returns Formatted placeholder name
4305
+ */
4306
+ function formatI18nPlaceholderName(name, useCamelCase = true) {
4307
+ const publicName = toPublicName(name);
4308
+ if (!useCamelCase) {
4309
+ return publicName;
4226
4310
  }
4227
- visitAllExpressions(expressions, ctx, separator) {
4228
- this.visitAllObjects(expr => expr.visitExpression(this, ctx), expressions, ctx, separator);
4311
+ const chunks = publicName.split('_');
4312
+ if (chunks.length === 1) {
4313
+ // if no "_" found - just lowercase the value
4314
+ return name.toLowerCase();
4229
4315
  }
4230
- visitAllObjects(handler, expressions, ctx, separator) {
4231
- let incrementedIndent = false;
4232
- for (let i = 0; i < expressions.length; i++) {
4233
- if (i > 0) {
4234
- if (ctx.lineLength() > 80) {
4235
- ctx.print(null, separator, true);
4236
- if (!incrementedIndent) {
4237
- // continuation are marked with double indent.
4238
- ctx.incIndent();
4239
- ctx.incIndent();
4240
- incrementedIndent = true;
4241
- }
4242
- }
4243
- else {
4244
- ctx.print(null, separator, false);
4245
- }
4246
- }
4247
- handler(expressions[i]);
4248
- }
4249
- if (incrementedIndent) {
4250
- // continuation are marked with double indent.
4251
- ctx.decIndent();
4252
- ctx.decIndent();
4253
- }
4316
+ let postfix;
4317
+ // eject last element if it's a number
4318
+ if (/^\d+$/.test(chunks[chunks.length - 1])) {
4319
+ postfix = chunks.pop();
4254
4320
  }
4255
- visitAllStatements(statements, ctx) {
4256
- statements.forEach((stmt) => stmt.visitStatement(this, ctx));
4321
+ let raw = chunks.shift().toLowerCase();
4322
+ if (chunks.length) {
4323
+ raw += chunks.map(c => c.charAt(0).toUpperCase() + c.slice(1).toLowerCase()).join('');
4257
4324
  }
4325
+ return postfix ? `${raw}_${postfix}` : raw;
4258
4326
  }
4259
- function escapeIdentifier(input, escapeDollar, alwaysQuote = true) {
4260
- if (input == null) {
4261
- return null;
4262
- }
4263
- const body = input.replace(_SINGLE_QUOTE_ESCAPE_STRING_RE, (...match) => {
4264
- if (match[0] == '$') {
4265
- return escapeDollar ? '\\$' : '$';
4266
- }
4267
- else if (match[0] == '\n') {
4268
- return '\\n';
4269
- }
4270
- else if (match[0] == '\r') {
4271
- return '\\r';
4272
- }
4273
- else {
4274
- return `\\${match[0]}`;
4275
- }
4276
- });
4277
- const requiresQuotes = alwaysQuote || !_LEGAL_IDENTIFIER_RE.test(body);
4278
- return requiresQuotes ? `'${body}'` : body;
4327
+ /**
4328
+ * Generates a prefix for translation const name.
4329
+ *
4330
+ * @param extra Additional local prefix that should be injected into translation var name
4331
+ * @returns Complete translation const prefix
4332
+ */
4333
+ function getTranslationConstPrefix(extra) {
4334
+ return `${CLOSURE_TRANSLATION_VAR_PREFIX}${extra}`.toUpperCase();
4279
4335
  }
4280
- function _createIndent(count) {
4281
- let res = '';
4282
- for (let i = 0; i < count; i++) {
4283
- res += _INDENT_WITH;
4284
- }
4285
- return res;
4336
+ /**
4337
+ * Generate AST to declare a variable. E.g. `var I18N_1;`.
4338
+ * @param variable the name of the variable to declare.
4339
+ */
4340
+ function declareI18nVariable(variable) {
4341
+ return new DeclareVarStmt(variable.name, undefined, INFERRED_TYPE, undefined, variable.sourceSpan);
4286
4342
  }
4287
4343
 
4288
4344
  /**
@@ -4292,239 +4348,205 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
4292
4348
  * Use of this source code is governed by an MIT-style license that can be
4293
4349
  * found in the LICENSE file at https://angular.io/license
4294
4350
  */
4295
- function typeWithParameters(type, numParams) {
4296
- if (numParams === 0) {
4297
- return expressionType(type);
4298
- }
4299
- const params = [];
4300
- for (let i = 0; i < numParams; i++) {
4301
- params.push(DYNAMIC_TYPE);
4302
- }
4303
- return expressionType(type, undefined, params);
4304
- }
4305
- const ANIMATE_SYMBOL_PREFIX = '@';
4306
- function prepareSyntheticPropertyName(name) {
4307
- return `${ANIMATE_SYMBOL_PREFIX}${name}`;
4308
- }
4309
- function prepareSyntheticListenerName(name, phase) {
4310
- return `${ANIMATE_SYMBOL_PREFIX}${name}.${phase}`;
4311
- }
4312
- function getSafePropertyAccessString(accessor, name) {
4313
- const escapedName = escapeIdentifier(name, false, false);
4314
- return escapedName !== name ? `${accessor}[${escapedName}]` : `${accessor}.${name}`;
4351
+ /**
4352
+ * Checks whether an object key contains potentially unsafe chars, thus the key should be wrapped in
4353
+ * quotes. Note: we do not wrap all keys into quotes, as it may have impact on minification and may
4354
+ * bot work in some cases when object keys are mangled by minifier.
4355
+ *
4356
+ * TODO(FW-1136): this is a temporary solution, we need to come up with a better way of working with
4357
+ * inputs that contain potentially unsafe chars.
4358
+ */
4359
+ const UNSAFE_OBJECT_KEY_NAME_REGEXP = /[-.]/;
4360
+ /** Name of the temporary to use during data binding */
4361
+ const TEMPORARY_NAME = '_t';
4362
+ /** Name of the context parameter passed into a template function */
4363
+ const CONTEXT_NAME = 'ctx';
4364
+ /** Name of the RenderFlag passed into a template function */
4365
+ const RENDER_FLAGS = 'rf';
4366
+ /** The prefix reference variables */
4367
+ const REFERENCE_PREFIX = '_r';
4368
+ /** The name of the implicit context reference */
4369
+ const IMPLICIT_REFERENCE = '$implicit';
4370
+ /** Non bindable attribute name **/
4371
+ const NON_BINDABLE_ATTR = 'ngNonBindable';
4372
+ /** Name for the variable keeping track of the context returned by `ɵɵrestoreView`. */
4373
+ const RESTORED_VIEW_CONTEXT_NAME = 'restoredCtx';
4374
+ /**
4375
+ * Creates an allocator for a temporary variable.
4376
+ *
4377
+ * A variable declaration is added to the statements the first time the allocator is invoked.
4378
+ */
4379
+ function temporaryAllocator(statements, name) {
4380
+ let temp = null;
4381
+ return () => {
4382
+ if (!temp) {
4383
+ statements.push(new DeclareVarStmt(TEMPORARY_NAME, undefined, DYNAMIC_TYPE));
4384
+ temp = variable(name);
4385
+ }
4386
+ return temp;
4387
+ };
4315
4388
  }
4316
- function prepareSyntheticListenerFunctionName(name, phase) {
4317
- return `animation_${name}_${phase}`;
4389
+ function unsupported(feature) {
4390
+ if (this) {
4391
+ throw new Error(`Builder ${this.constructor.name} doesn't support ${feature} yet`);
4392
+ }
4393
+ throw new Error(`Feature ${feature} is not supported yet`);
4318
4394
  }
4319
- function jitOnlyGuardedExpression(expr) {
4320
- return guardedExpression('ngJitMode', expr);
4395
+ function invalid$1(arg) {
4396
+ throw new Error(`Invalid state: Visitor ${this.constructor.name} doesn't handle ${arg.constructor.name}`);
4321
4397
  }
4322
- function guardedExpression(guard, expr) {
4323
- const guardExpr = new ExternalExpr({ name: guard, moduleName: null });
4324
- const guardNotDefined = new BinaryOperatorExpr(BinaryOperator.Identical, new TypeofExpr(guardExpr), literal('undefined'));
4325
- const guardUndefinedOrTrue = new BinaryOperatorExpr(BinaryOperator.Or, guardNotDefined, guardExpr, /* type */ undefined,
4326
- /* sourceSpan */ undefined, true);
4327
- return new BinaryOperatorExpr(BinaryOperator.And, guardUndefinedOrTrue, expr);
4398
+ function asLiteral(value) {
4399
+ if (Array.isArray(value)) {
4400
+ return literalArr(value.map(asLiteral));
4401
+ }
4402
+ return literal(value, INFERRED_TYPE);
4328
4403
  }
4329
- function wrapReference(value) {
4330
- const wrapped = new WrappedNodeExpr(value);
4331
- return { value: wrapped, type: wrapped };
4404
+ function conditionallyCreateMapObjectLiteral(keys, keepDeclared) {
4405
+ if (Object.getOwnPropertyNames(keys).length > 0) {
4406
+ return mapToExpression(keys, keepDeclared);
4407
+ }
4408
+ return null;
4332
4409
  }
4333
- function refsToArray(refs, shouldForwardDeclare) {
4334
- const values = literalArr(refs.map(ref => ref.value));
4335
- return shouldForwardDeclare ? fn([], [new ReturnStatement(values)]) : values;
4410
+ function mapToExpression(map, keepDeclared) {
4411
+ return literalMap(Object.getOwnPropertyNames(map).map(key => {
4412
+ // canonical syntax: `dirProp: publicProp`
4413
+ // if there is no `:`, use dirProp = elProp
4414
+ const value = map[key];
4415
+ let declaredName;
4416
+ let publicName;
4417
+ let minifiedName;
4418
+ let needsDeclaredName;
4419
+ if (Array.isArray(value)) {
4420
+ [publicName, declaredName] = value;
4421
+ minifiedName = key;
4422
+ needsDeclaredName = publicName !== declaredName;
4423
+ }
4424
+ else {
4425
+ [declaredName, publicName] = splitAtColon(key, [key, value]);
4426
+ minifiedName = declaredName;
4427
+ // Only include the declared name if extracted from the key, i.e. the key contains a colon.
4428
+ // Otherwise the declared name should be omitted even if it is different from the public name,
4429
+ // as it may have already been minified.
4430
+ needsDeclaredName = publicName !== declaredName && key.includes(':');
4431
+ }
4432
+ return {
4433
+ key: minifiedName,
4434
+ // put quotes around keys that contain potentially unsafe characters
4435
+ quoted: UNSAFE_OBJECT_KEY_NAME_REGEXP.test(minifiedName),
4436
+ value: (keepDeclared && needsDeclaredName) ?
4437
+ literalArr([asLiteral(publicName), asLiteral(declaredName)]) :
4438
+ asLiteral(publicName)
4439
+ };
4440
+ }));
4336
4441
  }
4337
-
4338
- var R3FactoryDelegateType;
4339
- (function (R3FactoryDelegateType) {
4340
- R3FactoryDelegateType[R3FactoryDelegateType["Class"] = 0] = "Class";
4341
- R3FactoryDelegateType[R3FactoryDelegateType["Function"] = 1] = "Function";
4342
- })(R3FactoryDelegateType || (R3FactoryDelegateType = {}));
4343
- var FactoryTarget;
4344
- (function (FactoryTarget) {
4345
- FactoryTarget[FactoryTarget["Directive"] = 0] = "Directive";
4346
- FactoryTarget[FactoryTarget["Component"] = 1] = "Component";
4347
- FactoryTarget[FactoryTarget["Injectable"] = 2] = "Injectable";
4348
- FactoryTarget[FactoryTarget["Pipe"] = 3] = "Pipe";
4349
- FactoryTarget[FactoryTarget["NgModule"] = 4] = "NgModule";
4350
- })(FactoryTarget || (FactoryTarget = {}));
4351
4442
  /**
4352
- * Construct a factory function expression for the given `R3FactoryMetadata`.
4443
+ * Remove trailing null nodes as they are implied.
4353
4444
  */
4354
- function compileFactoryFunction(meta) {
4355
- const t = variable('t');
4356
- let baseFactoryVar = null;
4357
- // The type to instantiate via constructor invocation. If there is no delegated factory, meaning
4358
- // this type is always created by constructor invocation, then this is the type-to-create
4359
- // parameter provided by the user (t) if specified, or the current type if not. If there is a
4360
- // delegated factory (which is used to create the current type) then this is only the type-to-
4361
- // create parameter (t).
4362
- const typeForCtor = !isDelegatedFactoryMetadata(meta) ?
4363
- new BinaryOperatorExpr(BinaryOperator.Or, t, meta.internalType) :
4364
- t;
4365
- let ctorExpr = null;
4366
- if (meta.deps !== null) {
4367
- // There is a constructor (either explicitly or implicitly defined).
4368
- if (meta.deps !== 'invalid') {
4369
- ctorExpr = new InstantiateExpr(typeForCtor, injectDependencies(meta.deps, meta.target));
4370
- }
4371
- }
4372
- else {
4373
- // There is no constructor, use the base class' factory to construct typeForCtor.
4374
- baseFactoryVar = variable(`ɵ${meta.name}_BaseFactory`);
4375
- ctorExpr = baseFactoryVar.callFn([typeForCtor]);
4376
- }
4377
- const body = [];
4378
- let retExpr = null;
4379
- function makeConditionalFactory(nonCtorExpr) {
4380
- const r = variable('r');
4381
- body.push(r.set(NULL_EXPR).toDeclStmt());
4382
- const ctorStmt = ctorExpr !== null ? r.set(ctorExpr).toStmt() :
4383
- importExpr(Identifiers.invalidFactory).callFn([]).toStmt();
4384
- body.push(ifStmt(t, [ctorStmt], [r.set(nonCtorExpr).toStmt()]));
4385
- return r;
4386
- }
4387
- if (isDelegatedFactoryMetadata(meta)) {
4388
- // This type is created with a delegated factory. If a type parameter is not specified, call
4389
- // the factory instead.
4390
- const delegateArgs = injectDependencies(meta.delegateDeps, meta.target);
4391
- // Either call `new delegate(...)` or `delegate(...)` depending on meta.delegateType.
4392
- const factoryExpr = new (meta.delegateType === R3FactoryDelegateType.Class ?
4393
- InstantiateExpr :
4394
- InvokeFunctionExpr)(meta.delegate, delegateArgs);
4395
- retExpr = makeConditionalFactory(factoryExpr);
4445
+ function trimTrailingNulls(parameters) {
4446
+ while (isNull(parameters[parameters.length - 1])) {
4447
+ parameters.pop();
4396
4448
  }
4397
- else if (isExpressionFactoryMetadata(meta)) {
4398
- // TODO(alxhub): decide whether to lower the value here or in the caller
4399
- retExpr = makeConditionalFactory(meta.expression);
4449
+ return parameters;
4450
+ }
4451
+ function getQueryPredicate(query, constantPool) {
4452
+ if (Array.isArray(query.predicate)) {
4453
+ let predicate = [];
4454
+ query.predicate.forEach((selector) => {
4455
+ // Each item in predicates array may contain strings with comma-separated refs
4456
+ // (for ex. 'ref, ref1, ..., refN'), thus we extract individual refs and store them
4457
+ // as separate array entities
4458
+ const selectors = selector.split(',').map(token => literal(token.trim()));
4459
+ predicate.push(...selectors);
4460
+ });
4461
+ return constantPool.getConstLiteral(literalArr(predicate), true);
4400
4462
  }
4401
4463
  else {
4402
- retExpr = ctorExpr;
4403
- }
4404
- if (retExpr === null) {
4405
- // The expression cannot be formed so render an `ɵɵinvalidFactory()` call.
4406
- body.push(importExpr(Identifiers.invalidFactory).callFn([]).toStmt());
4464
+ // The original predicate may have been wrapped in a `forwardRef()` call.
4465
+ switch (query.predicate.forwardRef) {
4466
+ case 0 /* None */:
4467
+ case 2 /* Unwrapped */:
4468
+ return query.predicate.expression;
4469
+ case 1 /* Wrapped */:
4470
+ return importExpr(Identifiers.resolveForwardRef).callFn([query.predicate.expression]);
4471
+ }
4407
4472
  }
4408
- else if (baseFactoryVar !== null) {
4409
- // This factory uses a base factory, so call `ɵɵgetInheritedFactory()` to compute it.
4410
- const getInheritedFactoryCall = importExpr(Identifiers.getInheritedFactory).callFn([meta.internalType]);
4411
- // Memoize the base factoryFn: `baseFactory || (baseFactory = ɵɵgetInheritedFactory(...))`
4412
- const baseFactory = new BinaryOperatorExpr(BinaryOperator.Or, baseFactoryVar, baseFactoryVar.set(getInheritedFactoryCall));
4413
- body.push(new ReturnStatement(baseFactory.callFn([typeForCtor])));
4473
+ }
4474
+ /**
4475
+ * A representation for an object literal used during codegen of definition objects. The generic
4476
+ * type `T` allows to reference a documented type of the generated structure, such that the
4477
+ * property names that are set can be resolved to their documented declaration.
4478
+ */
4479
+ class DefinitionMap {
4480
+ constructor() {
4481
+ this.values = [];
4414
4482
  }
4415
- else {
4416
- // This is straightforward factory, just return it.
4417
- body.push(new ReturnStatement(retExpr));
4483
+ set(key, value) {
4484
+ if (value) {
4485
+ this.values.push({ key: key, value, quoted: false });
4486
+ }
4418
4487
  }
4419
- let factoryFn = fn([new FnParam('t', DYNAMIC_TYPE)], body, INFERRED_TYPE, undefined, `${meta.name}_Factory`);
4420
- if (baseFactoryVar !== null) {
4421
- // There is a base factory variable so wrap its declaration along with the factory function into
4422
- // an IIFE.
4423
- factoryFn = fn([], [
4424
- new DeclareVarStmt(baseFactoryVar.name), new ReturnStatement(factoryFn)
4425
- ]).callFn([], /* sourceSpan */ undefined, /* pure */ true);
4488
+ toLiteralMap() {
4489
+ return literalMap(this.values);
4426
4490
  }
4427
- return {
4428
- expression: factoryFn,
4429
- statements: [],
4430
- type: createFactoryType(meta),
4431
- };
4432
- }
4433
- function createFactoryType(meta) {
4434
- const ctorDepsType = meta.deps !== null && meta.deps !== 'invalid' ? createCtorDepsType(meta.deps) : NONE_TYPE;
4435
- return expressionType(importExpr(Identifiers.FactoryDeclaration, [typeWithParameters(meta.type.type, meta.typeArgumentCount), ctorDepsType]));
4436
- }
4437
- function injectDependencies(deps, target) {
4438
- return deps.map((dep, index) => compileInjectDependency(dep, target, index));
4439
4491
  }
4440
- function compileInjectDependency(dep, target, index) {
4441
- // Interpret the dependency according to its resolved type.
4442
- if (dep.token === null) {
4443
- return importExpr(Identifiers.invalidFactoryDep).callFn([literal(index)]);
4444
- }
4445
- else if (dep.attributeNameType === null) {
4446
- // Build up the injection flags according to the metadata.
4447
- const flags = 0 /* Default */ | (dep.self ? 2 /* Self */ : 0) |
4448
- (dep.skipSelf ? 4 /* SkipSelf */ : 0) | (dep.host ? 1 /* Host */ : 0) |
4449
- (dep.optional ? 8 /* Optional */ : 0) |
4450
- (target === FactoryTarget.Pipe ? 16 /* ForPipe */ : 0);
4451
- // If this dependency is optional or otherwise has non-default flags, then additional
4452
- // parameters describing how to inject the dependency must be passed to the inject function
4453
- // that's being used.
4454
- let flagsParam = (flags !== 0 /* Default */ || dep.optional) ? literal(flags) : null;
4455
- // Build up the arguments to the injectFn call.
4456
- const injectArgs = [dep.token];
4457
- if (flagsParam) {
4458
- injectArgs.push(flagsParam);
4459
- }
4460
- const injectFn = getInjectFn(target);
4461
- return importExpr(injectFn).callFn(injectArgs);
4492
+ /**
4493
+ * Extract a map of properties to values for a given element or template node, which can be used
4494
+ * by the directive matching machinery.
4495
+ *
4496
+ * @param elOrTpl the element or template in question
4497
+ * @return an object set up for directive matching. For attributes on the element/template, this
4498
+ * object maps a property name to its (static) value. For any bindings, this map simply maps the
4499
+ * property name to an empty string.
4500
+ */
4501
+ function getAttrsForDirectiveMatching(elOrTpl) {
4502
+ const attributesMap = {};
4503
+ if (elOrTpl instanceof Template && elOrTpl.tagName !== 'ng-template') {
4504
+ elOrTpl.templateAttrs.forEach(a => attributesMap[a.name] = '');
4462
4505
  }
4463
4506
  else {
4464
- // The `dep.attributeTypeName` value is defined, which indicates that this is an `@Attribute()`
4465
- // type dependency. For the generated JS we still want to use the `dep.token` value in case the
4466
- // name given for the attribute is not a string literal. For example given `@Attribute(foo())`,
4467
- // we want to generate `ɵɵinjectAttribute(foo())`.
4468
- //
4469
- // The `dep.attributeTypeName` is only actually used (in `createCtorDepType()`) to generate
4470
- // typings.
4471
- return importExpr(Identifiers.injectAttribute).callFn([dep.token]);
4507
+ elOrTpl.attributes.forEach(a => {
4508
+ if (!isI18nAttribute(a.name)) {
4509
+ attributesMap[a.name] = a.value;
4510
+ }
4511
+ });
4512
+ elOrTpl.inputs.forEach(i => {
4513
+ attributesMap[i.name] = '';
4514
+ });
4515
+ elOrTpl.outputs.forEach(o => {
4516
+ attributesMap[o.name] = '';
4517
+ });
4472
4518
  }
4519
+ return attributesMap;
4473
4520
  }
4474
- function createCtorDepsType(deps) {
4475
- let hasTypes = false;
4476
- const attributeTypes = deps.map(dep => {
4477
- const type = createCtorDepType(dep);
4478
- if (type !== null) {
4479
- hasTypes = true;
4480
- return type;
4481
- }
4482
- else {
4483
- return literal(null);
4521
+ /** Returns a call expression to a chained instruction, e.g. `property(params[0])(params[1])`. */
4522
+ function chainedInstruction(reference, calls, span) {
4523
+ let expression = importExpr(reference, null, span);
4524
+ if (calls.length > 0) {
4525
+ for (let i = 0; i < calls.length; i++) {
4526
+ expression = expression.callFn(calls[i], span);
4484
4527
  }
4485
- });
4486
- if (hasTypes) {
4487
- return expressionType(literalArr(attributeTypes));
4488
4528
  }
4489
4529
  else {
4490
- return NONE_TYPE;
4530
+ // Add a blank invocation, in case the `calls` array is empty.
4531
+ expression = expression.callFn([], span);
4491
4532
  }
4533
+ return expression;
4492
4534
  }
4493
- function createCtorDepType(dep) {
4494
- const entries = [];
4495
- if (dep.attributeNameType !== null) {
4496
- entries.push({ key: 'attribute', value: dep.attributeNameType, quoted: false });
4497
- }
4498
- if (dep.optional) {
4499
- entries.push({ key: 'optional', value: literal(true), quoted: false });
4500
- }
4501
- if (dep.host) {
4502
- entries.push({ key: 'host', value: literal(true), quoted: false });
4503
- }
4504
- if (dep.self) {
4505
- entries.push({ key: 'self', value: literal(true), quoted: false });
4506
- }
4507
- if (dep.skipSelf) {
4508
- entries.push({ key: 'skipSelf', value: literal(true), quoted: false });
4535
+ /**
4536
+ * Gets the number of arguments expected to be passed to a generated instruction in the case of
4537
+ * interpolation instructions.
4538
+ * @param interpolation An interpolation ast
4539
+ */
4540
+ function getInterpolationArgsLength(interpolation) {
4541
+ const { expressions, strings } = interpolation;
4542
+ if (expressions.length === 1 && strings.length === 2 && strings[0] === '' && strings[1] === '') {
4543
+ // If the interpolation has one interpolated value, but the prefix and suffix are both empty
4544
+ // strings, we only pass one argument, to a special instruction like `propertyInterpolate` or
4545
+ // `textInterpolate`.
4546
+ return 1;
4509
4547
  }
4510
- return entries.length > 0 ? literalMap(entries) : null;
4511
- }
4512
- function isDelegatedFactoryMetadata(meta) {
4513
- return meta.delegateType !== undefined;
4514
- }
4515
- function isExpressionFactoryMetadata(meta) {
4516
- return meta.expression !== undefined;
4517
- }
4518
- function getInjectFn(target) {
4519
- switch (target) {
4520
- case FactoryTarget.Component:
4521
- case FactoryTarget.Directive:
4522
- case FactoryTarget.Pipe:
4523
- return Identifiers.directiveInject;
4524
- case FactoryTarget.NgModule:
4525
- case FactoryTarget.Injectable:
4526
- default:
4527
- return Identifiers.inject;
4548
+ else {
4549
+ return expressions.length + strings.length;
4528
4550
  }
4529
4551
  }
4530
4552
 
@@ -4535,9 +4557,6 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
4535
4557
  * Use of this source code is governed by an MIT-style license that can be
4536
4558
  * found in the LICENSE file at https://angular.io/license
4537
4559
  */
4538
- function createR3ProviderExpression(expression, isForwardRef) {
4539
- return { expression, isForwardRef };
4540
- }
4541
4560
  function compileInjectable(meta, resolveForwardRefs) {
4542
4561
  let result = null;
4543
4562
  const factoryMeta = {
@@ -4607,8 +4626,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
4607
4626
  injectableProps.set('factory', result.expression);
4608
4627
  // Only generate providedIn property if it has a non-null value
4609
4628
  if (meta.providedIn.expression.value !== null) {
4610
- injectableProps.set('providedIn', meta.providedIn.isForwardRef ? generateForwardRef(meta.providedIn.expression) :
4611
- meta.providedIn.expression);
4629
+ injectableProps.set('providedIn', convertFromMaybeForwardRefExpression(meta.providedIn));
4612
4630
  }
4613
4631
  const expression = importExpr(Identifiers.ɵɵdefineInjectable)
4614
4632
  .callFn([injectableProps.toLiteralMap()], undefined, true);
@@ -21354,22 +21372,27 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
21354
21372
  const USE_VALUE = Object.keys({ useValue: null })[0];
21355
21373
  const USE_EXISTING = Object.keys({ useExisting: null })[0];
21356
21374
  function convertToR3QueryMetadata(facade) {
21357
- return Object.assign(Object.assign({}, facade), { predicate: Array.isArray(facade.predicate) ? facade.predicate :
21358
- new WrappedNodeExpr(facade.predicate), read: facade.read ? new WrappedNodeExpr(facade.read) : null, static: facade.static, emitDistinctChangesOnly: facade.emitDistinctChangesOnly });
21375
+ return Object.assign(Object.assign({}, facade), { predicate: convertQueryPredicate(facade.predicate), read: facade.read ? new WrappedNodeExpr(facade.read) : null, static: facade.static, emitDistinctChangesOnly: facade.emitDistinctChangesOnly });
21359
21376
  }
21360
21377
  function convertQueryDeclarationToMetadata(declaration) {
21361
21378
  var _a, _b, _c, _d;
21362
21379
  return {
21363
21380
  propertyName: declaration.propertyName,
21364
21381
  first: (_a = declaration.first) !== null && _a !== void 0 ? _a : false,
21365
- predicate: Array.isArray(declaration.predicate) ? declaration.predicate :
21366
- new WrappedNodeExpr(declaration.predicate),
21382
+ predicate: convertQueryPredicate(declaration.predicate),
21367
21383
  descendants: (_b = declaration.descendants) !== null && _b !== void 0 ? _b : false,
21368
21384
  read: declaration.read ? new WrappedNodeExpr(declaration.read) : null,
21369
21385
  static: (_c = declaration.static) !== null && _c !== void 0 ? _c : false,
21370
21386
  emitDistinctChangesOnly: (_d = declaration.emitDistinctChangesOnly) !== null && _d !== void 0 ? _d : true,
21371
21387
  };
21372
21388
  }
21389
+ function convertQueryPredicate(predicate) {
21390
+ return Array.isArray(predicate) ?
21391
+ // The predicate is an array of strings so pass it through.
21392
+ predicate :
21393
+ // The predicate is a type - assume that we will need to unwrap any `forwardRef()` calls.
21394
+ createMayBeForwardRefExpression(new WrappedNodeExpr(predicate), 1 /* Wrapped */);
21395
+ }
21373
21396
  function convertDirectiveFacadeToMetadata(facade) {
21374
21397
  const inputsFromMetadata = parseInputOutputs(facade.inputs || []);
21375
21398
  const outputsFromMetadata = parseInputOutputs(facade.outputs || []);
@@ -21480,11 +21503,11 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
21480
21503
  * In JIT mode we do not want the compiler to wrap the expression in a `forwardRef()` call because,
21481
21504
  * if it is referencing a type that has not yet been defined, it will have already been wrapped in
21482
21505
  * a `forwardRef()` - either by the application developer or during partial-compilation. Thus we can
21483
- * set `isForwardRef` to `false`.
21506
+ * use `ForwardRefHandling.None`.
21484
21507
  */
21485
21508
  function convertToProviderExpression(obj, property) {
21486
21509
  if (obj.hasOwnProperty(property)) {
21487
- return createR3ProviderExpression(new WrappedNodeExpr(obj[property]), /* isForwardRef */ false);
21510
+ return createMayBeForwardRefExpression(new WrappedNodeExpr(obj[property]), 0 /* None */);
21488
21511
  }
21489
21512
  else {
21490
21513
  return undefined;
@@ -21503,7 +21526,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
21503
21526
  new LiteralExpr(providedIn !== null && providedIn !== void 0 ? providedIn : null) :
21504
21527
  new WrappedNodeExpr(providedIn);
21505
21528
  // See `convertToProviderExpression()` for why `isForwardRef` is false.
21506
- return createR3ProviderExpression(expression, /* isForwardRef */ false);
21529
+ return createMayBeForwardRefExpression(expression, 0 /* None */);
21507
21530
  }
21508
21531
  function convertR3DependencyMetadataArray(facades) {
21509
21532
  return facades == null ? null : facades.map(convertR3DependencyMetadata);
@@ -21611,7 +21634,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
21611
21634
  * Use of this source code is governed by an MIT-style license that can be
21612
21635
  * found in the LICENSE file at https://angular.io/license
21613
21636
  */
21614
- const VERSION$1 = new Version('12.2.11');
21637
+ const VERSION$1 = new Version('12.2.15');
21615
21638
 
21616
21639
  /**
21617
21640
  * @license
@@ -29514,10 +29537,22 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
29514
29537
  * Use of this source code is governed by an MIT-style license that can be
29515
29538
  * found in the LICENSE file at https://angular.io/license
29516
29539
  */
29517
- // Base URL for the error details page.
29518
- // Keep this value in sync with a similar const in
29519
- // `packages/compiler-cli/src/ngtsc/diagnostics/src/error_code.ts`.
29540
+ /**
29541
+ * Base URL for the error details page.
29542
+ *
29543
+ * Keep the files below in sync:
29544
+ * - packages/compiler-cli/src/ngtsc/diagnostics/src/error_details_base_url.ts
29545
+ * - packages/core/src/render3/error_details_base_url.ts
29546
+ */
29520
29547
  const ERROR_DETAILS_PAGE_BASE_URL = 'https://angular.io/errors';
29548
+
29549
+ /**
29550
+ * @license
29551
+ * Copyright Google LLC All Rights Reserved.
29552
+ *
29553
+ * Use of this source code is governed by an MIT-style license that can be
29554
+ * found in the LICENSE file at https://angular.io/license
29555
+ */
29521
29556
  class RuntimeError extends Error {
29522
29557
  constructor(code, message) {
29523
29558
  super(formatRuntimeError(code, message));
@@ -31984,8 +32019,8 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
31984
32019
  this._tNode = _tNode;
31985
32020
  this._lView = _lView;
31986
32021
  }
31987
- get(token, notFoundValue) {
31988
- return getOrCreateInjectable(this._tNode, this._lView, token, undefined, notFoundValue);
32022
+ get(token, notFoundValue, flags) {
32023
+ return getOrCreateInjectable(this._tNode, this._lView, token, flags, notFoundValue);
31989
32024
  }
31990
32025
  }
31991
32026
 
@@ -36833,7 +36868,7 @@ define(['exports', 'typescript/lib/tsserverlibrary', 'typescript', 'path'], func
36833
36868
  /**
36834
36869
  * @publicApi
36835
36870
  */
36836
- const VERSION$2 = new Version$1('12.2.11');
36871
+ const VERSION$2 = new Version$1('12.2.15');
36837
36872
 
36838
36873
  /**
36839
36874
  * @license