@angular/compiler 16.1.0-next.3 → 16.1.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm2022/src/compiler_util/expression_converter.mjs +2 -3
- package/esm2022/src/constant_pool.mjs +53 -60
- package/esm2022/src/jit_compiler_facade.mjs +2 -2
- package/esm2022/src/render3/partial/class_metadata.mjs +1 -1
- package/esm2022/src/render3/partial/directive.mjs +1 -1
- package/esm2022/src/render3/partial/factory.mjs +1 -1
- package/esm2022/src/render3/partial/injectable.mjs +1 -1
- package/esm2022/src/render3/partial/injector.mjs +1 -1
- package/esm2022/src/render3/partial/ng_module.mjs +1 -1
- package/esm2022/src/render3/partial/pipe.mjs +1 -1
- package/esm2022/src/render3/r3_identifiers.mjs +2 -3
- package/esm2022/src/render3/view/compiler.mjs +2 -2
- package/esm2022/src/shadow_css.mjs +34 -21
- package/esm2022/src/template/pipeline/ir/src/enums.mjs +26 -2
- package/esm2022/src/template/pipeline/ir/src/expression.mjs +156 -5
- package/esm2022/src/template/pipeline/ir/src/operations.mjs +6 -5
- package/esm2022/src/template/pipeline/ir/src/ops/create.mjs +10 -1
- package/esm2022/src/template/pipeline/ir/src/ops/update.mjs +16 -1
- package/esm2022/src/template/pipeline/ir/src/traits.mjs +20 -2
- package/esm2022/src/template/pipeline/src/compilation.mjs +3 -2
- package/esm2022/src/template/pipeline/src/emit.mjs +11 -1
- package/esm2022/src/template/pipeline/src/ingest.mjs +43 -10
- package/esm2022/src/template/pipeline/src/instruction.mjs +111 -10
- package/esm2022/src/template/pipeline/src/phases/align_pipe_variadic_var_offset.mjs +41 -0
- package/esm2022/src/template/pipeline/src/phases/next_context_merging.mjs +4 -1
- package/esm2022/src/template/pipeline/src/phases/pipe_creation.mjs +57 -0
- package/esm2022/src/template/pipeline/src/phases/pipe_variadic.mjs +26 -0
- package/esm2022/src/template/pipeline/src/phases/pure_function_extraction.mjs +54 -0
- package/esm2022/src/template/pipeline/src/phases/pure_literal_structures.mjs +58 -0
- package/esm2022/src/template/pipeline/src/phases/reify.mjs +21 -1
- package/esm2022/src/template/pipeline/src/phases/slot_allocation.mjs +4 -1
- package/esm2022/src/template/pipeline/src/phases/var_counting.mjs +23 -3
- package/esm2022/src/template/pipeline/src/phases/variable_optimization.mjs +13 -1
- package/esm2022/src/version.mjs +1 -1
- package/fesm2022/compiler.mjs +731 -117
- package/fesm2022/compiler.mjs.map +1 -1
- package/fesm2022/testing.mjs +1 -1
- package/index.d.ts +11 -2
- package/package.json +2 -2
- package/testing/index.d.ts +1 -1
package/fesm2022/compiler.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Angular v16.1.0-
|
|
2
|
+
* @license Angular v16.1.0-rc.0
|
|
3
3
|
* (c) 2010-2022 Google LLC. https://angular.io/
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
@@ -2272,6 +2272,7 @@ class ConstantPool {
|
|
|
2272
2272
|
this.statements = [];
|
|
2273
2273
|
this.literals = new Map();
|
|
2274
2274
|
this.literalFactories = new Map();
|
|
2275
|
+
this.sharedConstants = new Map();
|
|
2275
2276
|
this.nextNameIndex = 0;
|
|
2276
2277
|
}
|
|
2277
2278
|
getConstLiteral(literal, forceShared) {
|
|
@@ -2281,7 +2282,7 @@ class ConstantPool {
|
|
|
2281
2282
|
// reference to a constant.
|
|
2282
2283
|
return literal;
|
|
2283
2284
|
}
|
|
2284
|
-
const key =
|
|
2285
|
+
const key = GenericKeyFn.INSTANCE.keyOf(literal);
|
|
2285
2286
|
let fixup = this.literals.get(key);
|
|
2286
2287
|
let newValue = false;
|
|
2287
2288
|
if (!fixup) {
|
|
@@ -2326,11 +2327,20 @@ class ConstantPool {
|
|
|
2326
2327
|
}
|
|
2327
2328
|
return fixup;
|
|
2328
2329
|
}
|
|
2330
|
+
getSharedConstant(def, expr) {
|
|
2331
|
+
const key = def.keyOf(expr);
|
|
2332
|
+
if (!this.sharedConstants.has(key)) {
|
|
2333
|
+
const id = this.freshName();
|
|
2334
|
+
this.sharedConstants.set(key, variable(id));
|
|
2335
|
+
this.statements.push(def.toSharedConstantDeclaration(id, expr));
|
|
2336
|
+
}
|
|
2337
|
+
return this.sharedConstants.get(key);
|
|
2338
|
+
}
|
|
2329
2339
|
getLiteralFactory(literal) {
|
|
2330
2340
|
// Create a pure function that builds an array of a mix of constant and variable expressions
|
|
2331
2341
|
if (literal instanceof LiteralArrayExpr) {
|
|
2332
2342
|
const argumentsForKey = literal.entries.map(e => e.isConstant() ? e : UNKNOWN_VALUE_KEY);
|
|
2333
|
-
const key =
|
|
2343
|
+
const key = GenericKeyFn.INSTANCE.keyOf(literalArr(argumentsForKey));
|
|
2334
2344
|
return this._getLiteralFactory(key, literal.entries, entries => literalArr(entries));
|
|
2335
2345
|
}
|
|
2336
2346
|
else {
|
|
@@ -2339,7 +2349,7 @@ class ConstantPool {
|
|
|
2339
2349
|
value: e.value.isConstant() ? e.value : UNKNOWN_VALUE_KEY,
|
|
2340
2350
|
quoted: e.quoted
|
|
2341
2351
|
})));
|
|
2342
|
-
const key =
|
|
2352
|
+
const key = GenericKeyFn.INSTANCE.keyOf(expressionForKey);
|
|
2343
2353
|
return this._getLiteralFactory(key, literal.entries.map(e => e.value), entries => literalMap(entries.map((value, index) => ({
|
|
2344
2354
|
key: literal.entries[index].key,
|
|
2345
2355
|
value,
|
|
@@ -2376,65 +2386,48 @@ class ConstantPool {
|
|
|
2376
2386
|
freshName() {
|
|
2377
2387
|
return this.uniqueName(CONSTANT_PREFIX);
|
|
2378
2388
|
}
|
|
2379
|
-
keyOf(expression) {
|
|
2380
|
-
return expression.visitExpression(new KeyVisitor(), KEY_CONTEXT);
|
|
2381
|
-
}
|
|
2382
2389
|
}
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
return `{${ast.entries.map(mapEntry).join(',')}`;
|
|
2423
|
-
}
|
|
2424
|
-
visitExternalExpr(ast) {
|
|
2425
|
-
return ast.value.moduleName ? `EX:${ast.value.moduleName}:${ast.value.name}` :
|
|
2426
|
-
`EX:${ast.value.runtime.name}`;
|
|
2427
|
-
}
|
|
2428
|
-
visitReadVarExpr(node) {
|
|
2429
|
-
return `VAR:${node.name}`;
|
|
2430
|
-
}
|
|
2431
|
-
visitTypeofExpr(node, context) {
|
|
2432
|
-
return `TYPEOF:${node.expr.visitExpression(this, context)}`;
|
|
2390
|
+
class GenericKeyFn {
|
|
2391
|
+
static { this.INSTANCE = new GenericKeyFn(); }
|
|
2392
|
+
keyOf(expr) {
|
|
2393
|
+
if (expr instanceof LiteralExpr && typeof expr.value === 'string') {
|
|
2394
|
+
return `"${expr.value}"`;
|
|
2395
|
+
}
|
|
2396
|
+
else if (expr instanceof LiteralExpr) {
|
|
2397
|
+
return String(expr.value);
|
|
2398
|
+
}
|
|
2399
|
+
else if (expr instanceof LiteralArrayExpr) {
|
|
2400
|
+
const entries = [];
|
|
2401
|
+
for (const entry of expr.entries) {
|
|
2402
|
+
entries.push(this.keyOf(entry));
|
|
2403
|
+
}
|
|
2404
|
+
return `[${entries.join(',')}]`;
|
|
2405
|
+
}
|
|
2406
|
+
else if (expr instanceof LiteralMapExpr) {
|
|
2407
|
+
const entries = [];
|
|
2408
|
+
for (const entry of expr.entries) {
|
|
2409
|
+
let key = entry.key;
|
|
2410
|
+
if (entry.quoted) {
|
|
2411
|
+
key = `"${key}"`;
|
|
2412
|
+
}
|
|
2413
|
+
entries.push(key + ':' + this.keyOf(entry.value));
|
|
2414
|
+
}
|
|
2415
|
+
return `{${entries.join(',')}}`;
|
|
2416
|
+
}
|
|
2417
|
+
else if (expr instanceof ExternalExpr) {
|
|
2418
|
+
return `import("${expr.value.moduleName}", ${expr.value.name})`;
|
|
2419
|
+
}
|
|
2420
|
+
else if (expr instanceof ReadVarExpr) {
|
|
2421
|
+
return `read(${expr.name})`;
|
|
2422
|
+
}
|
|
2423
|
+
else if (expr instanceof TypeofExpr) {
|
|
2424
|
+
return `typeof(${this.keyOf(expr.expr)})`;
|
|
2425
|
+
}
|
|
2426
|
+
else {
|
|
2427
|
+
throw new Error(`${this.constructor.name} does not handle expressions of type ${expr.constructor.name}`);
|
|
2428
|
+
}
|
|
2433
2429
|
}
|
|
2434
2430
|
}
|
|
2435
|
-
function invalid$1(arg) {
|
|
2436
|
-
throw new Error(`Invalid state: Visitor ${this.constructor.name} doesn't handle ${arg.constructor.name}`);
|
|
2437
|
-
}
|
|
2438
2431
|
function isVariable(e) {
|
|
2439
2432
|
return e instanceof ReadVarExpr;
|
|
2440
2433
|
}
|
|
@@ -7508,11 +7501,28 @@ class ShadowCss {
|
|
|
7508
7501
|
* The hostSelector is the attribute added to the host itself.
|
|
7509
7502
|
*/
|
|
7510
7503
|
shimCssText(cssText, selector, hostSelector = '') {
|
|
7511
|
-
|
|
7512
|
-
|
|
7504
|
+
// **NOTE**: Do not strip comments as this will cause component sourcemaps to break
|
|
7505
|
+
// due to shift in lines.
|
|
7506
|
+
// Collect comments and replace them with a placeholder, this is done to avoid complicating
|
|
7507
|
+
// the rule parsing RegExp and keep it safer.
|
|
7508
|
+
const comments = [];
|
|
7509
|
+
cssText = cssText.replace(_commentRe, (m) => {
|
|
7510
|
+
if (m.match(_commentWithHashRe)) {
|
|
7511
|
+
comments.push(m);
|
|
7512
|
+
}
|
|
7513
|
+
else {
|
|
7514
|
+
// Replace non hash comments with empty lines.
|
|
7515
|
+
// This is done so that we do not leak any senstive data in comments.
|
|
7516
|
+
const newLinesMatches = m.match(_newLinesRe);
|
|
7517
|
+
comments.push((newLinesMatches?.join('') ?? '') + '\n');
|
|
7518
|
+
}
|
|
7519
|
+
return COMMENT_PLACEHOLDER;
|
|
7520
|
+
});
|
|
7513
7521
|
cssText = this._insertDirectives(cssText);
|
|
7514
7522
|
const scopedCssText = this._scopeCssText(cssText, selector, hostSelector);
|
|
7515
|
-
|
|
7523
|
+
// Add back comments at the original position.
|
|
7524
|
+
let commentIdx = 0;
|
|
7525
|
+
return scopedCssText.replace(_commentWithHashPlaceHolderRe, () => comments[commentIdx++]);
|
|
7516
7526
|
}
|
|
7517
7527
|
_insertDirectives(cssText) {
|
|
7518
7528
|
cssText = this._insertPolyfillDirectivesInCssText(cssText);
|
|
@@ -7753,7 +7763,7 @@ class ShadowCss {
|
|
|
7753
7763
|
return cssText.replace(_cssColonHostRe, (_, hostSelectors, otherSelectors) => {
|
|
7754
7764
|
if (hostSelectors) {
|
|
7755
7765
|
const convertedSelectors = [];
|
|
7756
|
-
const hostSelectorArray = hostSelectors.split(',').map(p => p.trim());
|
|
7766
|
+
const hostSelectorArray = hostSelectors.split(',').map((p) => p.trim());
|
|
7757
7767
|
for (const hostSelector of hostSelectorArray) {
|
|
7758
7768
|
if (!hostSelector)
|
|
7759
7769
|
break;
|
|
@@ -7783,7 +7793,7 @@ class ShadowCss {
|
|
|
7783
7793
|
* .foo<scopeName> .bar { ... }
|
|
7784
7794
|
*/
|
|
7785
7795
|
_convertColonHostContext(cssText) {
|
|
7786
|
-
return cssText.replace(_cssColonHostContextReGlobal, selectorText => {
|
|
7796
|
+
return cssText.replace(_cssColonHostContextReGlobal, (selectorText) => {
|
|
7787
7797
|
// We have captured a selector that contains a `:host-context` rule.
|
|
7788
7798
|
// For backward compatibility `:host-context` may contain a comma separated list of selectors.
|
|
7789
7799
|
// Each context selector group will contain a list of host-context selectors that must match
|
|
@@ -7795,10 +7805,10 @@ class ShadowCss {
|
|
|
7795
7805
|
// Execute `_cssColonHostContextRe` over and over until we have extracted all the
|
|
7796
7806
|
// `:host-context` selectors from this selector.
|
|
7797
7807
|
let match;
|
|
7798
|
-
while (match = _cssColonHostContextRe.exec(selectorText)) {
|
|
7808
|
+
while ((match = _cssColonHostContextRe.exec(selectorText))) {
|
|
7799
7809
|
// `match` = [':host-context(<selectors>)<rest>', <selectors>, <rest>]
|
|
7800
7810
|
// The `<selectors>` could actually be a comma separated list: `:host-context(.one, .two)`.
|
|
7801
|
-
const newContextSelectors = (match[1] ?? '').trim().split(',').map(m => m.trim()).filter(m => m !== '');
|
|
7811
|
+
const newContextSelectors = (match[1] ?? '').trim().split(',').map((m) => m.trim()).filter((m) => m !== '');
|
|
7802
7812
|
// We must duplicate the current selector group for each of these new selectors.
|
|
7803
7813
|
// For example if the current groups are:
|
|
7804
7814
|
// ```
|
|
@@ -7821,7 +7831,7 @@ class ShadowCss {
|
|
|
7821
7831
|
repeatGroups(contextSelectorGroups, newContextSelectors.length);
|
|
7822
7832
|
for (let i = 0; i < newContextSelectors.length; i++) {
|
|
7823
7833
|
for (let j = 0; j < contextSelectorGroupsLength; j++) {
|
|
7824
|
-
contextSelectorGroups[j +
|
|
7834
|
+
contextSelectorGroups[j + i * contextSelectorGroupsLength].push(newContextSelectors[i]);
|
|
7825
7835
|
}
|
|
7826
7836
|
}
|
|
7827
7837
|
// Update the `selectorText` and see repeat to see if there are more `:host-context`s.
|
|
@@ -7831,7 +7841,7 @@ class ShadowCss {
|
|
|
7831
7841
|
// selectors that `:host-context` can match. See `combineHostContextSelectors()` for more
|
|
7832
7842
|
// info about how this is done.
|
|
7833
7843
|
return contextSelectorGroups
|
|
7834
|
-
.map(contextSelectors => combineHostContextSelectors(contextSelectors, selectorText))
|
|
7844
|
+
.map((contextSelectors) => combineHostContextSelectors(contextSelectors, selectorText))
|
|
7835
7845
|
.join(', ');
|
|
7836
7846
|
});
|
|
7837
7847
|
}
|
|
@@ -7883,7 +7893,7 @@ class ShadowCss {
|
|
|
7883
7893
|
* ```
|
|
7884
7894
|
*/
|
|
7885
7895
|
_stripScopingSelectors(cssText) {
|
|
7886
|
-
return processRules(cssText, rule => {
|
|
7896
|
+
return processRules(cssText, (rule) => {
|
|
7887
7897
|
const selector = rule.selector.replace(_shadowDeepSelectors, ' ')
|
|
7888
7898
|
.replace(_polyfillHostNoCombinatorRe, ' ');
|
|
7889
7899
|
return new CssRule(selector, rule.content);
|
|
@@ -7891,7 +7901,7 @@ class ShadowCss {
|
|
|
7891
7901
|
}
|
|
7892
7902
|
_scopeSelector(selector, scopeSelector, hostSelector) {
|
|
7893
7903
|
return selector.split(',')
|
|
7894
|
-
.map(part => part.trim().split(_shadowDeepSelectors))
|
|
7904
|
+
.map((part) => part.trim().split(_shadowDeepSelectors))
|
|
7895
7905
|
.map((deepParts) => {
|
|
7896
7906
|
const [shallowPart, ...otherParts] = deepParts;
|
|
7897
7907
|
const applyScope = (shallowPart) => {
|
|
@@ -8074,17 +8084,14 @@ const _selectorReSuffix = '([>\\s~+[.,{:][\\s\\S]*)?$';
|
|
|
8074
8084
|
const _polyfillHostRe = /-shadowcsshost/gim;
|
|
8075
8085
|
const _colonHostRe = /:host/gim;
|
|
8076
8086
|
const _colonHostContextRe = /:host-context/gim;
|
|
8087
|
+
const _newLinesRe = /\r?\n/g;
|
|
8077
8088
|
const _commentRe = /\/\*[\s\S]*?\*\//g;
|
|
8089
|
+
const _commentWithHashRe = /\/\*\s*#\s*source(Mapping)?URL=/g;
|
|
8090
|
+
const COMMENT_PLACEHOLDER = '%COMMENT%';
|
|
8091
|
+
const _commentWithHashPlaceHolderRe = new RegExp(COMMENT_PLACEHOLDER, 'g');
|
|
8078
8092
|
const _placeholderRe = /__ph-(\d+)__/g;
|
|
8079
|
-
function stripComments(input) {
|
|
8080
|
-
return input.replace(_commentRe, '');
|
|
8081
|
-
}
|
|
8082
|
-
const _commentWithHashRe = /\/\*\s*#\s*source(Mapping)?URL=[\s\S]+?\*\//g;
|
|
8083
|
-
function extractCommentsWithHash(input) {
|
|
8084
|
-
return input.match(_commentWithHashRe) || [];
|
|
8085
|
-
}
|
|
8086
8093
|
const BLOCK_PLACEHOLDER = '%BLOCK%';
|
|
8087
|
-
const _ruleRe =
|
|
8094
|
+
const _ruleRe = new RegExp(`(\\s*(?:${COMMENT_PLACEHOLDER}\\s*)*)([^;\\{\\}]+?)(\\s*)((?:{%BLOCK%}?\\s*;?)|(?:\\s*;))`, 'g');
|
|
8088
8095
|
const CONTENT_PAIRS = new Map([['{', '}']]);
|
|
8089
8096
|
const COMMA_IN_PLACEHOLDER = '%COMMA_IN_PLACEHOLDER%';
|
|
8090
8097
|
const SEMI_IN_PLACEHOLDER = '%SEMI_IN_PLACEHOLDER%';
|
|
@@ -8293,7 +8300,6 @@ function unescapeQuotes(str, isQuoted) {
|
|
|
8293
8300
|
*
|
|
8294
8301
|
* And so on...
|
|
8295
8302
|
*
|
|
8296
|
-
* @param hostMarker the string that selects the host element.
|
|
8297
8303
|
* @param contextSelectors an array of context selectors that will be combined.
|
|
8298
8304
|
* @param otherSelectors the rest of the selectors that are not context selectors.
|
|
8299
8305
|
*/
|
|
@@ -8538,10 +8544,18 @@ var OpKind;
|
|
|
8538
8544
|
* An operation to bind an expression to a property of an element.
|
|
8539
8545
|
*/
|
|
8540
8546
|
OpKind[OpKind["Property"] = 13] = "Property";
|
|
8547
|
+
/**
|
|
8548
|
+
* An operation to interpolate text into a property binding.
|
|
8549
|
+
*/
|
|
8550
|
+
OpKind[OpKind["InterpolateProperty"] = 14] = "InterpolateProperty";
|
|
8541
8551
|
/**
|
|
8542
8552
|
* An operation to advance the runtime's implicit slot context during the update phase of a view.
|
|
8543
8553
|
*/
|
|
8544
|
-
OpKind[OpKind["Advance"] =
|
|
8554
|
+
OpKind[OpKind["Advance"] = 15] = "Advance";
|
|
8555
|
+
/**
|
|
8556
|
+
* An operation to instantiate a pipe.
|
|
8557
|
+
*/
|
|
8558
|
+
OpKind[OpKind["Pipe"] = 16] = "Pipe";
|
|
8545
8559
|
})(OpKind || (OpKind = {}));
|
|
8546
8560
|
/**
|
|
8547
8561
|
* Distinguishes different kinds of IR expressions.
|
|
@@ -8580,6 +8594,22 @@ var ExpressionKind;
|
|
|
8580
8594
|
* Runtime operation to reset the current view context after `RestoreView`.
|
|
8581
8595
|
*/
|
|
8582
8596
|
ExpressionKind[ExpressionKind["ResetView"] = 7] = "ResetView";
|
|
8597
|
+
/**
|
|
8598
|
+
* Defines and calls a function with change-detected arguments.
|
|
8599
|
+
*/
|
|
8600
|
+
ExpressionKind[ExpressionKind["PureFunctionExpr"] = 8] = "PureFunctionExpr";
|
|
8601
|
+
/**
|
|
8602
|
+
* Indicates a positional parameter to a pure function definition.
|
|
8603
|
+
*/
|
|
8604
|
+
ExpressionKind[ExpressionKind["PureFunctionParameterExpr"] = 9] = "PureFunctionParameterExpr";
|
|
8605
|
+
/**
|
|
8606
|
+
* Binding to a pipe transformation.
|
|
8607
|
+
*/
|
|
8608
|
+
ExpressionKind[ExpressionKind["PipeBinding"] = 10] = "PipeBinding";
|
|
8609
|
+
/**
|
|
8610
|
+
* Binding to a pipe transformation with a variable number of arguments.
|
|
8611
|
+
*/
|
|
8612
|
+
ExpressionKind[ExpressionKind["PipeBindingVariadic"] = 11] = "PipeBindingVariadic";
|
|
8583
8613
|
})(ExpressionKind || (ExpressionKind = {}));
|
|
8584
8614
|
/**
|
|
8585
8615
|
* Distinguishes between different kinds of `SemanticVariable`s.
|
|
@@ -8615,7 +8645,11 @@ const UsesSlotIndex = Symbol('UsesSlotIndex');
|
|
|
8615
8645
|
/**
|
|
8616
8646
|
* Marker symbol for `ConsumesVars` trait.
|
|
8617
8647
|
*/
|
|
8618
|
-
const ConsumesVarsTrait = Symbol('
|
|
8648
|
+
const ConsumesVarsTrait = Symbol('ConsumesVars');
|
|
8649
|
+
/**
|
|
8650
|
+
* Marker symbol for `UsesVarOffset` trait.
|
|
8651
|
+
*/
|
|
8652
|
+
const UsesVarOffset = Symbol('UsesVarOffset');
|
|
8619
8653
|
/**
|
|
8620
8654
|
* Default values for most `ConsumesSlotOpTrait` fields (used with the spread operator to initialize
|
|
8621
8655
|
* implementors of the trait).
|
|
@@ -8647,6 +8681,14 @@ const TRAIT_DEPENDS_ON_SLOT_CONTEXT = {
|
|
|
8647
8681
|
const TRAIT_CONSUMES_VARS = {
|
|
8648
8682
|
[ConsumesVarsTrait]: true,
|
|
8649
8683
|
};
|
|
8684
|
+
/**
|
|
8685
|
+
* Default values for `UsesVarOffset` fields (used with the spread operator to initialize
|
|
8686
|
+
* implementors of this trait).
|
|
8687
|
+
*/
|
|
8688
|
+
const TRAIT_USES_VAR_OFFSET = {
|
|
8689
|
+
[UsesVarOffset]: true,
|
|
8690
|
+
varOffset: null,
|
|
8691
|
+
};
|
|
8650
8692
|
/**
|
|
8651
8693
|
* Test whether an operation implements `ConsumesSlotOpTrait`.
|
|
8652
8694
|
*/
|
|
@@ -8662,11 +8704,17 @@ function hasDependsOnSlotContextTrait(op) {
|
|
|
8662
8704
|
function hasConsumesVarsTrait(value) {
|
|
8663
8705
|
return value[ConsumesVarsTrait] === true;
|
|
8664
8706
|
}
|
|
8707
|
+
/**
|
|
8708
|
+
* Test whether an expression implements `UsesVarOffsetTrait`.
|
|
8709
|
+
*/
|
|
8710
|
+
function hasUsesVarOffsetTrait(expr) {
|
|
8711
|
+
return expr[UsesVarOffset] === true;
|
|
8712
|
+
}
|
|
8665
8713
|
function hasUsesSlotIndexTrait(value) {
|
|
8666
8714
|
return value[UsesSlotIndex] === true;
|
|
8667
8715
|
}
|
|
8668
8716
|
|
|
8669
|
-
var _a;
|
|
8717
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
8670
8718
|
/**
|
|
8671
8719
|
* Check whether a given `o.Expression` is a logical IR expression type.
|
|
8672
8720
|
*/
|
|
@@ -8852,6 +8900,125 @@ class ReadVariableExpr extends ExpressionBase {
|
|
|
8852
8900
|
}
|
|
8853
8901
|
transformInternalExpressions() { }
|
|
8854
8902
|
}
|
|
8903
|
+
class PureFunctionExpr extends ExpressionBase {
|
|
8904
|
+
static { _b = ConsumesVarsTrait, _c = UsesVarOffset; }
|
|
8905
|
+
constructor(expression, args) {
|
|
8906
|
+
super();
|
|
8907
|
+
this.kind = ExpressionKind.PureFunctionExpr;
|
|
8908
|
+
this[_b] = true;
|
|
8909
|
+
this[_c] = true;
|
|
8910
|
+
this.varOffset = null;
|
|
8911
|
+
/**
|
|
8912
|
+
* Once extracted to the `ConstantPool`, a reference to the function which defines the computation
|
|
8913
|
+
* of `body`.
|
|
8914
|
+
*/
|
|
8915
|
+
this.fn = null;
|
|
8916
|
+
this.body = expression;
|
|
8917
|
+
this.args = args;
|
|
8918
|
+
}
|
|
8919
|
+
visitExpression(visitor, context) {
|
|
8920
|
+
this.body?.visitExpression(visitor, context);
|
|
8921
|
+
for (const arg of this.args) {
|
|
8922
|
+
arg.visitExpression(visitor, context);
|
|
8923
|
+
}
|
|
8924
|
+
}
|
|
8925
|
+
isEquivalent(other) {
|
|
8926
|
+
if (!(other instanceof PureFunctionExpr) || other.args.length !== this.args.length) {
|
|
8927
|
+
return false;
|
|
8928
|
+
}
|
|
8929
|
+
return other.body !== null && this.body !== null && other.body.isEquivalent(this.body) &&
|
|
8930
|
+
other.args.every((arg, idx) => arg.isEquivalent(this.args[idx]));
|
|
8931
|
+
}
|
|
8932
|
+
isConstant() {
|
|
8933
|
+
return false;
|
|
8934
|
+
}
|
|
8935
|
+
transformInternalExpressions(transform, flags) {
|
|
8936
|
+
if (this.body !== null) {
|
|
8937
|
+
// TODO: figure out if this is the right flag to pass here.
|
|
8938
|
+
this.body = transformExpressionsInExpression(this.body, transform, flags | VisitorContextFlag.InChildOperation);
|
|
8939
|
+
}
|
|
8940
|
+
else if (this.fn !== null) {
|
|
8941
|
+
this.fn = transformExpressionsInExpression(this.fn, transform, flags);
|
|
8942
|
+
}
|
|
8943
|
+
for (let i = 0; i < this.args.length; i++) {
|
|
8944
|
+
this.args[i] = transformExpressionsInExpression(this.args[i], transform, flags);
|
|
8945
|
+
}
|
|
8946
|
+
}
|
|
8947
|
+
}
|
|
8948
|
+
class PureFunctionParameterExpr extends ExpressionBase {
|
|
8949
|
+
constructor(index) {
|
|
8950
|
+
super();
|
|
8951
|
+
this.index = index;
|
|
8952
|
+
this.kind = ExpressionKind.PureFunctionParameterExpr;
|
|
8953
|
+
}
|
|
8954
|
+
visitExpression() { }
|
|
8955
|
+
isEquivalent(other) {
|
|
8956
|
+
return other instanceof PureFunctionParameterExpr && other.index === this.index;
|
|
8957
|
+
}
|
|
8958
|
+
isConstant() {
|
|
8959
|
+
return true;
|
|
8960
|
+
}
|
|
8961
|
+
transformInternalExpressions() { }
|
|
8962
|
+
}
|
|
8963
|
+
class PipeBindingExpr extends ExpressionBase {
|
|
8964
|
+
static { _d = UsesSlotIndex, _e = ConsumesVarsTrait, _f = UsesVarOffset; }
|
|
8965
|
+
constructor(target, name, args) {
|
|
8966
|
+
super();
|
|
8967
|
+
this.target = target;
|
|
8968
|
+
this.name = name;
|
|
8969
|
+
this.args = args;
|
|
8970
|
+
this.kind = ExpressionKind.PipeBinding;
|
|
8971
|
+
this[_d] = true;
|
|
8972
|
+
this[_e] = true;
|
|
8973
|
+
this[_f] = true;
|
|
8974
|
+
this.slot = null;
|
|
8975
|
+
this.varOffset = null;
|
|
8976
|
+
}
|
|
8977
|
+
visitExpression(visitor, context) {
|
|
8978
|
+
for (const arg of this.args) {
|
|
8979
|
+
arg.visitExpression(visitor, context);
|
|
8980
|
+
}
|
|
8981
|
+
}
|
|
8982
|
+
isEquivalent() {
|
|
8983
|
+
return false;
|
|
8984
|
+
}
|
|
8985
|
+
isConstant() {
|
|
8986
|
+
return false;
|
|
8987
|
+
}
|
|
8988
|
+
transformInternalExpressions(transform, flags) {
|
|
8989
|
+
for (let idx = 0; idx < this.args.length; idx++) {
|
|
8990
|
+
this.args[idx] = transformExpressionsInExpression(this.args[idx], transform, flags);
|
|
8991
|
+
}
|
|
8992
|
+
}
|
|
8993
|
+
}
|
|
8994
|
+
class PipeBindingVariadicExpr extends ExpressionBase {
|
|
8995
|
+
static { _g = UsesSlotIndex, _h = ConsumesVarsTrait, _j = UsesVarOffset; }
|
|
8996
|
+
constructor(target, name, args, numArgs) {
|
|
8997
|
+
super();
|
|
8998
|
+
this.target = target;
|
|
8999
|
+
this.name = name;
|
|
9000
|
+
this.args = args;
|
|
9001
|
+
this.numArgs = numArgs;
|
|
9002
|
+
this.kind = ExpressionKind.PipeBindingVariadic;
|
|
9003
|
+
this[_g] = true;
|
|
9004
|
+
this[_h] = true;
|
|
9005
|
+
this[_j] = true;
|
|
9006
|
+
this.slot = null;
|
|
9007
|
+
this.varOffset = null;
|
|
9008
|
+
}
|
|
9009
|
+
visitExpression(visitor, context) {
|
|
9010
|
+
this.args.visitExpression(visitor, context);
|
|
9011
|
+
}
|
|
9012
|
+
isEquivalent() {
|
|
9013
|
+
return false;
|
|
9014
|
+
}
|
|
9015
|
+
isConstant() {
|
|
9016
|
+
return false;
|
|
9017
|
+
}
|
|
9018
|
+
transformInternalExpressions(transform, flags) {
|
|
9019
|
+
this.args = transformExpressionsInExpression(this.args, transform, flags);
|
|
9020
|
+
}
|
|
9021
|
+
}
|
|
8855
9022
|
/**
|
|
8856
9023
|
* Visits all `Expression`s in the AST of `op` with the `visitor` function.
|
|
8857
9024
|
*/
|
|
@@ -8877,6 +9044,11 @@ function transformExpressionsInOp(op, transform, flags) {
|
|
|
8877
9044
|
case OpKind.Property:
|
|
8878
9045
|
op.expression = transformExpressionsInExpression(op.expression, transform, flags);
|
|
8879
9046
|
break;
|
|
9047
|
+
case OpKind.InterpolateProperty:
|
|
9048
|
+
for (let i = 0; i < op.expressions.length; i++) {
|
|
9049
|
+
op.expressions[i] = transformExpressionsInExpression(op.expressions[i], transform, flags);
|
|
9050
|
+
}
|
|
9051
|
+
break;
|
|
8880
9052
|
case OpKind.Statement:
|
|
8881
9053
|
transformExpressionsInStatement(op.statement, transform, flags);
|
|
8882
9054
|
break;
|
|
@@ -8901,6 +9073,7 @@ function transformExpressionsInOp(op, transform, flags) {
|
|
|
8901
9073
|
case OpKind.ContainerEnd:
|
|
8902
9074
|
case OpKind.Template:
|
|
8903
9075
|
case OpKind.Text:
|
|
9076
|
+
case OpKind.Pipe:
|
|
8904
9077
|
case OpKind.Advance:
|
|
8905
9078
|
// These operations contain no expressions.
|
|
8906
9079
|
break;
|
|
@@ -8917,7 +9090,6 @@ function transformExpressionsInOp(op, transform, flags) {
|
|
|
8917
9090
|
function transformExpressionsInExpression(expr, transform, flags) {
|
|
8918
9091
|
if (expr instanceof ExpressionBase) {
|
|
8919
9092
|
expr.transformInternalExpressions(transform, flags);
|
|
8920
|
-
return transform(expr, flags);
|
|
8921
9093
|
}
|
|
8922
9094
|
else if (expr instanceof BinaryOperatorExpr) {
|
|
8923
9095
|
expr.lhs = transformExpressionsInExpression(expr.lhs, transform, flags);
|
|
@@ -8930,12 +9102,39 @@ function transformExpressionsInExpression(expr, transform, flags) {
|
|
|
8930
9102
|
expr.receiver = transformExpressionsInExpression(expr.receiver, transform, flags);
|
|
8931
9103
|
expr.index = transformExpressionsInExpression(expr.index, transform, flags);
|
|
8932
9104
|
}
|
|
9105
|
+
else if (expr instanceof WritePropExpr) {
|
|
9106
|
+
expr.receiver = transformExpressionsInExpression(expr.receiver, transform, flags);
|
|
9107
|
+
expr.value = transformExpressionsInExpression(expr.value, transform, flags);
|
|
9108
|
+
}
|
|
9109
|
+
else if (expr instanceof WriteKeyExpr) {
|
|
9110
|
+
expr.receiver = transformExpressionsInExpression(expr.receiver, transform, flags);
|
|
9111
|
+
expr.index = transformExpressionsInExpression(expr.index, transform, flags);
|
|
9112
|
+
expr.value = transformExpressionsInExpression(expr.value, transform, flags);
|
|
9113
|
+
}
|
|
8933
9114
|
else if (expr instanceof InvokeFunctionExpr) {
|
|
8934
9115
|
expr.fn = transformExpressionsInExpression(expr.fn, transform, flags);
|
|
8935
9116
|
for (let i = 0; i < expr.args.length; i++) {
|
|
8936
9117
|
expr.args[i] = transformExpressionsInExpression(expr.args[i], transform, flags);
|
|
8937
9118
|
}
|
|
8938
9119
|
}
|
|
9120
|
+
else if (expr instanceof LiteralArrayExpr) {
|
|
9121
|
+
for (let i = 0; i < expr.entries.length; i++) {
|
|
9122
|
+
expr.entries[i] = transformExpressionsInExpression(expr.entries[i], transform, flags);
|
|
9123
|
+
}
|
|
9124
|
+
}
|
|
9125
|
+
else if (expr instanceof LiteralMapExpr) {
|
|
9126
|
+
for (let i = 0; i < expr.entries.length; i++) {
|
|
9127
|
+
expr.entries[i].value =
|
|
9128
|
+
transformExpressionsInExpression(expr.entries[i].value, transform, flags);
|
|
9129
|
+
}
|
|
9130
|
+
}
|
|
9131
|
+
else if (expr instanceof ConditionalExpr) {
|
|
9132
|
+
expr.condition = transformExpressionsInExpression(expr.condition, transform, flags);
|
|
9133
|
+
expr.trueCase = transformExpressionsInExpression(expr.trueCase, transform, flags);
|
|
9134
|
+
if (expr.falseCase !== null) {
|
|
9135
|
+
expr.falseCase = transformExpressionsInExpression(expr.falseCase, transform, flags);
|
|
9136
|
+
}
|
|
9137
|
+
}
|
|
8939
9138
|
else if (expr instanceof ReadVarExpr || expr instanceof ExternalExpr ||
|
|
8940
9139
|
expr instanceof LiteralExpr) {
|
|
8941
9140
|
// No action for these types.
|
|
@@ -8943,7 +9142,7 @@ function transformExpressionsInExpression(expr, transform, flags) {
|
|
|
8943
9142
|
else {
|
|
8944
9143
|
throw new Error(`Unhandled expression kind: ${expr.constructor.name}`);
|
|
8945
9144
|
}
|
|
8946
|
-
return expr;
|
|
9145
|
+
return transform(expr, flags);
|
|
8947
9146
|
}
|
|
8948
9147
|
/**
|
|
8949
9148
|
* Transform all `Expression`s in the AST of `stmt` with the `transform` function.
|
|
@@ -9144,10 +9343,12 @@ class OpList {
|
|
|
9144
9343
|
* Insert `op` before `before`.
|
|
9145
9344
|
*/
|
|
9146
9345
|
static insertBefore(op, before) {
|
|
9147
|
-
OpList.
|
|
9346
|
+
OpList.assertIsOwned(before);
|
|
9347
|
+
if (before.prev === null) {
|
|
9348
|
+
throw new Error(`AssertionError: illegal operation on list start`);
|
|
9349
|
+
}
|
|
9148
9350
|
OpList.assertIsNotEnd(op);
|
|
9149
9351
|
OpList.assertIsUnowned(op);
|
|
9150
|
-
OpList.assertIsOwned(before);
|
|
9151
9352
|
op.debugListId = before.debugListId;
|
|
9152
9353
|
// Just in case.
|
|
9153
9354
|
op.prev = null;
|
|
@@ -9287,6 +9488,15 @@ function createListenerOp(target, name, tag) {
|
|
|
9287
9488
|
...TRAIT_USES_SLOT_INDEX,
|
|
9288
9489
|
};
|
|
9289
9490
|
}
|
|
9491
|
+
function createPipeOp(xref, name) {
|
|
9492
|
+
return {
|
|
9493
|
+
kind: OpKind.Pipe,
|
|
9494
|
+
xref,
|
|
9495
|
+
name,
|
|
9496
|
+
...NEW_OP,
|
|
9497
|
+
...TRAIT_CONSUMES_SLOT,
|
|
9498
|
+
};
|
|
9499
|
+
}
|
|
9290
9500
|
|
|
9291
9501
|
/**
|
|
9292
9502
|
* Create an `InterpolationTextOp`.
|
|
@@ -9316,6 +9526,21 @@ function createPropertyOp(xref, name, expression) {
|
|
|
9316
9526
|
...NEW_OP,
|
|
9317
9527
|
};
|
|
9318
9528
|
}
|
|
9529
|
+
/**
|
|
9530
|
+
* Create a `InterpolateProperty`.
|
|
9531
|
+
*/
|
|
9532
|
+
function createInterpolatePropertyOp(xref, name, strings, expressions) {
|
|
9533
|
+
return {
|
|
9534
|
+
kind: OpKind.InterpolateProperty,
|
|
9535
|
+
target: xref,
|
|
9536
|
+
name,
|
|
9537
|
+
strings,
|
|
9538
|
+
expressions,
|
|
9539
|
+
...TRAIT_DEPENDS_ON_SLOT_CONTEXT,
|
|
9540
|
+
...TRAIT_CONSUMES_VARS,
|
|
9541
|
+
...NEW_OP,
|
|
9542
|
+
};
|
|
9543
|
+
}
|
|
9319
9544
|
/**
|
|
9320
9545
|
* Create an `AdvanceOp`.
|
|
9321
9546
|
*/
|
|
@@ -9500,6 +9725,12 @@ function listener(name, handlerFn) {
|
|
|
9500
9725
|
handlerFn,
|
|
9501
9726
|
]);
|
|
9502
9727
|
}
|
|
9728
|
+
function pipe(slot, name) {
|
|
9729
|
+
return call(Identifiers.pipe, [
|
|
9730
|
+
literal(slot),
|
|
9731
|
+
literal(name),
|
|
9732
|
+
]);
|
|
9733
|
+
}
|
|
9503
9734
|
function advance(delta) {
|
|
9504
9735
|
return call(Identifiers.advance, [
|
|
9505
9736
|
literal(delta),
|
|
@@ -9539,6 +9770,30 @@ function property(name, expression) {
|
|
|
9539
9770
|
expression,
|
|
9540
9771
|
]);
|
|
9541
9772
|
}
|
|
9773
|
+
const PIPE_BINDINGS = [
|
|
9774
|
+
Identifiers.pipeBind1,
|
|
9775
|
+
Identifiers.pipeBind2,
|
|
9776
|
+
Identifiers.pipeBind3,
|
|
9777
|
+
Identifiers.pipeBind4,
|
|
9778
|
+
];
|
|
9779
|
+
function pipeBind(slot, varOffset, args) {
|
|
9780
|
+
if (args.length < 1 || args.length > PIPE_BINDINGS.length) {
|
|
9781
|
+
throw new Error(`pipeBind() argument count out of bounds`);
|
|
9782
|
+
}
|
|
9783
|
+
const instruction = PIPE_BINDINGS[args.length - 1];
|
|
9784
|
+
return importExpr(instruction).callFn([
|
|
9785
|
+
literal(slot),
|
|
9786
|
+
literal(varOffset),
|
|
9787
|
+
...args,
|
|
9788
|
+
]);
|
|
9789
|
+
}
|
|
9790
|
+
function pipeBindV(slot, varOffset, args) {
|
|
9791
|
+
return importExpr(Identifiers.pipeBindV).callFn([
|
|
9792
|
+
literal(slot),
|
|
9793
|
+
literal(varOffset),
|
|
9794
|
+
args,
|
|
9795
|
+
]);
|
|
9796
|
+
}
|
|
9542
9797
|
function textInterpolate(strings, expressions) {
|
|
9543
9798
|
if (strings.length < 1 || expressions.length !== strings.length - 1) {
|
|
9544
9799
|
throw new Error(`AssertionError: expected specific shape of args for strings/expressions in interpolation`);
|
|
@@ -9555,7 +9810,31 @@ function textInterpolate(strings, expressions) {
|
|
|
9555
9810
|
// idx points at the last string.
|
|
9556
9811
|
interpolationArgs.push(literal(strings[idx]));
|
|
9557
9812
|
}
|
|
9558
|
-
return
|
|
9813
|
+
return callVariadicInstruction(TEXT_INTERPOLATE_CONFIG, [], interpolationArgs);
|
|
9814
|
+
}
|
|
9815
|
+
function propertyInterpolate(name, strings, expressions) {
|
|
9816
|
+
if (strings.length < 1 || expressions.length !== strings.length - 1) {
|
|
9817
|
+
throw new Error(`AssertionError: expected specific shape of args for strings/expressions in interpolation`);
|
|
9818
|
+
}
|
|
9819
|
+
const interpolationArgs = [];
|
|
9820
|
+
if (expressions.length === 1 && strings[0] === '' && strings[1] === '') {
|
|
9821
|
+
interpolationArgs.push(expressions[0]);
|
|
9822
|
+
}
|
|
9823
|
+
else {
|
|
9824
|
+
let idx;
|
|
9825
|
+
for (idx = 0; idx < expressions.length; idx++) {
|
|
9826
|
+
interpolationArgs.push(literal(strings[idx]), expressions[idx]);
|
|
9827
|
+
}
|
|
9828
|
+
// idx points at the last string.
|
|
9829
|
+
interpolationArgs.push(literal(strings[idx]));
|
|
9830
|
+
}
|
|
9831
|
+
return callVariadicInstruction(PROPERTY_INTERPOLATE_CONFIG, [literal(name)], interpolationArgs);
|
|
9832
|
+
}
|
|
9833
|
+
function pureFunction(varOffset, fn, args) {
|
|
9834
|
+
return callVariadicInstructionExpr(PURE_FUNCTION_CONFIG, [
|
|
9835
|
+
literal(varOffset),
|
|
9836
|
+
fn,
|
|
9837
|
+
], args);
|
|
9559
9838
|
}
|
|
9560
9839
|
function call(instruction, args) {
|
|
9561
9840
|
return createStatementOp(importExpr(instruction).callFn(args).toStmt());
|
|
@@ -9576,21 +9855,68 @@ const TEXT_INTERPOLATE_CONFIG = {
|
|
|
9576
9855
|
Identifiers.textInterpolate8,
|
|
9577
9856
|
],
|
|
9578
9857
|
variable: Identifiers.textInterpolateV,
|
|
9858
|
+
mapping: n => {
|
|
9859
|
+
if (n % 2 === 0) {
|
|
9860
|
+
throw new Error(`Expected odd number of arguments`);
|
|
9861
|
+
}
|
|
9862
|
+
return (n - 1) / 2;
|
|
9863
|
+
},
|
|
9579
9864
|
};
|
|
9580
|
-
|
|
9581
|
-
|
|
9582
|
-
|
|
9583
|
-
|
|
9584
|
-
|
|
9865
|
+
/**
|
|
9866
|
+
* `InterpolationConfig` for the `propertyInterpolate` instruction.
|
|
9867
|
+
*/
|
|
9868
|
+
const PROPERTY_INTERPOLATE_CONFIG = {
|
|
9869
|
+
constant: [
|
|
9870
|
+
Identifiers.propertyInterpolate,
|
|
9871
|
+
Identifiers.propertyInterpolate1,
|
|
9872
|
+
Identifiers.propertyInterpolate2,
|
|
9873
|
+
Identifiers.propertyInterpolate3,
|
|
9874
|
+
Identifiers.propertyInterpolate4,
|
|
9875
|
+
Identifiers.propertyInterpolate5,
|
|
9876
|
+
Identifiers.propertyInterpolate6,
|
|
9877
|
+
Identifiers.propertyInterpolate7,
|
|
9878
|
+
Identifiers.propertyInterpolate8,
|
|
9879
|
+
],
|
|
9880
|
+
variable: Identifiers.propertyInterpolateV,
|
|
9881
|
+
mapping: n => {
|
|
9882
|
+
if (n % 2 === 0) {
|
|
9883
|
+
throw new Error(`Expected odd number of arguments`);
|
|
9884
|
+
}
|
|
9885
|
+
return (n - 1) / 2;
|
|
9886
|
+
},
|
|
9887
|
+
};
|
|
9888
|
+
const PURE_FUNCTION_CONFIG = {
|
|
9889
|
+
constant: [
|
|
9890
|
+
Identifiers.pureFunction0,
|
|
9891
|
+
Identifiers.pureFunction1,
|
|
9892
|
+
Identifiers.pureFunction2,
|
|
9893
|
+
Identifiers.pureFunction3,
|
|
9894
|
+
Identifiers.pureFunction4,
|
|
9895
|
+
Identifiers.pureFunction5,
|
|
9896
|
+
Identifiers.pureFunction6,
|
|
9897
|
+
Identifiers.pureFunction7,
|
|
9898
|
+
Identifiers.pureFunction8,
|
|
9899
|
+
],
|
|
9900
|
+
variable: Identifiers.pureFunctionV,
|
|
9901
|
+
mapping: n => n,
|
|
9902
|
+
};
|
|
9903
|
+
function callVariadicInstructionExpr(config, baseArgs, interpolationArgs) {
|
|
9904
|
+
const n = config.mapping(interpolationArgs.length);
|
|
9585
9905
|
if (n < config.constant.length) {
|
|
9586
9906
|
// Constant calling pattern.
|
|
9587
|
-
return
|
|
9907
|
+
return importExpr(config.constant[n]).callFn([...baseArgs, ...interpolationArgs]);
|
|
9588
9908
|
}
|
|
9589
|
-
else {
|
|
9909
|
+
else if (config.variable !== null) {
|
|
9590
9910
|
// Variable calling pattern.
|
|
9591
|
-
return
|
|
9911
|
+
return importExpr(config.variable).callFn([...baseArgs, literalArr(interpolationArgs)]);
|
|
9912
|
+
}
|
|
9913
|
+
else {
|
|
9914
|
+
throw new Error(`AssertionError: unable to call variadic function`);
|
|
9592
9915
|
}
|
|
9593
9916
|
}
|
|
9917
|
+
function callVariadicInstruction(config, baseArgs, interpolationArgs) {
|
|
9918
|
+
return createStatementOp(callVariadicInstructionExpr(config, baseArgs, interpolationArgs).toStmt());
|
|
9919
|
+
}
|
|
9594
9920
|
|
|
9595
9921
|
/**
|
|
9596
9922
|
* Compiles semantic operations across all views and generates output `o.Statement`s with actual
|
|
@@ -9635,6 +9961,9 @@ function reifyCreateOperations(view, ops) {
|
|
|
9635
9961
|
const childView = view.tpl.views.get(op.xref);
|
|
9636
9962
|
OpList.replace(op, template(op.slot, variable(childView.fnName), childView.decls, childView.vars, op.tag, op.attributes));
|
|
9637
9963
|
break;
|
|
9964
|
+
case OpKind.Pipe:
|
|
9965
|
+
OpList.replace(op, pipe(op.slot, op.name));
|
|
9966
|
+
break;
|
|
9638
9967
|
case OpKind.Listener:
|
|
9639
9968
|
const listenerFn = reifyListenerHandler(view, op.handlerFnName, op.handlerOps);
|
|
9640
9969
|
OpList.replace(op, listener(op.name, listenerFn));
|
|
@@ -9663,6 +9992,9 @@ function reifyUpdateOperations(_view, ops) {
|
|
|
9663
9992
|
case OpKind.Property:
|
|
9664
9993
|
OpList.replace(op, property(op.name, op.expression));
|
|
9665
9994
|
break;
|
|
9995
|
+
case OpKind.InterpolateProperty:
|
|
9996
|
+
OpList.replace(op, propertyInterpolate(op.name, op.strings, op.expressions));
|
|
9997
|
+
break;
|
|
9666
9998
|
case OpKind.InterpolateText:
|
|
9667
9999
|
OpList.replace(op, textInterpolate(op.strings, op.expressions));
|
|
9668
10000
|
break;
|
|
@@ -9681,6 +10013,9 @@ function reifyUpdateOperations(_view, ops) {
|
|
|
9681
10013
|
}
|
|
9682
10014
|
}
|
|
9683
10015
|
function reifyIrExpression(expr) {
|
|
10016
|
+
if (!isIrExpression(expr)) {
|
|
10017
|
+
return expr;
|
|
10018
|
+
}
|
|
9684
10019
|
switch (expr.kind) {
|
|
9685
10020
|
case ExpressionKind.NextContext:
|
|
9686
10021
|
return nextContext(expr.steps);
|
|
@@ -9702,6 +10037,17 @@ function reifyIrExpression(expr) {
|
|
|
9702
10037
|
throw new Error(`Read of unnamed variable ${expr.xref}`);
|
|
9703
10038
|
}
|
|
9704
10039
|
return variable(expr.name);
|
|
10040
|
+
case ExpressionKind.PureFunctionExpr:
|
|
10041
|
+
if (expr.fn === null) {
|
|
10042
|
+
throw new Error(`AssertionError: expected PureFunctions to have been extracted`);
|
|
10043
|
+
}
|
|
10044
|
+
return pureFunction(expr.varOffset, expr.fn, expr.args);
|
|
10045
|
+
case ExpressionKind.PureFunctionParameterExpr:
|
|
10046
|
+
throw new Error(`AssertionError: expected PureFunctionParameterExpr to have been extracted`);
|
|
10047
|
+
case ExpressionKind.PipeBinding:
|
|
10048
|
+
return pipeBind(expr.slot, expr.varOffset, expr.args);
|
|
10049
|
+
case ExpressionKind.PipeBindingVariadic:
|
|
10050
|
+
return pipeBindV(expr.slot, expr.varOffset, expr.args);
|
|
9705
10051
|
default:
|
|
9706
10052
|
throw new Error(`AssertionError: Unsupported reification of ir.Expression kind: ${ExpressionKind[expr.kind]}`);
|
|
9707
10053
|
}
|
|
@@ -9805,6 +10151,9 @@ function phaseSlotAllocation(cpl) {
|
|
|
9805
10151
|
}
|
|
9806
10152
|
// Process all `ir.Expression`s within this view, and look for `usesSlotIndexExprTrait`.
|
|
9807
10153
|
visitExpressionsInOp(op, expr => {
|
|
10154
|
+
if (!isIrExpression(expr)) {
|
|
10155
|
+
return;
|
|
10156
|
+
}
|
|
9808
10157
|
if (!hasUsesSlotIndexTrait(expr) || expr.slot !== null) {
|
|
9809
10158
|
return;
|
|
9810
10159
|
}
|
|
@@ -9835,6 +10184,13 @@ function phaseVarCounting(cpl) {
|
|
|
9835
10184
|
varCount += varsUsedByOp(op);
|
|
9836
10185
|
}
|
|
9837
10186
|
visitExpressionsInOp(op, expr => {
|
|
10187
|
+
if (!isIrExpression(expr)) {
|
|
10188
|
+
return;
|
|
10189
|
+
}
|
|
10190
|
+
// Some expressions require knowledge of the number of variable slots consumed.
|
|
10191
|
+
if (hasUsesVarOffsetTrait(expr)) {
|
|
10192
|
+
expr.varOffset = varCount;
|
|
10193
|
+
}
|
|
9838
10194
|
if (hasConsumesVarsTrait(expr)) {
|
|
9839
10195
|
varCount += varsUsedByIrExpression(expr);
|
|
9840
10196
|
}
|
|
@@ -9866,12 +10222,25 @@ function varsUsedByOp(op) {
|
|
|
9866
10222
|
case OpKind.InterpolateText:
|
|
9867
10223
|
// `ir.InterpolateTextOp`s use a variable slot for each dynamic expression.
|
|
9868
10224
|
return op.expressions.length;
|
|
10225
|
+
case OpKind.InterpolateProperty:
|
|
10226
|
+
// `ir.InterpolatePropertyOp`s use a variable slot for each dynamic expression, plus one for
|
|
10227
|
+
// the result.
|
|
10228
|
+
return 1 + op.expressions.length;
|
|
9869
10229
|
default:
|
|
9870
10230
|
throw new Error(`Unhandled op: ${OpKind[op.kind]}`);
|
|
9871
10231
|
}
|
|
9872
10232
|
}
|
|
9873
10233
|
function varsUsedByIrExpression(expr) {
|
|
9874
|
-
|
|
10234
|
+
switch (expr.kind) {
|
|
10235
|
+
case ExpressionKind.PureFunctionExpr:
|
|
10236
|
+
return 1 + expr.args.length;
|
|
10237
|
+
case ExpressionKind.PipeBinding:
|
|
10238
|
+
return 1 + expr.args.length;
|
|
10239
|
+
case ExpressionKind.PipeBindingVariadic:
|
|
10240
|
+
return 1 + expr.numArgs;
|
|
10241
|
+
default:
|
|
10242
|
+
throw new Error(`AssertionError: unhandled ConsumesVarsTrait expression ${expr.constructor.name}`);
|
|
10243
|
+
}
|
|
9875
10244
|
}
|
|
9876
10245
|
|
|
9877
10246
|
/**
|
|
@@ -10455,6 +10824,9 @@ function collectOpInfo(op) {
|
|
|
10455
10824
|
let fences = Fence.None;
|
|
10456
10825
|
const variablesUsed = new Set();
|
|
10457
10826
|
visitExpressionsInOp(op, expr => {
|
|
10827
|
+
if (!isIrExpression(expr)) {
|
|
10828
|
+
return;
|
|
10829
|
+
}
|
|
10458
10830
|
switch (expr.kind) {
|
|
10459
10831
|
case ExpressionKind.ReadVariable:
|
|
10460
10832
|
variablesUsed.add(expr.xref);
|
|
@@ -10471,6 +10843,9 @@ function collectOpInfo(op) {
|
|
|
10471
10843
|
*/
|
|
10472
10844
|
function countVariableUsages(op, varUsages, varRemoteUsage) {
|
|
10473
10845
|
visitExpressionsInOp(op, (expr, flags) => {
|
|
10846
|
+
if (!isIrExpression(expr)) {
|
|
10847
|
+
return;
|
|
10848
|
+
}
|
|
10474
10849
|
if (expr.kind !== ExpressionKind.ReadVariable) {
|
|
10475
10850
|
return;
|
|
10476
10851
|
}
|
|
@@ -10490,6 +10865,9 @@ function countVariableUsages(op, varUsages, varRemoteUsage) {
|
|
|
10490
10865
|
*/
|
|
10491
10866
|
function uncountVariableUsages(op, varUsages) {
|
|
10492
10867
|
visitExpressionsInOp(op, expr => {
|
|
10868
|
+
if (!isIrExpression(expr)) {
|
|
10869
|
+
return;
|
|
10870
|
+
}
|
|
10493
10871
|
if (expr.kind !== ExpressionKind.ReadVariable) {
|
|
10494
10872
|
return;
|
|
10495
10873
|
}
|
|
@@ -10539,6 +10917,9 @@ function tryInlineVariableInitializer(id, initializer, target, declFences) {
|
|
|
10539
10917
|
let inlined = false;
|
|
10540
10918
|
let inliningAllowed = true;
|
|
10541
10919
|
transformExpressionsInOp(target, (expr, flags) => {
|
|
10920
|
+
if (!isIrExpression(expr)) {
|
|
10921
|
+
return expr;
|
|
10922
|
+
}
|
|
10542
10923
|
if (inlined || !inliningAllowed) {
|
|
10543
10924
|
// Either the inlining has already succeeded, or we've passed a fence that disallows inlining
|
|
10544
10925
|
// at this point, so don't try.
|
|
@@ -10693,6 +11074,9 @@ function mergeNextContextsInOps(ops) {
|
|
|
10693
11074
|
let tryToMerge = true;
|
|
10694
11075
|
for (let candidate = op.next; candidate.kind !== OpKind.ListEnd && tryToMerge; candidate = candidate.next) {
|
|
10695
11076
|
visitExpressionsInOp(candidate, (expr, flags) => {
|
|
11077
|
+
if (!isIrExpression(expr)) {
|
|
11078
|
+
return expr;
|
|
11079
|
+
}
|
|
10696
11080
|
if (!tryToMerge) {
|
|
10697
11081
|
// Either we've already merged, or failed to merge.
|
|
10698
11082
|
return;
|
|
@@ -10777,11 +11161,205 @@ function phaseSaveRestoreView(cpl) {
|
|
|
10777
11161
|
}
|
|
10778
11162
|
}
|
|
10779
11163
|
|
|
11164
|
+
function phasePureFunctionExtraction(cpl) {
|
|
11165
|
+
for (const view of cpl.views.values()) {
|
|
11166
|
+
for (const op of view.ops()) {
|
|
11167
|
+
visitExpressionsInOp(op, expr => {
|
|
11168
|
+
if (!(expr instanceof PureFunctionExpr) || expr.body === null) {
|
|
11169
|
+
return;
|
|
11170
|
+
}
|
|
11171
|
+
const constantDef = new PureFunctionConstant(expr.args.length);
|
|
11172
|
+
expr.fn = cpl.pool.getSharedConstant(constantDef, expr.body);
|
|
11173
|
+
expr.body = null;
|
|
11174
|
+
});
|
|
11175
|
+
}
|
|
11176
|
+
}
|
|
11177
|
+
}
|
|
11178
|
+
class PureFunctionConstant extends GenericKeyFn {
|
|
11179
|
+
constructor(numArgs) {
|
|
11180
|
+
super();
|
|
11181
|
+
this.numArgs = numArgs;
|
|
11182
|
+
}
|
|
11183
|
+
keyOf(expr) {
|
|
11184
|
+
if (expr instanceof PureFunctionParameterExpr) {
|
|
11185
|
+
return `param(${expr.index})`;
|
|
11186
|
+
}
|
|
11187
|
+
else {
|
|
11188
|
+
return super.keyOf(expr);
|
|
11189
|
+
}
|
|
11190
|
+
}
|
|
11191
|
+
toSharedConstantDeclaration(declName, keyExpr) {
|
|
11192
|
+
const fnParams = [];
|
|
11193
|
+
for (let idx = 0; idx < this.numArgs; idx++) {
|
|
11194
|
+
fnParams.push(new FnParam('_p' + idx));
|
|
11195
|
+
}
|
|
11196
|
+
// We will never visit `ir.PureFunctionParameterExpr`s that don't belong to us, because this
|
|
11197
|
+
// transform runs inside another visitor which will visit nested pure functions before this one.
|
|
11198
|
+
const returnExpr = transformExpressionsInExpression(keyExpr, expr => {
|
|
11199
|
+
if (!(expr instanceof PureFunctionParameterExpr)) {
|
|
11200
|
+
return expr;
|
|
11201
|
+
}
|
|
11202
|
+
return variable('_p' + expr.index);
|
|
11203
|
+
}, VisitorContextFlag.None);
|
|
11204
|
+
return new DeclareFunctionStmt(declName, fnParams, [new ReturnStatement(returnExpr)]);
|
|
11205
|
+
}
|
|
11206
|
+
}
|
|
11207
|
+
|
|
11208
|
+
function phasePipeCreation(cpl) {
|
|
11209
|
+
for (const view of cpl.views.values()) {
|
|
11210
|
+
processPipeBindingsInView(view);
|
|
11211
|
+
}
|
|
11212
|
+
}
|
|
11213
|
+
function processPipeBindingsInView(view) {
|
|
11214
|
+
for (const updateOp of view.update) {
|
|
11215
|
+
visitExpressionsInOp(updateOp, (expr, flags) => {
|
|
11216
|
+
if (!isIrExpression(expr)) {
|
|
11217
|
+
return;
|
|
11218
|
+
}
|
|
11219
|
+
if (expr.kind !== ExpressionKind.PipeBinding) {
|
|
11220
|
+
return;
|
|
11221
|
+
}
|
|
11222
|
+
if (flags & VisitorContextFlag.InChildOperation) {
|
|
11223
|
+
throw new Error(`AssertionError: pipe bindings should not appear in child expressions`);
|
|
11224
|
+
}
|
|
11225
|
+
if (!hasDependsOnSlotContextTrait(updateOp)) {
|
|
11226
|
+
throw new Error(`AssertionError: pipe binding associated with non-slot operation ${OpKind[updateOp.kind]}`);
|
|
11227
|
+
}
|
|
11228
|
+
addPipeToCreationBlock(view, updateOp.target, expr);
|
|
11229
|
+
});
|
|
11230
|
+
}
|
|
11231
|
+
}
|
|
11232
|
+
function addPipeToCreationBlock(view, afterTargetXref, binding) {
|
|
11233
|
+
// Find the appropriate point to insert the Pipe creation operation.
|
|
11234
|
+
// We're looking for `afterTargetXref` (and also want to insert after any other pipe operations
|
|
11235
|
+
// which might be beyond it).
|
|
11236
|
+
for (let op = view.create.head.next; op.kind !== OpKind.ListEnd; op = op.next) {
|
|
11237
|
+
if (!hasConsumesSlotTrait(op)) {
|
|
11238
|
+
continue;
|
|
11239
|
+
}
|
|
11240
|
+
if (op.xref !== afterTargetXref) {
|
|
11241
|
+
continue;
|
|
11242
|
+
}
|
|
11243
|
+
// We've found a tentative insertion point; however, we also want to skip past any _other_ pipe
|
|
11244
|
+
// operations present.
|
|
11245
|
+
while (op.next.kind === OpKind.Pipe) {
|
|
11246
|
+
op = op.next;
|
|
11247
|
+
}
|
|
11248
|
+
const pipe = createPipeOp(binding.target, binding.name);
|
|
11249
|
+
OpList.insertBefore(pipe, op.next);
|
|
11250
|
+
// This completes adding the pipe to the creation block.
|
|
11251
|
+
return;
|
|
11252
|
+
}
|
|
11253
|
+
// At this point, we've failed to add the pipe to the creation block.
|
|
11254
|
+
throw new Error(`AssertionError: unable to find insertion point for pipe ${binding.name}`);
|
|
11255
|
+
}
|
|
11256
|
+
|
|
11257
|
+
function phasePipeVariadic(cpl) {
|
|
11258
|
+
for (const view of cpl.views.values()) {
|
|
11259
|
+
for (const op of view.update) {
|
|
11260
|
+
transformExpressionsInOp(op, expr => {
|
|
11261
|
+
if (!(expr instanceof PipeBindingExpr)) {
|
|
11262
|
+
return expr;
|
|
11263
|
+
}
|
|
11264
|
+
// Pipes are variadic if they have more than 4 arguments.
|
|
11265
|
+
if (expr.args.length <= 4) {
|
|
11266
|
+
return expr;
|
|
11267
|
+
}
|
|
11268
|
+
return new PipeBindingVariadicExpr(expr.target, expr.name, literalArr(expr.args), expr.args.length);
|
|
11269
|
+
}, VisitorContextFlag.None);
|
|
11270
|
+
}
|
|
11271
|
+
}
|
|
11272
|
+
}
|
|
11273
|
+
|
|
11274
|
+
function phasePureLiteralStructures(cpl) {
|
|
11275
|
+
for (const view of cpl.views.values()) {
|
|
11276
|
+
for (const op of view.update) {
|
|
11277
|
+
transformExpressionsInOp(op, (expr, flags) => {
|
|
11278
|
+
if (flags & VisitorContextFlag.InChildOperation) {
|
|
11279
|
+
return expr;
|
|
11280
|
+
}
|
|
11281
|
+
if (expr instanceof LiteralArrayExpr) {
|
|
11282
|
+
return transformLiteralArray(expr);
|
|
11283
|
+
}
|
|
11284
|
+
else if (expr instanceof LiteralMapExpr) {
|
|
11285
|
+
return transformLiteralMap(expr);
|
|
11286
|
+
}
|
|
11287
|
+
return expr;
|
|
11288
|
+
}, VisitorContextFlag.None);
|
|
11289
|
+
}
|
|
11290
|
+
}
|
|
11291
|
+
}
|
|
11292
|
+
function transformLiteralArray(expr) {
|
|
11293
|
+
const derivedEntries = [];
|
|
11294
|
+
const nonConstantArgs = [];
|
|
11295
|
+
for (const entry of expr.entries) {
|
|
11296
|
+
if (entry.isConstant()) {
|
|
11297
|
+
derivedEntries.push(entry);
|
|
11298
|
+
}
|
|
11299
|
+
else {
|
|
11300
|
+
const idx = nonConstantArgs.length;
|
|
11301
|
+
nonConstantArgs.push(entry);
|
|
11302
|
+
derivedEntries.push(new PureFunctionParameterExpr(idx));
|
|
11303
|
+
}
|
|
11304
|
+
}
|
|
11305
|
+
return new PureFunctionExpr(literalArr(derivedEntries), nonConstantArgs);
|
|
11306
|
+
}
|
|
11307
|
+
function transformLiteralMap(expr) {
|
|
11308
|
+
let derivedEntries = [];
|
|
11309
|
+
const nonConstantArgs = [];
|
|
11310
|
+
for (const entry of expr.entries) {
|
|
11311
|
+
if (entry.value.isConstant()) {
|
|
11312
|
+
derivedEntries.push(entry);
|
|
11313
|
+
}
|
|
11314
|
+
else {
|
|
11315
|
+
const idx = nonConstantArgs.length;
|
|
11316
|
+
nonConstantArgs.push(entry.value);
|
|
11317
|
+
derivedEntries.push(new LiteralMapEntry(entry.key, new PureFunctionParameterExpr(idx), entry.quoted));
|
|
11318
|
+
}
|
|
11319
|
+
}
|
|
11320
|
+
return new PureFunctionExpr(literalMap(derivedEntries), nonConstantArgs);
|
|
11321
|
+
}
|
|
11322
|
+
|
|
11323
|
+
function phaseAlignPipeVariadicVarOffset(cpl) {
|
|
11324
|
+
for (const view of cpl.views.values()) {
|
|
11325
|
+
for (const op of view.update) {
|
|
11326
|
+
visitExpressionsInOp(op, expr => {
|
|
11327
|
+
if (!(expr instanceof PipeBindingVariadicExpr)) {
|
|
11328
|
+
return expr;
|
|
11329
|
+
}
|
|
11330
|
+
if (!(expr.args instanceof PureFunctionExpr)) {
|
|
11331
|
+
return expr;
|
|
11332
|
+
}
|
|
11333
|
+
if (expr.varOffset === null || expr.args.varOffset === null) {
|
|
11334
|
+
throw new Error(`Must run after variable counting`);
|
|
11335
|
+
}
|
|
11336
|
+
// The structure of this variadic pipe expression is:
|
|
11337
|
+
// PipeBindingVariadic(#, Y, PureFunction(X, ...ARGS))
|
|
11338
|
+
// Where X and Y are the slot offsets for the variables used by these operations, and Y > X.
|
|
11339
|
+
// In `TemplateDefinitionBuilder` the PipeBindingVariadic variable slots are allocated
|
|
11340
|
+
// before the PureFunction slots, which is unusually out-of-order.
|
|
11341
|
+
//
|
|
11342
|
+
// To maintain identical output for the tests in question, we adjust the variable offsets of
|
|
11343
|
+
// these two calls to emulate TDB's behavior. This is not perfect, because the ARGS of the
|
|
11344
|
+
// PureFunction call may also allocate slots which by TDB's ordering would come after X, and
|
|
11345
|
+
// we don't account for that. Still, this should be enough to pass the existing pipe tests.
|
|
11346
|
+
// Put the PipeBindingVariadic vars where the PureFunction vars were previously allocated.
|
|
11347
|
+
expr.varOffset = expr.args.varOffset;
|
|
11348
|
+
// Put the PureFunction vars following the PipeBindingVariadic vars.
|
|
11349
|
+
expr.args.varOffset = expr.varOffset + varsUsedByIrExpression(expr);
|
|
11350
|
+
});
|
|
11351
|
+
}
|
|
11352
|
+
}
|
|
11353
|
+
}
|
|
11354
|
+
|
|
10780
11355
|
/**
|
|
10781
11356
|
* Run all transformation phases in the correct order against a `ComponentCompilation`. After this
|
|
10782
11357
|
* processing, the compilation should be in a state where it can be emitted via `emitTemplateFn`.s
|
|
10783
11358
|
*/
|
|
10784
11359
|
function transformTemplate(cpl) {
|
|
11360
|
+
phasePipeCreation(cpl);
|
|
11361
|
+
phasePipeVariadic(cpl);
|
|
11362
|
+
phasePureLiteralStructures(cpl);
|
|
10785
11363
|
phaseGenerateVariables(cpl);
|
|
10786
11364
|
phaseSaveRestoreView(cpl);
|
|
10787
11365
|
phaseResolveNames(cpl);
|
|
@@ -10796,6 +11374,8 @@ function transformTemplate(cpl) {
|
|
|
10796
11374
|
phaseMergeNextContext(cpl);
|
|
10797
11375
|
phaseNgContainer(cpl);
|
|
10798
11376
|
phaseEmptyElements(cpl);
|
|
11377
|
+
phasePureFunctionExtraction(cpl);
|
|
11378
|
+
phaseAlignPipeVariadicVarOffset(cpl);
|
|
10799
11379
|
phaseReify(cpl);
|
|
10800
11380
|
phaseChaining(cpl);
|
|
10801
11381
|
}
|
|
@@ -10866,8 +11446,9 @@ function maybeGenerateRfBlock(flag, statements) {
|
|
|
10866
11446
|
* embedded views or host bindings.
|
|
10867
11447
|
*/
|
|
10868
11448
|
class ComponentCompilation {
|
|
10869
|
-
constructor(componentName) {
|
|
11449
|
+
constructor(componentName, pool) {
|
|
10870
11450
|
this.componentName = componentName;
|
|
11451
|
+
this.pool = pool;
|
|
10871
11452
|
/**
|
|
10872
11453
|
* Tracks the next `ir.XrefId` which can be assigned as template structures are ingested.
|
|
10873
11454
|
*/
|
|
@@ -10999,8 +11580,8 @@ const BINARY_OPERATORS = new Map([
|
|
|
10999
11580
|
* Process a template AST and convert it into a `ComponentCompilation` in the intermediate
|
|
11000
11581
|
* representation.
|
|
11001
11582
|
*/
|
|
11002
|
-
function ingest(componentName, template) {
|
|
11003
|
-
const cpl = new ComponentCompilation(componentName);
|
|
11583
|
+
function ingest(componentName, template, constantPool) {
|
|
11584
|
+
const cpl = new ComponentCompilation(componentName, constantPool);
|
|
11004
11585
|
ingestNodes(cpl.root, template);
|
|
11005
11586
|
return cpl;
|
|
11006
11587
|
}
|
|
@@ -11095,6 +11676,12 @@ function convertAst(ast, cpl) {
|
|
|
11095
11676
|
return new ReadPropExpr(convertAst(ast.receiver, cpl), ast.name);
|
|
11096
11677
|
}
|
|
11097
11678
|
}
|
|
11679
|
+
else if (ast instanceof PropertyWrite) {
|
|
11680
|
+
return new WritePropExpr(convertAst(ast.receiver, cpl), ast.name, convertAst(ast.value, cpl));
|
|
11681
|
+
}
|
|
11682
|
+
else if (ast instanceof KeyedWrite) {
|
|
11683
|
+
return new WriteKeyExpr(convertAst(ast.receiver, cpl), convertAst(ast.key, cpl), convertAst(ast.value, cpl));
|
|
11684
|
+
}
|
|
11098
11685
|
else if (ast instanceof Call) {
|
|
11099
11686
|
if (ast.receiver instanceof ImplicitReceiver) {
|
|
11100
11687
|
throw new Error(`Unexpected ImplicitReceiver`);
|
|
@@ -11122,6 +11709,25 @@ function convertAst(ast, cpl) {
|
|
|
11122
11709
|
else if (ast instanceof Chain) {
|
|
11123
11710
|
throw new Error(`AssertionError: Chain in unknown context`);
|
|
11124
11711
|
}
|
|
11712
|
+
else if (ast instanceof LiteralMap) {
|
|
11713
|
+
const entries = ast.keys.map((key, idx) => {
|
|
11714
|
+
const value = ast.values[idx];
|
|
11715
|
+
return new LiteralMapEntry(key.key, convertAst(value, cpl), key.quoted);
|
|
11716
|
+
});
|
|
11717
|
+
return new LiteralMapExpr(entries);
|
|
11718
|
+
}
|
|
11719
|
+
else if (ast instanceof LiteralArray) {
|
|
11720
|
+
return new LiteralArrayExpr(ast.expressions.map(expr => convertAst(expr, cpl)));
|
|
11721
|
+
}
|
|
11722
|
+
else if (ast instanceof Conditional) {
|
|
11723
|
+
return new ConditionalExpr(convertAst(ast.condition, cpl), convertAst(ast.trueExp, cpl), convertAst(ast.falseExp, cpl));
|
|
11724
|
+
}
|
|
11725
|
+
else if (ast instanceof BindingPipe) {
|
|
11726
|
+
return new PipeBindingExpr(cpl.allocateXrefId(), ast.name, [
|
|
11727
|
+
convertAst(ast.exp, cpl),
|
|
11728
|
+
...ast.args.map(arg => convertAst(arg, cpl)),
|
|
11729
|
+
]);
|
|
11730
|
+
}
|
|
11125
11731
|
else {
|
|
11126
11732
|
throw new Error(`Unhandled expression type: ${ast.constructor.name}`);
|
|
11127
11733
|
}
|
|
@@ -11154,19 +11760,16 @@ function ingestAttributes(op, element) {
|
|
|
11154
11760
|
*/
|
|
11155
11761
|
function ingestBindings(view, op, element) {
|
|
11156
11762
|
if (element instanceof Template) {
|
|
11157
|
-
|
|
11158
|
-
|
|
11159
|
-
// <item-cmp *ngFor="let item of items" [item]="item">
|
|
11160
|
-
for (const input of [...element.templateAttrs, ...element.inputs]) {
|
|
11161
|
-
if (!(input instanceof BoundAttribute)) {
|
|
11763
|
+
for (const attr of [...element.templateAttrs, ...element.inputs]) {
|
|
11764
|
+
if (!(attr instanceof BoundAttribute)) {
|
|
11162
11765
|
continue;
|
|
11163
11766
|
}
|
|
11164
|
-
view
|
|
11767
|
+
ingestPropertyBinding(view, op.xref, attr.name, attr.value);
|
|
11165
11768
|
}
|
|
11166
11769
|
}
|
|
11167
11770
|
else {
|
|
11168
11771
|
for (const input of element.inputs) {
|
|
11169
|
-
view
|
|
11772
|
+
ingestPropertyBinding(view, op.xref, input.name, input.value);
|
|
11170
11773
|
}
|
|
11171
11774
|
for (const output of element.outputs) {
|
|
11172
11775
|
const listenerOp = createListenerOp(op.xref, output.name, op.tag);
|
|
@@ -11197,6 +11800,17 @@ function ingestBindings(view, op, element) {
|
|
|
11197
11800
|
}
|
|
11198
11801
|
}
|
|
11199
11802
|
}
|
|
11803
|
+
function ingestPropertyBinding(view, xref, name, value) {
|
|
11804
|
+
if (value instanceof ASTWithSource) {
|
|
11805
|
+
value = value.ast;
|
|
11806
|
+
}
|
|
11807
|
+
if (value instanceof Interpolation) {
|
|
11808
|
+
view.update.push(createInterpolatePropertyOp(xref, name, value.strings, value.expressions.map(expr => convertAst(expr, view.tpl))));
|
|
11809
|
+
}
|
|
11810
|
+
else {
|
|
11811
|
+
view.update.push(createPropertyOp(xref, name, convertAst(value, view.tpl)));
|
|
11812
|
+
}
|
|
11813
|
+
}
|
|
11200
11814
|
/**
|
|
11201
11815
|
* Process all of the local references on an element-like structure in the template AST and convert
|
|
11202
11816
|
* them to their IR representation.
|
|
@@ -21579,7 +22193,7 @@ function compileComponentFromMetadata(meta, constantPool, bindingParser) {
|
|
|
21579
22193
|
else {
|
|
21580
22194
|
// This path compiles the template using the prototype template pipeline. First the template is
|
|
21581
22195
|
// ingested into IR:
|
|
21582
|
-
const tpl = ingest(meta.name, meta.template.nodes);
|
|
22196
|
+
const tpl = ingest(meta.name, meta.template.nodes, constantPool);
|
|
21583
22197
|
// Then the IR is transformed to prepare it for cod egeneration.
|
|
21584
22198
|
transformTemplate(tpl);
|
|
21585
22199
|
// Finally we emit the template function:
|
|
@@ -22670,7 +23284,7 @@ function inputsMappingToInputMetadata(inputs) {
|
|
|
22670
23284
|
result[key] = {
|
|
22671
23285
|
bindingPropertyName: value[0],
|
|
22672
23286
|
classPropertyName: value[1],
|
|
22673
|
-
transformFunction: value[2]
|
|
23287
|
+
transformFunction: value[2] ? new WrappedNodeExpr(value[2]) : null,
|
|
22674
23288
|
required: false,
|
|
22675
23289
|
};
|
|
22676
23290
|
}
|
|
@@ -22745,7 +23359,7 @@ function publishFacade(global) {
|
|
|
22745
23359
|
* @description
|
|
22746
23360
|
* Entry point for all public APIs of the compiler package.
|
|
22747
23361
|
*/
|
|
22748
|
-
const VERSION = new Version('16.1.0-
|
|
23362
|
+
const VERSION = new Version('16.1.0-rc.0');
|
|
22749
23363
|
|
|
22750
23364
|
class CompilerConfig {
|
|
22751
23365
|
constructor({ defaultEncapsulation = ViewEncapsulation.Emulated, useJit = true, missingTranslation = null, preserveWhitespaces, strictInjectionParameters } = {}) {
|
|
@@ -24673,7 +25287,7 @@ const MINIMUM_PARTIAL_LINKER_VERSION$6 = '12.0.0';
|
|
|
24673
25287
|
function compileDeclareClassMetadata(metadata) {
|
|
24674
25288
|
const definitionMap = new DefinitionMap();
|
|
24675
25289
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$6));
|
|
24676
|
-
definitionMap.set('version', literal('16.1.0-
|
|
25290
|
+
definitionMap.set('version', literal('16.1.0-rc.0'));
|
|
24677
25291
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
24678
25292
|
definitionMap.set('type', metadata.type);
|
|
24679
25293
|
definitionMap.set('decorators', metadata.decorators);
|
|
@@ -24776,7 +25390,7 @@ function compileDeclareDirectiveFromMetadata(meta) {
|
|
|
24776
25390
|
function createDirectiveDefinitionMap(meta) {
|
|
24777
25391
|
const definitionMap = new DefinitionMap();
|
|
24778
25392
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$5));
|
|
24779
|
-
definitionMap.set('version', literal('16.1.0-
|
|
25393
|
+
definitionMap.set('version', literal('16.1.0-rc.0'));
|
|
24780
25394
|
// e.g. `type: MyDirective`
|
|
24781
25395
|
definitionMap.set('type', meta.type.value);
|
|
24782
25396
|
if (meta.isStandalone) {
|
|
@@ -25004,7 +25618,7 @@ const MINIMUM_PARTIAL_LINKER_VERSION$4 = '12.0.0';
|
|
|
25004
25618
|
function compileDeclareFactoryFunction(meta) {
|
|
25005
25619
|
const definitionMap = new DefinitionMap();
|
|
25006
25620
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$4));
|
|
25007
|
-
definitionMap.set('version', literal('16.1.0-
|
|
25621
|
+
definitionMap.set('version', literal('16.1.0-rc.0'));
|
|
25008
25622
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
25009
25623
|
definitionMap.set('type', meta.type.value);
|
|
25010
25624
|
definitionMap.set('deps', compileDependencies(meta.deps));
|
|
@@ -25039,7 +25653,7 @@ function compileDeclareInjectableFromMetadata(meta) {
|
|
|
25039
25653
|
function createInjectableDefinitionMap(meta) {
|
|
25040
25654
|
const definitionMap = new DefinitionMap();
|
|
25041
25655
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$3));
|
|
25042
|
-
definitionMap.set('version', literal('16.1.0-
|
|
25656
|
+
definitionMap.set('version', literal('16.1.0-rc.0'));
|
|
25043
25657
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
25044
25658
|
definitionMap.set('type', meta.type.value);
|
|
25045
25659
|
// Only generate providedIn property if it has a non-null value
|
|
@@ -25090,7 +25704,7 @@ function compileDeclareInjectorFromMetadata(meta) {
|
|
|
25090
25704
|
function createInjectorDefinitionMap(meta) {
|
|
25091
25705
|
const definitionMap = new DefinitionMap();
|
|
25092
25706
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$2));
|
|
25093
|
-
definitionMap.set('version', literal('16.1.0-
|
|
25707
|
+
definitionMap.set('version', literal('16.1.0-rc.0'));
|
|
25094
25708
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
25095
25709
|
definitionMap.set('type', meta.type.value);
|
|
25096
25710
|
definitionMap.set('providers', meta.providers);
|
|
@@ -25120,7 +25734,7 @@ function compileDeclareNgModuleFromMetadata(meta) {
|
|
|
25120
25734
|
function createNgModuleDefinitionMap(meta) {
|
|
25121
25735
|
const definitionMap = new DefinitionMap();
|
|
25122
25736
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$1));
|
|
25123
|
-
definitionMap.set('version', literal('16.1.0-
|
|
25737
|
+
definitionMap.set('version', literal('16.1.0-rc.0'));
|
|
25124
25738
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
25125
25739
|
definitionMap.set('type', meta.type.value);
|
|
25126
25740
|
// We only generate the keys in the metadata if the arrays contain values.
|
|
@@ -25171,7 +25785,7 @@ function compileDeclarePipeFromMetadata(meta) {
|
|
|
25171
25785
|
function createPipeDefinitionMap(meta) {
|
|
25172
25786
|
const definitionMap = new DefinitionMap();
|
|
25173
25787
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION));
|
|
25174
|
-
definitionMap.set('version', literal('16.1.0-
|
|
25788
|
+
definitionMap.set('version', literal('16.1.0-rc.0'));
|
|
25175
25789
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
25176
25790
|
// e.g. `type: MyPipe`
|
|
25177
25791
|
definitionMap.set('type', meta.type.value);
|