You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

28842 lines
990 KiB

/**
* @license Angular v21.1.1
* (c) 2010-2026 Google LLC. https://angular.dev/
* License: MIT
*/
const _SELECTOR_REGEXP = new RegExp('(\\:not\\()|' + '(([\\.\\#]?)[-\\w]+)|' + '(?:\\[([-.\\w*\\\\$]+)(?:=(["\']?)([^\\]"\']*)\\5)?\\])|' + '(\\))|' + '(\\s*,\\s*)', 'g');
class CssSelector {
element = null;
classNames = [];
attrs = [];
notSelectors = [];
static parse(selector) {
const results = [];
const _addResult = (res, cssSel) => {
if (cssSel.notSelectors.length > 0 && !cssSel.element && cssSel.classNames.length == 0 && cssSel.attrs.length == 0) {
cssSel.element = '*';
}
res.push(cssSel);
};
let cssSelector = new CssSelector();
let match;
let current = cssSelector;
let inNot = false;
_SELECTOR_REGEXP.lastIndex = 0;
while (match = _SELECTOR_REGEXP.exec(selector)) {
if (match[1]) {
if (inNot) {
throw new Error('Nesting :not in a selector is not allowed');
}
inNot = true;
current = new CssSelector();
cssSelector.notSelectors.push(current);
}
const tag = match[2];
if (tag) {
const prefix = match[3];
if (prefix === '#') {
current.addAttribute('id', tag.slice(1));
} else if (prefix === '.') {
current.addClassName(tag.slice(1));
} else {
current.setElement(tag);
}
}
const attribute = match[4];
if (attribute) {
current.addAttribute(current.unescapeAttribute(attribute), match[6]);
}
if (match[7]) {
inNot = false;
current = cssSelector;
}
if (match[8]) {
if (inNot) {
throw new Error('Multiple selectors in :not are not supported');
}
_addResult(results, cssSelector);
cssSelector = current = new CssSelector();
}
}
_addResult(results, cssSelector);
return results;
}
unescapeAttribute(attr) {
let result = '';
let escaping = false;
for (let i = 0; i < attr.length; i++) {
const char = attr.charAt(i);
if (char === '\\') {
escaping = true;
continue;
}
if (char === '$' && !escaping) {
throw new Error(`Error in attribute selector "${attr}". ` + `Unescaped "$" is not supported. Please escape with "\\$".`);
}
escaping = false;
result += char;
}
return result;
}
escapeAttribute(attr) {
return attr.replace(/\\/g, '\\\\').replace(/\$/g, '\\$');
}
isElementSelector() {
return this.hasElementSelector() && this.classNames.length == 0 && this.attrs.length == 0 && this.notSelectors.length === 0;
}
hasElementSelector() {
return !!this.element;
}
setElement(element = null) {
this.element = element;
}
getAttrs() {
const result = [];
if (this.classNames.length > 0) {
result.push('class', this.classNames.join(' '));
}
return result.concat(this.attrs);
}
addAttribute(name, value = '') {
this.attrs.push(name, value && value.toLowerCase() || '');
}
addClassName(name) {
this.classNames.push(name.toLowerCase());
}
toString() {
let res = this.element || '';
if (this.classNames) {
this.classNames.forEach(klass => res += `.${klass}`);
}
if (this.attrs) {
for (let i = 0; i < this.attrs.length; i += 2) {
const name = this.escapeAttribute(this.attrs[i]);
const value = this.attrs[i + 1];
res += `[${name}${value ? '=' + value : ''}]`;
}
}
this.notSelectors.forEach(notSelector => res += `:not(${notSelector})`);
return res;
}
}
class SelectorMatcher {
static createNotMatcher(notSelectors) {
const notMatcher = new SelectorMatcher();
notMatcher.addSelectables(notSelectors, null);
return notMatcher;
}
_elementMap = new Map();
_elementPartialMap = new Map();
_classMap = new Map();
_classPartialMap = new Map();
_attrValueMap = new Map();
_attrValuePartialMap = new Map();
_listContexts = [];
addSelectables(cssSelectors, callbackCtxt) {
let listContext = null;
if (cssSelectors.length > 1) {
listContext = new SelectorListContext(cssSelectors);
this._listContexts.push(listContext);
}
for (let i = 0; i < cssSelectors.length; i++) {
this._addSelectable(cssSelectors[i], callbackCtxt, listContext);
}
}
_addSelectable(cssSelector, callbackCtxt, listContext) {
let matcher = this;
const element = cssSelector.element;
const classNames = cssSelector.classNames;
const attrs = cssSelector.attrs;
const selectable = new SelectorContext(cssSelector, callbackCtxt, listContext);
if (element) {
const isTerminal = attrs.length === 0 && classNames.length === 0;
if (isTerminal) {
this._addTerminal(matcher._elementMap, element, selectable);
} else {
matcher = this._addPartial(matcher._elementPartialMap, element);
}
}
if (classNames) {
for (let i = 0; i < classNames.length; i++) {
const isTerminal = attrs.length === 0 && i === classNames.length - 1;
const className = classNames[i];
if (isTerminal) {
this._addTerminal(matcher._classMap, className, selectable);
} else {
matcher = this._addPartial(matcher._classPartialMap, className);
}
}
}
if (attrs) {
for (let i = 0; i < attrs.length; i += 2) {
const isTerminal = i === attrs.length - 2;
const name = attrs[i];
const value = attrs[i + 1];
if (isTerminal) {
const terminalMap = matcher._attrValueMap;
let terminalValuesMap = terminalMap.get(name);
if (!terminalValuesMap) {
terminalValuesMap = new Map();
terminalMap.set(name, terminalValuesMap);
}
this._addTerminal(terminalValuesMap, value, selectable);
} else {
const partialMap = matcher._attrValuePartialMap;
let partialValuesMap = partialMap.get(name);
if (!partialValuesMap) {
partialValuesMap = new Map();
partialMap.set(name, partialValuesMap);
}
matcher = this._addPartial(partialValuesMap, value);
}
}
}
}
_addTerminal(map, name, selectable) {
let terminalList = map.get(name);
if (!terminalList) {
terminalList = [];
map.set(name, terminalList);
}
terminalList.push(selectable);
}
_addPartial(map, name) {
let matcher = map.get(name);
if (!matcher) {
matcher = new SelectorMatcher();
map.set(name, matcher);
}
return matcher;
}
match(cssSelector, matchedCallback) {
let result = false;
const element = cssSelector.element;
const classNames = cssSelector.classNames;
const attrs = cssSelector.attrs;
for (let i = 0; i < this._listContexts.length; i++) {
this._listContexts[i].alreadyMatched = false;
}
result = this._matchTerminal(this._elementMap, element, cssSelector, matchedCallback) || result;
result = this._matchPartial(this._elementPartialMap, element, cssSelector, matchedCallback) || result;
if (classNames) {
for (let i = 0; i < classNames.length; i++) {
const className = classNames[i];
result = this._matchTerminal(this._classMap, className, cssSelector, matchedCallback) || result;
result = this._matchPartial(this._classPartialMap, className, cssSelector, matchedCallback) || result;
}
}
if (attrs) {
for (let i = 0; i < attrs.length; i += 2) {
const name = attrs[i];
const value = attrs[i + 1];
const terminalValuesMap = this._attrValueMap.get(name);
if (value) {
result = this._matchTerminal(terminalValuesMap, '', cssSelector, matchedCallback) || result;
}
result = this._matchTerminal(terminalValuesMap, value, cssSelector, matchedCallback) || result;
const partialValuesMap = this._attrValuePartialMap.get(name);
if (value) {
result = this._matchPartial(partialValuesMap, '', cssSelector, matchedCallback) || result;
}
result = this._matchPartial(partialValuesMap, value, cssSelector, matchedCallback) || result;
}
}
return result;
}
_matchTerminal(map, name, cssSelector, matchedCallback) {
if (!map || typeof name !== 'string') {
return false;
}
let selectables = map.get(name) || [];
const starSelectables = map.get('*');
if (starSelectables) {
selectables = selectables.concat(starSelectables);
}
if (selectables.length === 0) {
return false;
}
let selectable;
let result = false;
for (let i = 0; i < selectables.length; i++) {
selectable = selectables[i];
result = selectable.finalize(cssSelector, matchedCallback) || result;
}
return result;
}
_matchPartial(map, name, cssSelector, matchedCallback) {
if (!map || typeof name !== 'string') {
return false;
}
const nestedSelector = map.get(name);
if (!nestedSelector) {
return false;
}
return nestedSelector.match(cssSelector, matchedCallback);
}
}
class SelectorListContext {
selectors;
alreadyMatched = false;
constructor(selectors) {
this.selectors = selectors;
}
}
class SelectorContext {
selector;
cbContext;
listContext;
notSelectors;
constructor(selector, cbContext, listContext) {
this.selector = selector;
this.cbContext = cbContext;
this.listContext = listContext;
this.notSelectors = selector.notSelectors;
}
finalize(cssSelector, callback) {
let result = true;
if (this.notSelectors.length > 0 && (!this.listContext || !this.listContext.alreadyMatched)) {
const notMatcher = SelectorMatcher.createNotMatcher(this.notSelectors);
result = !notMatcher.match(cssSelector, null);
}
if (result && callback && (!this.listContext || !this.listContext.alreadyMatched)) {
if (this.listContext) {
this.listContext.alreadyMatched = true;
}
callback(this.selector, this.cbContext);
}
return result;
}
}
class SelectorlessMatcher {
registry;
constructor(registry) {
this.registry = registry;
}
match(name) {
return this.registry.has(name) ? this.registry.get(name) : [];
}
}
const emitDistinctChangesOnlyDefaultValue = true;
var ViewEncapsulation$1;
(function (ViewEncapsulation) {
ViewEncapsulation[ViewEncapsulation["Emulated"] = 0] = "Emulated";
ViewEncapsulation[ViewEncapsulation["None"] = 2] = "None";
ViewEncapsulation[ViewEncapsulation["ShadowDom"] = 3] = "ShadowDom";
ViewEncapsulation[ViewEncapsulation["ExperimentalIsolatedShadowDom"] = 4] = "ExperimentalIsolatedShadowDom";
})(ViewEncapsulation$1 || (ViewEncapsulation$1 = {}));
var ChangeDetectionStrategy;
(function (ChangeDetectionStrategy) {
ChangeDetectionStrategy[ChangeDetectionStrategy["OnPush"] = 0] = "OnPush";
ChangeDetectionStrategy[ChangeDetectionStrategy["Default"] = 1] = "Default";
})(ChangeDetectionStrategy || (ChangeDetectionStrategy = {}));
var InputFlags;
(function (InputFlags) {
InputFlags[InputFlags["None"] = 0] = "None";
InputFlags[InputFlags["SignalBased"] = 1] = "SignalBased";
InputFlags[InputFlags["HasDecoratorInputTransform"] = 2] = "HasDecoratorInputTransform";
})(InputFlags || (InputFlags = {}));
const CUSTOM_ELEMENTS_SCHEMA = {
name: 'custom-elements'
};
const NO_ERRORS_SCHEMA = {
name: 'no-errors-schema'
};
const Type$1 = Function;
var SecurityContext;
(function (SecurityContext) {
SecurityContext[SecurityContext["NONE"] = 0] = "NONE";
SecurityContext[SecurityContext["HTML"] = 1] = "HTML";
SecurityContext[SecurityContext["STYLE"] = 2] = "STYLE";
SecurityContext[SecurityContext["SCRIPT"] = 3] = "SCRIPT";
SecurityContext[SecurityContext["URL"] = 4] = "URL";
SecurityContext[SecurityContext["RESOURCE_URL"] = 5] = "RESOURCE_URL";
SecurityContext[SecurityContext["ATTRIBUTE_NO_BINDING"] = 6] = "ATTRIBUTE_NO_BINDING";
})(SecurityContext || (SecurityContext = {}));
var MissingTranslationStrategy;
(function (MissingTranslationStrategy) {
MissingTranslationStrategy[MissingTranslationStrategy["Error"] = 0] = "Error";
MissingTranslationStrategy[MissingTranslationStrategy["Warning"] = 1] = "Warning";
MissingTranslationStrategy[MissingTranslationStrategy["Ignore"] = 2] = "Ignore";
})(MissingTranslationStrategy || (MissingTranslationStrategy = {}));
function parserSelectorToSimpleSelector(selector) {
const classes = selector.classNames && selector.classNames.length ? [8, ...selector.classNames] : [];
const elementName = selector.element && selector.element !== '*' ? selector.element : '';
return [elementName, ...selector.attrs, ...classes];
}
function parserSelectorToNegativeSelector(selector) {
const classes = selector.classNames && selector.classNames.length ? [8, ...selector.classNames] : [];
if (selector.element) {
return [1 | 4, selector.element, ...selector.attrs, ...classes];
} else if (selector.attrs.length) {
return [1 | 2, ...selector.attrs, ...classes];
} else {
return selector.classNames && selector.classNames.length ? [1 | 8, ...selector.classNames] : [];
}
}
function parserSelectorToR3Selector(selector) {
const positive = parserSelectorToSimpleSelector(selector);
const negative = selector.notSelectors && selector.notSelectors.length ? selector.notSelectors.map(notSelector => parserSelectorToNegativeSelector(notSelector)) : [];
return positive.concat(...negative);
}
function parseSelectorToR3Selector(selector) {
return selector ? CssSelector.parse(selector).map(parserSelectorToR3Selector) : [];
}
var core = /*#__PURE__*/Object.freeze({
__proto__: null,
CUSTOM_ELEMENTS_SCHEMA: CUSTOM_ELEMENTS_SCHEMA,
get ChangeDetectionStrategy () { return ChangeDetectionStrategy; },
get InputFlags () { return InputFlags; },
get MissingTranslationStrategy () { return MissingTranslationStrategy; },
NO_ERRORS_SCHEMA: NO_ERRORS_SCHEMA,
get SecurityContext () { return SecurityContext; },
Type: Type$1,
get ViewEncapsulation () { return ViewEncapsulation$1; },
emitDistinctChangesOnlyDefaultValue: emitDistinctChangesOnlyDefaultValue,
parseSelectorToR3Selector: parseSelectorToR3Selector
});
var FactoryTarget;
(function (FactoryTarget) {
FactoryTarget[FactoryTarget["Directive"] = 0] = "Directive";
FactoryTarget[FactoryTarget["Component"] = 1] = "Component";
FactoryTarget[FactoryTarget["Injectable"] = 2] = "Injectable";
FactoryTarget[FactoryTarget["Pipe"] = 3] = "Pipe";
FactoryTarget[FactoryTarget["NgModule"] = 4] = "NgModule";
})(FactoryTarget || (FactoryTarget = {}));
var R3TemplateDependencyKind$1;
(function (R3TemplateDependencyKind) {
R3TemplateDependencyKind[R3TemplateDependencyKind["Directive"] = 0] = "Directive";
R3TemplateDependencyKind[R3TemplateDependencyKind["Pipe"] = 1] = "Pipe";
R3TemplateDependencyKind[R3TemplateDependencyKind["NgModule"] = 2] = "NgModule";
})(R3TemplateDependencyKind$1 || (R3TemplateDependencyKind$1 = {}));
var ViewEncapsulation;
(function (ViewEncapsulation) {
ViewEncapsulation[ViewEncapsulation["Emulated"] = 0] = "Emulated";
ViewEncapsulation[ViewEncapsulation["None"] = 2] = "None";
ViewEncapsulation[ViewEncapsulation["ShadowDom"] = 3] = "ShadowDom";
ViewEncapsulation[ViewEncapsulation["ExperimentalIsolatedShadowDom"] = 4] = "ExperimentalIsolatedShadowDom";
})(ViewEncapsulation || (ViewEncapsulation = {}));
let textEncoder;
function digest$1(message) {
return message.id || computeDigest(message);
}
function computeDigest(message) {
return sha1(serializeNodes(message.nodes).join('') + `[${message.meaning}]`);
}
function decimalDigest(message) {
return message.id || computeDecimalDigest(message);
}
function computeDecimalDigest(message) {
const visitor = new _SerializerIgnoreIcuExpVisitor();
const parts = message.nodes.map(a => a.visit(visitor, null));
return computeMsgId(parts.join(''), message.meaning);
}
class _SerializerVisitor {
visitText(text, context) {
return text.value;
}
visitContainer(container, context) {
return `[${container.children.map(child => child.visit(this)).join(', ')}]`;
}
visitIcu(icu, context) {
const strCases = Object.keys(icu.cases).map(k => `${k} {${icu.cases[k].visit(this)}}`);
return `{${icu.expression}, ${icu.type}, ${strCases.join(', ')}}`;
}
visitTagPlaceholder(ph, context) {
return ph.isVoid ? `<ph tag name="${ph.startName}"/>` : `<ph tag name="${ph.startName}">${ph.children.map(child => child.visit(this)).join(', ')}</ph name="${ph.closeName}">`;
}
visitPlaceholder(ph, context) {
return ph.value ? `<ph name="${ph.name}">${ph.value}</ph>` : `<ph name="${ph.name}"/>`;
}
visitIcuPlaceholder(ph, context) {
return `<ph icu name="${ph.name}">${ph.value.visit(this)}</ph>`;
}
visitBlockPlaceholder(ph, context) {
return `<ph block name="${ph.startName}">${ph.children.map(child => child.visit(this)).join(', ')}</ph name="${ph.closeName}">`;
}
}
const serializerVisitor$1 = new _SerializerVisitor();
function serializeNodes(nodes) {
return nodes.map(a => a.visit(serializerVisitor$1, null));
}
class _SerializerIgnoreIcuExpVisitor extends _SerializerVisitor {
visitIcu(icu) {
let strCases = Object.keys(icu.cases).map(k => `${k} {${icu.cases[k].visit(this)}}`);
return `{${icu.type}, ${strCases.join(', ')}}`;
}
}
function sha1(str) {
textEncoder ??= new TextEncoder();
const utf8 = [...textEncoder.encode(str)];
const words32 = bytesToWords32(utf8, Endian.Big);
const len = utf8.length * 8;
const w = new Uint32Array(80);
let a = 0x67452301,
b = 0xefcdab89,
c = 0x98badcfe,
d = 0x10325476,
e = 0xc3d2e1f0;
words32[len >> 5] |= 0x80 << 24 - len % 32;
words32[(len + 64 >> 9 << 4) + 15] = len;
for (let i = 0; i < words32.length; i += 16) {
const h0 = a,
h1 = b,
h2 = c,
h3 = d,
h4 = e;
for (let j = 0; j < 80; j++) {
if (j < 16) {
w[j] = words32[i + j];
} else {
w[j] = rol32(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1);
}
const fkVal = fk(j, b, c, d);
const f = fkVal[0];
const k = fkVal[1];
const temp = [rol32(a, 5), f, e, k, w[j]].reduce(add32);
e = d;
d = c;
c = rol32(b, 30);
b = a;
a = temp;
}
a = add32(a, h0);
b = add32(b, h1);
c = add32(c, h2);
d = add32(d, h3);
e = add32(e, h4);
}
return toHexU32(a) + toHexU32(b) + toHexU32(c) + toHexU32(d) + toHexU32(e);
}
function toHexU32(value) {
return (value >>> 0).toString(16).padStart(8, '0');
}
function fk(index, b, c, d) {
if (index < 20) {
return [b & c | ~b & d, 0x5a827999];
}
if (index < 40) {
return [b ^ c ^ d, 0x6ed9eba1];
}
if (index < 60) {
return [b & c | b & d | c & d, 0x8f1bbcdc];
}
return [b ^ c ^ d, 0xca62c1d6];
}
function fingerprint(str) {
textEncoder ??= new TextEncoder();
const utf8 = textEncoder.encode(str);
const view = new DataView(utf8.buffer, utf8.byteOffset, utf8.byteLength);
let hi = hash32(view, utf8.length, 0);
let lo = hash32(view, utf8.length, 102072);
if (hi == 0 && (lo == 0 || lo == 1)) {
hi = hi ^ 0x130f9bef;
lo = lo ^ -0x6b5f56d8;
}
return BigInt.asUintN(32, BigInt(hi)) << BigInt(32) | BigInt.asUintN(32, BigInt(lo));
}
function computeMsgId(msg, meaning = '') {
let msgFingerprint = fingerprint(msg);
if (meaning) {
msgFingerprint = BigInt.asUintN(64, msgFingerprint << BigInt(1)) | msgFingerprint >> BigInt(63) & BigInt(1);
msgFingerprint += fingerprint(meaning);
}
return BigInt.asUintN(63, msgFingerprint).toString();
}
function hash32(view, length, c) {
let a = 0x9e3779b9,
b = 0x9e3779b9;
let index = 0;
const end = length - 12;
for (; index <= end; index += 12) {
a += view.getUint32(index, true);
b += view.getUint32(index + 4, true);
c += view.getUint32(index + 8, true);
const res = mix(a, b, c);
a = res[0], b = res[1], c = res[2];
}
const remainder = length - index;
c += length;
if (remainder >= 4) {
a += view.getUint32(index, true);
index += 4;
if (remainder >= 8) {
b += view.getUint32(index, true);
index += 4;
if (remainder >= 9) {
c += view.getUint8(index++) << 8;
}
if (remainder >= 10) {
c += view.getUint8(index++) << 16;
}
if (remainder === 11) {
c += view.getUint8(index++) << 24;
}
} else {
if (remainder >= 5) {
b += view.getUint8(index++);
}
if (remainder >= 6) {
b += view.getUint8(index++) << 8;
}
if (remainder === 7) {
b += view.getUint8(index++) << 16;
}
}
} else {
if (remainder >= 1) {
a += view.getUint8(index++);
}
if (remainder >= 2) {
a += view.getUint8(index++) << 8;
}
if (remainder === 3) {
a += view.getUint8(index++) << 16;
}
}
return mix(a, b, c)[2];
}
function mix(a, b, c) {
a -= b;
a -= c;
a ^= c >>> 13;
b -= c;
b -= a;
b ^= a << 8;
c -= a;
c -= b;
c ^= b >>> 13;
a -= b;
a -= c;
a ^= c >>> 12;
b -= c;
b -= a;
b ^= a << 16;
c -= a;
c -= b;
c ^= b >>> 5;
a -= b;
a -= c;
a ^= c >>> 3;
b -= c;
b -= a;
b ^= a << 10;
c -= a;
c -= b;
c ^= b >>> 15;
return [a, b, c];
}
var Endian;
(function (Endian) {
Endian[Endian["Little"] = 0] = "Little";
Endian[Endian["Big"] = 1] = "Big";
})(Endian || (Endian = {}));
function add32(a, b) {
return add32to64(a, b)[1];
}
function add32to64(a, b) {
const low = (a & 0xffff) + (b & 0xffff);
const high = (a >>> 16) + (b >>> 16) + (low >>> 16);
return [high >>> 16, high << 16 | low & 0xffff];
}
function rol32(a, count) {
return a << count | a >>> 32 - count;
}
function bytesToWords32(bytes, endian) {
const size = bytes.length + 3 >>> 2;
const words32 = [];
for (let i = 0; i < size; i++) {
words32[i] = wordAt(bytes, i * 4, endian);
}
return words32;
}
function byteAt(bytes, index) {
return index >= bytes.length ? 0 : bytes[index];
}
function wordAt(bytes, index, endian) {
let word = 0;
if (endian === Endian.Big) {
for (let i = 0; i < 4; i++) {
word += byteAt(bytes, index + i) << 24 - 8 * i;
}
} else {
for (let i = 0; i < 4; i++) {
word += byteAt(bytes, index + i) << 8 * i;
}
}
return word;
}
var TypeModifier;
(function (TypeModifier) {
TypeModifier[TypeModifier["None"] = 0] = "None";
TypeModifier[TypeModifier["Const"] = 1] = "Const";
})(TypeModifier || (TypeModifier = {}));
class Type {
modifiers;
constructor(modifiers = TypeModifier.None) {
this.modifiers = modifiers;
}
hasModifier(modifier) {
return (this.modifiers & modifier) !== 0;
}
}
var BuiltinTypeName;
(function (BuiltinTypeName) {
BuiltinTypeName[BuiltinTypeName["Dynamic"] = 0] = "Dynamic";
BuiltinTypeName[BuiltinTypeName["Bool"] = 1] = "Bool";
BuiltinTypeName[BuiltinTypeName["String"] = 2] = "String";
BuiltinTypeName[BuiltinTypeName["Int"] = 3] = "Int";
BuiltinTypeName[BuiltinTypeName["Number"] = 4] = "Number";
BuiltinTypeName[BuiltinTypeName["Function"] = 5] = "Function";
BuiltinTypeName[BuiltinTypeName["Inferred"] = 6] = "Inferred";
BuiltinTypeName[BuiltinTypeName["None"] = 7] = "None";
})(BuiltinTypeName || (BuiltinTypeName = {}));
class BuiltinType extends Type {
name;
constructor(name, modifiers) {
super(modifiers);
this.name = name;
}
visitType(visitor, context) {
return visitor.visitBuiltinType(this, context);
}
}
class ExpressionType extends Type {
value;
typeParams;
constructor(value, modifiers, typeParams = null) {
super(modifiers);
this.value = value;
this.typeParams = typeParams;
}
visitType(visitor, context) {
return visitor.visitExpressionType(this, context);
}
}
class ArrayType extends Type {
of;
constructor(of, modifiers) {
super(modifiers);
this.of = of;
}
visitType(visitor, context) {
return visitor.visitArrayType(this, context);
}
}
class MapType extends Type {
valueType;
constructor(valueType, modifiers) {
super(modifiers);
this.valueType = valueType || null;
}
visitType(visitor, context) {
return visitor.visitMapType(this, context);
}
}
class TransplantedType extends Type {
type;
constructor(type, modifiers) {
super(modifiers);
this.type = type;
}
visitType(visitor, context) {
return visitor.visitTransplantedType(this, context);
}
}
const DYNAMIC_TYPE = new BuiltinType(BuiltinTypeName.Dynamic);
const INFERRED_TYPE = new BuiltinType(BuiltinTypeName.Inferred);
const BOOL_TYPE = new BuiltinType(BuiltinTypeName.Bool);
const INT_TYPE = new BuiltinType(BuiltinTypeName.Int);
const NUMBER_TYPE = new BuiltinType(BuiltinTypeName.Number);
const STRING_TYPE = new BuiltinType(BuiltinTypeName.String);
const FUNCTION_TYPE = new BuiltinType(BuiltinTypeName.Function);
const NONE_TYPE = new BuiltinType(BuiltinTypeName.None);
var UnaryOperator;
(function (UnaryOperator) {
UnaryOperator[UnaryOperator["Minus"] = 0] = "Minus";
UnaryOperator[UnaryOperator["Plus"] = 1] = "Plus";
})(UnaryOperator || (UnaryOperator = {}));
var BinaryOperator;
(function (BinaryOperator) {
BinaryOperator[BinaryOperator["Equals"] = 0] = "Equals";
BinaryOperator[BinaryOperator["NotEquals"] = 1] = "NotEquals";
BinaryOperator[BinaryOperator["Assign"] = 2] = "Assign";
BinaryOperator[BinaryOperator["Identical"] = 3] = "Identical";
BinaryOperator[BinaryOperator["NotIdentical"] = 4] = "NotIdentical";
BinaryOperator[BinaryOperator["Minus"] = 5] = "Minus";
BinaryOperator[BinaryOperator["Plus"] = 6] = "Plus";
BinaryOperator[BinaryOperator["Divide"] = 7] = "Divide";
BinaryOperator[BinaryOperator["Multiply"] = 8] = "Multiply";
BinaryOperator[BinaryOperator["Modulo"] = 9] = "Modulo";
BinaryOperator[BinaryOperator["And"] = 10] = "And";
BinaryOperator[BinaryOperator["Or"] = 11] = "Or";
BinaryOperator[BinaryOperator["BitwiseOr"] = 12] = "BitwiseOr";
BinaryOperator[BinaryOperator["BitwiseAnd"] = 13] = "BitwiseAnd";
BinaryOperator[BinaryOperator["Lower"] = 14] = "Lower";
BinaryOperator[BinaryOperator["LowerEquals"] = 15] = "LowerEquals";
BinaryOperator[BinaryOperator["Bigger"] = 16] = "Bigger";
BinaryOperator[BinaryOperator["BiggerEquals"] = 17] = "BiggerEquals";
BinaryOperator[BinaryOperator["NullishCoalesce"] = 18] = "NullishCoalesce";
BinaryOperator[BinaryOperator["Exponentiation"] = 19] = "Exponentiation";
BinaryOperator[BinaryOperator["In"] = 20] = "In";
BinaryOperator[BinaryOperator["AdditionAssignment"] = 21] = "AdditionAssignment";
BinaryOperator[BinaryOperator["SubtractionAssignment"] = 22] = "SubtractionAssignment";
BinaryOperator[BinaryOperator["MultiplicationAssignment"] = 23] = "MultiplicationAssignment";
BinaryOperator[BinaryOperator["DivisionAssignment"] = 24] = "DivisionAssignment";
BinaryOperator[BinaryOperator["RemainderAssignment"] = 25] = "RemainderAssignment";
BinaryOperator[BinaryOperator["ExponentiationAssignment"] = 26] = "ExponentiationAssignment";
BinaryOperator[BinaryOperator["AndAssignment"] = 27] = "AndAssignment";
BinaryOperator[BinaryOperator["OrAssignment"] = 28] = "OrAssignment";
BinaryOperator[BinaryOperator["NullishCoalesceAssignment"] = 29] = "NullishCoalesceAssignment";
})(BinaryOperator || (BinaryOperator = {}));
function nullSafeIsEquivalent(base, other) {
if (base == null || other == null) {
return base == other;
}
return base.isEquivalent(other);
}
function areAllEquivalentPredicate(base, other, equivalentPredicate) {
const len = base.length;
if (len !== other.length) {
return false;
}
for (let i = 0; i < len; i++) {
if (!equivalentPredicate(base[i], other[i])) {
return false;
}
}
return true;
}
function areAllEquivalent(base, other) {
return areAllEquivalentPredicate(base, other, (baseElement, otherElement) => baseElement.isEquivalent(otherElement));
}
class Expression {
type;
sourceSpan;
constructor(type, sourceSpan) {
this.type = type || null;
this.sourceSpan = sourceSpan || null;
}
prop(name, sourceSpan) {
return new ReadPropExpr(this, name, null, sourceSpan);
}
key(index, type, sourceSpan) {
return new ReadKeyExpr(this, index, type, sourceSpan);
}
callFn(params, sourceSpan, pure) {
return new InvokeFunctionExpr(this, params, null, sourceSpan, pure);
}
instantiate(params, type, sourceSpan) {
return new InstantiateExpr(this, params, type, sourceSpan);
}
conditional(trueCase, falseCase = null, sourceSpan) {
return new ConditionalExpr(this, trueCase, falseCase, null, sourceSpan);
}
equals(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.Equals, this, rhs, null, sourceSpan);
}
notEquals(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.NotEquals, this, rhs, null, sourceSpan);
}
identical(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.Identical, this, rhs, null, sourceSpan);
}
notIdentical(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.NotIdentical, this, rhs, null, sourceSpan);
}
minus(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.Minus, this, rhs, null, sourceSpan);
}
plus(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.Plus, this, rhs, null, sourceSpan);
}
divide(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.Divide, this, rhs, null, sourceSpan);
}
multiply(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.Multiply, this, rhs, null, sourceSpan);
}
modulo(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.Modulo, this, rhs, null, sourceSpan);
}
power(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.Exponentiation, this, rhs, null, sourceSpan);
}
and(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.And, this, rhs, null, sourceSpan);
}
bitwiseOr(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.BitwiseOr, this, rhs, null, sourceSpan);
}
bitwiseAnd(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.BitwiseAnd, this, rhs, null, sourceSpan);
}
or(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.Or, this, rhs, null, sourceSpan);
}
lower(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.Lower, this, rhs, null, sourceSpan);
}
lowerEquals(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.LowerEquals, this, rhs, null, sourceSpan);
}
bigger(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.Bigger, this, rhs, null, sourceSpan);
}
biggerEquals(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.BiggerEquals, this, rhs, null, sourceSpan);
}
isBlank(sourceSpan) {
return this.equals(TYPED_NULL_EXPR, sourceSpan);
}
nullishCoalesce(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.NullishCoalesce, this, rhs, null, sourceSpan);
}
toStmt() {
return new ExpressionStatement(this, null);
}
}
class ReadVarExpr extends Expression {
name;
constructor(name, type, sourceSpan) {
super(type, sourceSpan);
this.name = name;
}
isEquivalent(e) {
return e instanceof ReadVarExpr && this.name === e.name;
}
isConstant() {
return false;
}
visitExpression(visitor, context) {
return visitor.visitReadVarExpr(this, context);
}
clone() {
return new ReadVarExpr(this.name, this.type, this.sourceSpan);
}
set(value) {
return new BinaryOperatorExpr(BinaryOperator.Assign, this, value, null, this.sourceSpan);
}
}
class TypeofExpr extends Expression {
expr;
constructor(expr, type, sourceSpan) {
super(type, sourceSpan);
this.expr = expr;
}
visitExpression(visitor, context) {
return visitor.visitTypeofExpr(this, context);
}
isEquivalent(e) {
return e instanceof TypeofExpr && e.expr.isEquivalent(this.expr);
}
isConstant() {
return this.expr.isConstant();
}
clone() {
return new TypeofExpr(this.expr.clone());
}
}
class VoidExpr extends Expression {
expr;
constructor(expr, type, sourceSpan) {
super(type, sourceSpan);
this.expr = expr;
}
visitExpression(visitor, context) {
return visitor.visitVoidExpr(this, context);
}
isEquivalent(e) {
return e instanceof VoidExpr && e.expr.isEquivalent(this.expr);
}
isConstant() {
return this.expr.isConstant();
}
clone() {
return new VoidExpr(this.expr.clone());
}
}
class WrappedNodeExpr extends Expression {
node;
constructor(node, type, sourceSpan) {
super(type, sourceSpan);
this.node = node;
}
isEquivalent(e) {
return e instanceof WrappedNodeExpr && this.node === e.node;
}
isConstant() {
return false;
}
visitExpression(visitor, context) {
return visitor.visitWrappedNodeExpr(this, context);
}
clone() {
return new WrappedNodeExpr(this.node, this.type, this.sourceSpan);
}
}
class InvokeFunctionExpr extends Expression {
fn;
args;
pure;
constructor(fn, args, type, sourceSpan, pure = false) {
super(type, sourceSpan);
this.fn = fn;
this.args = args;
this.pure = pure;
}
get receiver() {
return this.fn;
}
isEquivalent(e) {
return e instanceof InvokeFunctionExpr && this.fn.isEquivalent(e.fn) && areAllEquivalent(this.args, e.args) && this.pure === e.pure;
}
isConstant() {
return false;
}
visitExpression(visitor, context) {
return visitor.visitInvokeFunctionExpr(this, context);
}
clone() {
return new InvokeFunctionExpr(this.fn.clone(), this.args.map(arg => arg.clone()), this.type, this.sourceSpan, this.pure);
}
}
class TaggedTemplateLiteralExpr extends Expression {
tag;
template;
constructor(tag, template, type, sourceSpan) {
super(type, sourceSpan);
this.tag = tag;
this.template = template;
}
isEquivalent(e) {
return e instanceof TaggedTemplateLiteralExpr && this.tag.isEquivalent(e.tag) && this.template.isEquivalent(e.template);
}
isConstant() {
return false;
}
visitExpression(visitor, context) {
return visitor.visitTaggedTemplateLiteralExpr(this, context);
}
clone() {
return new TaggedTemplateLiteralExpr(this.tag.clone(), this.template.clone(), this.type, this.sourceSpan);
}
}
class InstantiateExpr extends Expression {
classExpr;
args;
constructor(classExpr, args, type, sourceSpan) {
super(type, sourceSpan);
this.classExpr = classExpr;
this.args = args;
}
isEquivalent(e) {
return e instanceof InstantiateExpr && this.classExpr.isEquivalent(e.classExpr) && areAllEquivalent(this.args, e.args);
}
isConstant() {
return false;
}
visitExpression(visitor, context) {
return visitor.visitInstantiateExpr(this, context);
}
clone() {
return new InstantiateExpr(this.classExpr.clone(), this.args.map(arg => arg.clone()), this.type, this.sourceSpan);
}
}
class RegularExpressionLiteralExpr extends Expression {
body;
flags;
constructor(body, flags, sourceSpan) {
super(null, sourceSpan);
this.body = body;
this.flags = flags;
}
isEquivalent(e) {
return e instanceof RegularExpressionLiteralExpr && this.body === e.body && this.flags === e.flags;
}
isConstant() {
return true;
}
visitExpression(visitor, context) {
return visitor.visitRegularExpressionLiteral(this, context);
}
clone() {
return new RegularExpressionLiteralExpr(this.body, this.flags, this.sourceSpan);
}
}
class LiteralExpr extends Expression {
value;
constructor(value, type, sourceSpan) {
super(type, sourceSpan);
this.value = value;
}
isEquivalent(e) {
return e instanceof LiteralExpr && this.value === e.value;
}
isConstant() {
return true;
}
visitExpression(visitor, context) {
return visitor.visitLiteralExpr(this, context);
}
clone() {
return new LiteralExpr(this.value, this.type, this.sourceSpan);
}
}
class TemplateLiteralExpr extends Expression {
elements;
expressions;
constructor(elements, expressions, sourceSpan) {
super(null, sourceSpan);
this.elements = elements;
this.expressions = expressions;
}
isEquivalent(e) {
return e instanceof TemplateLiteralExpr && areAllEquivalentPredicate(this.elements, e.elements, (a, b) => a.text === b.text) && areAllEquivalent(this.expressions, e.expressions);
}
isConstant() {
return false;
}
visitExpression(visitor, context) {
return visitor.visitTemplateLiteralExpr(this, context);
}
clone() {
return new TemplateLiteralExpr(this.elements.map(el => el.clone()), this.expressions.map(expr => expr.clone()));
}
}
class TemplateLiteralElementExpr extends Expression {
text;
rawText;
constructor(text, sourceSpan, rawText) {
super(STRING_TYPE, sourceSpan);
this.text = text;
this.rawText = rawText ?? escapeForTemplateLiteral(escapeSlashes(text));
}
visitExpression(visitor, context) {
return visitor.visitTemplateLiteralElementExpr(this, context);
}
isEquivalent(e) {
return e instanceof TemplateLiteralElementExpr && e.text === this.text && e.rawText === this.rawText;
}
isConstant() {
return true;
}
clone() {
return new TemplateLiteralElementExpr(this.text, this.sourceSpan, this.rawText);
}
}
class LiteralPiece {
text;
sourceSpan;
constructor(text, sourceSpan) {
this.text = text;
this.sourceSpan = sourceSpan;
}
}
class PlaceholderPiece {
text;
sourceSpan;
associatedMessage;
constructor(text, sourceSpan, associatedMessage) {
this.text = text;
this.sourceSpan = sourceSpan;
this.associatedMessage = associatedMessage;
}
}
const MEANING_SEPARATOR$1 = '|';
const ID_SEPARATOR$1 = '@@';
const LEGACY_ID_INDICATOR = '␟';
class LocalizedString extends Expression {
metaBlock;
messageParts;
placeHolderNames;
expressions;
constructor(metaBlock, messageParts, placeHolderNames, expressions, sourceSpan) {
super(STRING_TYPE, sourceSpan);
this.metaBlock = metaBlock;
this.messageParts = messageParts;
this.placeHolderNames = placeHolderNames;
this.expressions = expressions;
}
isEquivalent(e) {
return false;
}
isConstant() {
return false;
}
visitExpression(visitor, context) {
return visitor.visitLocalizedString(this, context);
}
clone() {
return new LocalizedString(this.metaBlock, this.messageParts, this.placeHolderNames, this.expressions.map(expr => expr.clone()), this.sourceSpan);
}
serializeI18nHead() {
let metaBlock = this.metaBlock.description || '';
if (this.metaBlock.meaning) {
metaBlock = `${this.metaBlock.meaning}${MEANING_SEPARATOR$1}${metaBlock}`;
}
if (this.metaBlock.customId) {
metaBlock = `${metaBlock}${ID_SEPARATOR$1}${this.metaBlock.customId}`;
}
if (this.metaBlock.legacyIds) {
this.metaBlock.legacyIds.forEach(legacyId => {
metaBlock = `${metaBlock}${LEGACY_ID_INDICATOR}${legacyId}`;
});
}
return createCookedRawString(metaBlock, this.messageParts[0].text, this.getMessagePartSourceSpan(0));
}
getMessagePartSourceSpan(i) {
return this.messageParts[i]?.sourceSpan ?? this.sourceSpan;
}
getPlaceholderSourceSpan(i) {
return this.placeHolderNames[i]?.sourceSpan ?? this.expressions[i]?.sourceSpan ?? this.sourceSpan;
}
serializeI18nTemplatePart(partIndex) {
const placeholder = this.placeHolderNames[partIndex - 1];
const messagePart = this.messageParts[partIndex];
let metaBlock = placeholder.text;
if (placeholder.associatedMessage?.legacyIds.length === 0) {
metaBlock += `${ID_SEPARATOR$1}${computeMsgId(placeholder.associatedMessage.messageString, placeholder.associatedMessage.meaning)}`;
}
return createCookedRawString(metaBlock, messagePart.text, this.getMessagePartSourceSpan(partIndex));
}
}
const escapeSlashes = str => str.replace(/\\/g, '\\\\');
const escapeStartingColon = str => str.replace(/^:/, '\\:');
const escapeColons = str => str.replace(/:/g, '\\:');
const escapeForTemplateLiteral = str => str.replace(/`/g, '\\`').replace(/\${/g, '$\\{');
function createCookedRawString(metaBlock, messagePart, range) {
if (metaBlock === '') {
return {
cooked: messagePart,
raw: escapeForTemplateLiteral(escapeStartingColon(escapeSlashes(messagePart))),
range
};
} else {
return {
cooked: `:${metaBlock}:${messagePart}`,
raw: escapeForTemplateLiteral(`:${escapeColons(escapeSlashes(metaBlock))}:${escapeSlashes(messagePart)}`),
range
};
}
}
class ExternalExpr extends Expression {
value;
typeParams;
constructor(value, type, typeParams = null, sourceSpan) {
super(type, sourceSpan);
this.value = value;
this.typeParams = typeParams;
}
isEquivalent(e) {
return e instanceof ExternalExpr && this.value.name === e.value.name && this.value.moduleName === e.value.moduleName;
}
isConstant() {
return false;
}
visitExpression(visitor, context) {
return visitor.visitExternalExpr(this, context);
}
clone() {
return new ExternalExpr(this.value, this.type, this.typeParams, this.sourceSpan);
}
}
class ExternalReference {
moduleName;
name;
constructor(moduleName, name) {
this.moduleName = moduleName;
this.name = name;
}
}
class ConditionalExpr extends Expression {
condition;
falseCase;
trueCase;
constructor(condition, trueCase, falseCase = null, type, sourceSpan) {
super(type || trueCase.type, sourceSpan);
this.condition = condition;
this.falseCase = falseCase;
this.trueCase = trueCase;
}
isEquivalent(e) {
return e instanceof ConditionalExpr && this.condition.isEquivalent(e.condition) && this.trueCase.isEquivalent(e.trueCase) && nullSafeIsEquivalent(this.falseCase, e.falseCase);
}
isConstant() {
return false;
}
visitExpression(visitor, context) {
return visitor.visitConditionalExpr(this, context);
}
clone() {
return new ConditionalExpr(this.condition.clone(), this.trueCase.clone(), this.falseCase?.clone(), this.type, this.sourceSpan);
}
}
class DynamicImportExpr extends Expression {
url;
urlComment;
constructor(url, sourceSpan, urlComment) {
super(null, sourceSpan);
this.url = url;
this.urlComment = urlComment;
}
isEquivalent(e) {
return e instanceof DynamicImportExpr && this.url === e.url && this.urlComment === e.urlComment;
}
isConstant() {
return false;
}
visitExpression(visitor, context) {
return visitor.visitDynamicImportExpr(this, context);
}
clone() {
return new DynamicImportExpr(typeof this.url === 'string' ? this.url : this.url.clone(), this.sourceSpan, this.urlComment);
}
}
class NotExpr extends Expression {
condition;
constructor(condition, sourceSpan) {
super(BOOL_TYPE, sourceSpan);
this.condition = condition;
}
isEquivalent(e) {
return e instanceof NotExpr && this.condition.isEquivalent(e.condition);
}
isConstant() {
return false;
}
visitExpression(visitor, context) {
return visitor.visitNotExpr(this, context);
}
clone() {
return new NotExpr(this.condition.clone(), this.sourceSpan);
}
}
class FnParam {
name;
type;
constructor(name, type = null) {
this.name = name;
this.type = type;
}
isEquivalent(param) {
return this.name === param.name;
}
clone() {
return new FnParam(this.name, this.type);
}
}
class FunctionExpr extends Expression {
params;
statements;
name;
constructor(params, statements, type, sourceSpan, name) {
super(type, sourceSpan);
this.params = params;
this.statements = statements;
this.name = name;
}
isEquivalent(e) {
return (e instanceof FunctionExpr || e instanceof DeclareFunctionStmt) && areAllEquivalent(this.params, e.params) && areAllEquivalent(this.statements, e.statements);
}
isConstant() {
return false;
}
visitExpression(visitor, context) {
return visitor.visitFunctionExpr(this, context);
}
toDeclStmt(name, modifiers) {
return new DeclareFunctionStmt(name, this.params, this.statements, this.type, modifiers, this.sourceSpan);
}
clone() {
return new FunctionExpr(this.params.map(p => p.clone()), this.statements, this.type, this.sourceSpan, this.name);
}
}
class ArrowFunctionExpr extends Expression {
params;
body;
constructor(params, body, type, sourceSpan) {
super(type, sourceSpan);
this.params = params;
this.body = body;
}
isEquivalent(e) {
if (!(e instanceof ArrowFunctionExpr) || !areAllEquivalent(this.params, e.params)) {
return false;
}
if (this.body instanceof Expression && e.body instanceof Expression) {
return this.body.isEquivalent(e.body);
}
if (Array.isArray(this.body) && Array.isArray(e.body)) {
return areAllEquivalent(this.body, e.body);
}
return false;
}
isConstant() {
return false;
}
visitExpression(visitor, context) {
return visitor.visitArrowFunctionExpr(this, context);
}
clone() {
return new ArrowFunctionExpr(this.params.map(p => p.clone()), Array.isArray(this.body) ? this.body : this.body.clone(), this.type, this.sourceSpan);
}
toDeclStmt(name, modifiers) {
return new DeclareVarStmt(name, this, INFERRED_TYPE, modifiers, this.sourceSpan);
}
}
class UnaryOperatorExpr extends Expression {
operator;
expr;
parens;
constructor(operator, expr, type, sourceSpan, parens = true) {
super(type || NUMBER_TYPE, sourceSpan);
this.operator = operator;
this.expr = expr;
this.parens = parens;
}
isEquivalent(e) {
return e instanceof UnaryOperatorExpr && this.operator === e.operator && this.expr.isEquivalent(e.expr);
}
isConstant() {
return false;
}
visitExpression(visitor, context) {
return visitor.visitUnaryOperatorExpr(this, context);
}
clone() {
return new UnaryOperatorExpr(this.operator, this.expr.clone(), this.type, this.sourceSpan, this.parens);
}
}
class ParenthesizedExpr extends Expression {
expr;
constructor(expr, type, sourceSpan) {
super(type, sourceSpan);
this.expr = expr;
}
visitExpression(visitor, context) {
return visitor.visitParenthesizedExpr(this, context);
}
isEquivalent(e) {
return e instanceof ParenthesizedExpr && e.expr.isEquivalent(this.expr);
}
isConstant() {
return this.expr.isConstant();
}
clone() {
return new ParenthesizedExpr(this.expr.clone());
}
}
class BinaryOperatorExpr extends Expression {
operator;
rhs;
lhs;
constructor(operator, lhs, rhs, type, sourceSpan) {
super(type || lhs.type, sourceSpan);
this.operator = operator;
this.rhs = rhs;
this.lhs = lhs;
}
isEquivalent(e) {
return e instanceof BinaryOperatorExpr && this.operator === e.operator && this.lhs.isEquivalent(e.lhs) && this.rhs.isEquivalent(e.rhs);
}
isConstant() {
return false;
}
visitExpression(visitor, context) {
return visitor.visitBinaryOperatorExpr(this, context);
}
clone() {
return new BinaryOperatorExpr(this.operator, this.lhs.clone(), this.rhs.clone(), this.type, this.sourceSpan);
}
isAssignment() {
const op = this.operator;
return op === BinaryOperator.Assign || op === BinaryOperator.AdditionAssignment || op === BinaryOperator.SubtractionAssignment || op === BinaryOperator.MultiplicationAssignment || op === BinaryOperator.DivisionAssignment || op === BinaryOperator.RemainderAssignment || op === BinaryOperator.ExponentiationAssignment || op === BinaryOperator.AndAssignment || op === BinaryOperator.OrAssignment || op === BinaryOperator.NullishCoalesceAssignment;
}
}
class ReadPropExpr extends Expression {
receiver;
name;
constructor(receiver, name, type, sourceSpan) {
super(type, sourceSpan);
this.receiver = receiver;
this.name = name;
}
get index() {
return this.name;
}
isEquivalent(e) {
return e instanceof ReadPropExpr && this.receiver.isEquivalent(e.receiver) && this.name === e.name;
}
isConstant() {
return false;
}
visitExpression(visitor, context) {
return visitor.visitReadPropExpr(this, context);
}
set(value) {
return new BinaryOperatorExpr(BinaryOperator.Assign, this.receiver.prop(this.name), value, null, this.sourceSpan);
}
clone() {
return new ReadPropExpr(this.receiver.clone(), this.name, this.type, this.sourceSpan);
}
}
class ReadKeyExpr extends Expression {
receiver;
index;
constructor(receiver, index, type, sourceSpan) {
super(type, sourceSpan);
this.receiver = receiver;
this.index = index;
}
isEquivalent(e) {
return e instanceof ReadKeyExpr && this.receiver.isEquivalent(e.receiver) && this.index.isEquivalent(e.index);
}
isConstant() {
return false;
}
visitExpression(visitor, context) {
return visitor.visitReadKeyExpr(this, context);
}
set(value) {
return new BinaryOperatorExpr(BinaryOperator.Assign, this.receiver.key(this.index), value, null, this.sourceSpan);
}
clone() {
return new ReadKeyExpr(this.receiver.clone(), this.index.clone(), this.type, this.sourceSpan);
}
}
class LiteralArrayExpr extends Expression {
entries;
constructor(entries, type, sourceSpan) {
super(type, sourceSpan);
this.entries = entries;
}
isConstant() {
return this.entries.every(e => e.isConstant());
}
isEquivalent(e) {
return e instanceof LiteralArrayExpr && areAllEquivalent(this.entries, e.entries);
}
visitExpression(visitor, context) {
return visitor.visitLiteralArrayExpr(this, context);
}
clone() {
return new LiteralArrayExpr(this.entries.map(e => e.clone()), this.type, this.sourceSpan);
}
}
class LiteralMapPropertyAssignment {
key;
value;
quoted;
constructor(key, value, quoted) {
this.key = key;
this.value = value;
this.quoted = quoted;
}
isEquivalent(e) {
return this.key === e.key && this.value.isEquivalent(e.value);
}
clone() {
return new LiteralMapPropertyAssignment(this.key, this.value.clone(), this.quoted);
}
isConstant() {
return this.value.isConstant();
}
}
class LiteralMapSpreadAssignment {
expression;
constructor(expression) {
this.expression = expression;
}
isEquivalent(e) {
return e instanceof LiteralMapSpreadAssignment && this.expression.isEquivalent(e.expression);
}
clone() {
return new LiteralMapSpreadAssignment(this.expression.clone());
}
isConstant() {
return this.expression.isConstant();
}
}
class LiteralMapExpr extends Expression {
entries;
valueType = null;
constructor(entries, type, sourceSpan) {
super(type, sourceSpan);
this.entries = entries;
if (type) {
this.valueType = type.valueType;
}
}
isEquivalent(e) {
return e instanceof LiteralMapExpr && areAllEquivalent(this.entries, e.entries);
}
isConstant() {
return this.entries.every(e => e.isConstant());
}
visitExpression(visitor, context) {
return visitor.visitLiteralMapExpr(this, context);
}
clone() {
const entriesClone = this.entries.map(entry => entry.clone());
return new LiteralMapExpr(entriesClone, this.type, this.sourceSpan);
}
}
class CommaExpr extends Expression {
parts;
constructor(parts, sourceSpan) {
super(parts[parts.length - 1].type, sourceSpan);
this.parts = parts;
}
isEquivalent(e) {
return e instanceof CommaExpr && areAllEquivalent(this.parts, e.parts);
}
isConstant() {
return false;
}
visitExpression(visitor, context) {
return visitor.visitCommaExpr(this, context);
}
clone() {
return new CommaExpr(this.parts.map(p => p.clone()));
}
}
class SpreadElementExpr extends Expression {
expression;
constructor(expression, sourceSpan) {
super(null, sourceSpan);
this.expression = expression;
}
isEquivalent(e) {
return e instanceof SpreadElementExpr && this.expression.isEquivalent(e.expression);
}
isConstant() {
return this.expression.isConstant();
}
visitExpression(visitor, context) {
return visitor.visitSpreadElementExpr(this, context);
}
clone() {
return new SpreadElementExpr(this.expression.clone(), this.sourceSpan);
}
}
const NULL_EXPR = new LiteralExpr(null, null, null);
const TYPED_NULL_EXPR = new LiteralExpr(null, INFERRED_TYPE, null);
var StmtModifier;
(function (StmtModifier) {
StmtModifier[StmtModifier["None"] = 0] = "None";
StmtModifier[StmtModifier["Final"] = 1] = "Final";
StmtModifier[StmtModifier["Private"] = 2] = "Private";
StmtModifier[StmtModifier["Exported"] = 4] = "Exported";
StmtModifier[StmtModifier["Static"] = 8] = "Static";
})(StmtModifier || (StmtModifier = {}));
class LeadingComment {
text;
multiline;
trailingNewline;
constructor(text, multiline, trailingNewline) {
this.text = text;
this.multiline = multiline;
this.trailingNewline = trailingNewline;
}
toString() {
return this.multiline ? ` ${this.text} ` : this.text;
}
}
class JSDocComment extends LeadingComment {
tags;
constructor(tags) {
super('', true, true);
this.tags = tags;
}
toString() {
return serializeTags(this.tags);
}
}
class Statement {
modifiers;
sourceSpan;
leadingComments;
constructor(modifiers = StmtModifier.None, sourceSpan = null, leadingComments) {
this.modifiers = modifiers;
this.sourceSpan = sourceSpan;
this.leadingComments = leadingComments;
}
hasModifier(modifier) {
return (this.modifiers & modifier) !== 0;
}
addLeadingComment(leadingComment) {
this.leadingComments = this.leadingComments ?? [];
this.leadingComments.push(leadingComment);
}
}
class DeclareVarStmt extends Statement {
name;
value;
type;
constructor(name, value, type, modifiers, sourceSpan, leadingComments) {
super(modifiers, sourceSpan, leadingComments);
this.name = name;
this.value = value;
this.type = type || value && value.type || null;
}
isEquivalent(stmt) {
return stmt instanceof DeclareVarStmt && this.name === stmt.name && (this.value ? !!stmt.value && this.value.isEquivalent(stmt.value) : !stmt.value);
}
visitStatement(visitor, context) {
return visitor.visitDeclareVarStmt(this, context);
}
}
class DeclareFunctionStmt extends Statement {
name;
params;
statements;
type;
constructor(name, params, statements, type, modifiers, sourceSpan, leadingComments) {
super(modifiers, sourceSpan, leadingComments);
this.name = name;
this.params = params;
this.statements = statements;
this.type = type || null;
}
isEquivalent(stmt) {
return stmt instanceof DeclareFunctionStmt && areAllEquivalent(this.params, stmt.params) && areAllEquivalent(this.statements, stmt.statements);
}
visitStatement(visitor, context) {
return visitor.visitDeclareFunctionStmt(this, context);
}
}
class ExpressionStatement extends Statement {
expr;
constructor(expr, sourceSpan, leadingComments) {
super(StmtModifier.None, sourceSpan, leadingComments);
this.expr = expr;
}
isEquivalent(stmt) {
return stmt instanceof ExpressionStatement && this.expr.isEquivalent(stmt.expr);
}
visitStatement(visitor, context) {
return visitor.visitExpressionStmt(this, context);
}
}
class ReturnStatement extends Statement {
value;
constructor(value, sourceSpan = null, leadingComments) {
super(StmtModifier.None, sourceSpan, leadingComments);
this.value = value;
}
isEquivalent(stmt) {
return stmt instanceof ReturnStatement && this.value.isEquivalent(stmt.value);
}
visitStatement(visitor, context) {
return visitor.visitReturnStmt(this, context);
}
}
class IfStmt extends Statement {
condition;
trueCase;
falseCase;
constructor(condition, trueCase, falseCase = [], sourceSpan, leadingComments) {
super(StmtModifier.None, sourceSpan, leadingComments);
this.condition = condition;
this.trueCase = trueCase;
this.falseCase = falseCase;
}
isEquivalent(stmt) {
return stmt instanceof IfStmt && this.condition.isEquivalent(stmt.condition) && areAllEquivalent(this.trueCase, stmt.trueCase) && areAllEquivalent(this.falseCase, stmt.falseCase);
}
visitStatement(visitor, context) {
return visitor.visitIfStmt(this, context);
}
}
let RecursiveAstVisitor$1 = class RecursiveAstVisitor {
visitType(ast, context) {
return ast;
}
visitExpression(ast, context) {
if (ast.type) {
ast.type.visitType(this, context);
}
return ast;
}
visitBuiltinType(type, context) {
return this.visitType(type, context);
}
visitExpressionType(type, context) {
type.value.visitExpression(this, context);
if (type.typeParams !== null) {
type.typeParams.forEach(param => this.visitType(param, context));
}
return this.visitType(type, context);
}
visitArrayType(type, context) {
return this.visitType(type, context);
}
visitMapType(type, context) {
return this.visitType(type, context);
}
visitTransplantedType(type, context) {
return type;
}
visitWrappedNodeExpr(ast, context) {
return ast;
}
visitReadVarExpr(ast, context) {
return this.visitExpression(ast, context);
}
visitDynamicImportExpr(ast, context) {
return this.visitExpression(ast, context);
}
visitInvokeFunctionExpr(ast, context) {
ast.fn.visitExpression(this, context);
this.visitAllExpressions(ast.args, context);
return this.visitExpression(ast, context);
}
visitTaggedTemplateLiteralExpr(ast, context) {
ast.tag.visitExpression(this, context);
ast.template.visitExpression(this, context);
return this.visitExpression(ast, context);
}
visitInstantiateExpr(ast, context) {
ast.classExpr.visitExpression(this, context);
this.visitAllExpressions(ast.args, context);
return this.visitExpression(ast, context);
}
visitLiteralExpr(ast, context) {
return this.visitExpression(ast, context);
}
visitRegularExpressionLiteral(ast, context) {
return this.visitExpression(ast, context);
}
visitLocalizedString(ast, context) {
return this.visitExpression(ast, context);
}
visitExternalExpr(ast, context) {
if (ast.typeParams) {
ast.typeParams.forEach(type => type.visitType(this, context));
}
return this.visitExpression(ast, context);
}
visitConditionalExpr(ast, context) {
ast.condition.visitExpression(this, context);
ast.trueCase.visitExpression(this, context);
ast.falseCase.visitExpression(this, context);
return this.visitExpression(ast, context);
}
visitNotExpr(ast, context) {
ast.condition.visitExpression(this, context);
return this.visitExpression(ast, context);
}
visitFunctionExpr(ast, context) {
this.visitAllStatements(ast.statements, context);
return this.visitExpression(ast, context);
}
visitArrowFunctionExpr(ast, context) {
if (Array.isArray(ast.body)) {
this.visitAllStatements(ast.body, context);
} else {
ast.body.visitExpression(this, context);
}
return this.visitExpression(ast, context);
}
visitUnaryOperatorExpr(ast, context) {
ast.expr.visitExpression(this, context);
return this.visitExpression(ast, context);
}
visitTypeofExpr(ast, context) {
ast.expr.visitExpression(this, context);
return this.visitExpression(ast, context);
}
visitVoidExpr(ast, context) {
ast.expr.visitExpression(this, context);
return this.visitExpression(ast, context);
}
visitBinaryOperatorExpr(ast, context) {
ast.lhs.visitExpression(this, context);
ast.rhs.visitExpression(this, context);
return this.visitExpression(ast, context);
}
visitReadPropExpr(ast, context) {
ast.receiver.visitExpression(this, context);
return this.visitExpression(ast, context);
}
visitReadKeyExpr(ast, context) {
ast.receiver.visitExpression(this, context);
ast.index.visitExpression(this, context);
return this.visitExpression(ast, context);
}
visitLiteralArrayExpr(ast, context) {
this.visitAllExpressions(ast.entries, context);
return this.visitExpression(ast, context);
}
visitLiteralMapExpr(ast, context) {
ast.entries.forEach(entry => {
if (entry instanceof LiteralMapSpreadAssignment) {
entry.expression.visitExpression(this, context);
} else {
entry.value.visitExpression(this, context);
}
});
return this.visitExpression(ast, context);
}
visitCommaExpr(ast, context) {
this.visitAllExpressions(ast.parts, context);
return this.visitExpression(ast, context);
}
visitTemplateLiteralExpr(ast, context) {
this.visitAllExpressions(ast.elements, context);
this.visitAllExpressions(ast.expressions, context);
return this.visitExpression(ast, context);
}
visitTemplateLiteralElementExpr(ast, context) {
return this.visitExpression(ast, context);
}
visitParenthesizedExpr(ast, context) {
ast.expr.visitExpression(this, context);
return this.visitExpression(ast, context);
}
visitSpreadElementExpr(ast, context) {
ast.expression.visitExpression(this, context);
return this.visitExpression(ast, context);
}
visitAllExpressions(exprs, context) {
exprs.forEach(expr => expr.visitExpression(this, context));
}
visitDeclareVarStmt(stmt, context) {
if (stmt.value) {
stmt.value.visitExpression(this, context);
}
if (stmt.type) {
stmt.type.visitType(this, context);
}
return stmt;
}
visitDeclareFunctionStmt(stmt, context) {
this.visitAllStatements(stmt.statements, context);
if (stmt.type) {
stmt.type.visitType(this, context);
}
return stmt;
}
visitExpressionStmt(stmt, context) {
stmt.expr.visitExpression(this, context);
return stmt;
}
visitReturnStmt(stmt, context) {
stmt.value.visitExpression(this, context);
return stmt;
}
visitIfStmt(stmt, context) {
stmt.condition.visitExpression(this, context);
this.visitAllStatements(stmt.trueCase, context);
this.visitAllStatements(stmt.falseCase, context);
return stmt;
}
visitAllStatements(stmts, context) {
stmts.forEach(stmt => stmt.visitStatement(this, context));
}
};
function leadingComment(text, multiline = false, trailingNewline = true) {
return new LeadingComment(text, multiline, trailingNewline);
}
function jsDocComment(tags = []) {
return new JSDocComment(tags);
}
function variable(name, type, sourceSpan) {
return new ReadVarExpr(name, type, sourceSpan);
}
function importExpr(id, typeParams = null, sourceSpan) {
return new ExternalExpr(id, null, typeParams, sourceSpan);
}
function importType(id, typeParams, typeModifiers) {
return id != null ? expressionType(importExpr(id, typeParams, null), typeModifiers) : null;
}
function expressionType(expr, typeModifiers, typeParams) {
return new ExpressionType(expr, typeModifiers, typeParams);
}
function transplantedType(type, typeModifiers) {
return new TransplantedType(type, typeModifiers);
}
function typeofExpr(expr) {
return new TypeofExpr(expr);
}
function literalArr(values, type, sourceSpan) {
return new LiteralArrayExpr(values, type, sourceSpan);
}
function literalMap(values, type = null) {
return new LiteralMapExpr(values.map(e => new LiteralMapPropertyAssignment(e.key, e.value, e.quoted)), type, null);
}
function unary(operator, expr, type, sourceSpan) {
return new UnaryOperatorExpr(operator, expr, type, sourceSpan);
}
function not(expr, sourceSpan) {
return new NotExpr(expr, sourceSpan);
}
function fn(params, body, type, sourceSpan, name) {
return new FunctionExpr(params, body, type, sourceSpan, name);
}
function arrowFn(params, body, type, sourceSpan) {
return new ArrowFunctionExpr(params, body, type, sourceSpan);
}
function ifStmt(condition, thenClause, elseClause, sourceSpan, leadingComments) {
return new IfStmt(condition, thenClause, elseClause, sourceSpan, leadingComments);
}
function taggedTemplate(tag, template, type, sourceSpan) {
return new TaggedTemplateLiteralExpr(tag, template, type, sourceSpan);
}
function literal(value, type, sourceSpan) {
return new LiteralExpr(value, type, sourceSpan);
}
function localizedString(metaBlock, messageParts, placeholderNames, expressions, sourceSpan) {
return new LocalizedString(metaBlock, messageParts, placeholderNames, expressions, sourceSpan);
}
function isNull(exp) {
return exp instanceof LiteralExpr && exp.value === null;
}
function tagToString(tag) {
let out = '';
if (tag.tagName) {
out += ` @${tag.tagName}`;
}
if (tag.text) {
if (tag.text.match(/\/\*|\*\//)) {
throw new Error('JSDoc text cannot contain "/*" and "*/"');
}
out += ' ' + tag.text.replace(/@/g, '\\@');
}
return out;
}
function serializeTags(tags) {
if (tags.length === 0) return '';
if (tags.length === 1 && tags[0].tagName && !tags[0].text) {
return `*${tagToString(tags[0])} `;
}
let out = '*\n';
for (const tag of tags) {
out += ' *';
out += tagToString(tag).replace(/\n/g, '\n * ');
out += '\n';
}
out += ' ';
return out;
}
var output_ast = /*#__PURE__*/Object.freeze({
__proto__: null,
ArrayType: ArrayType,
ArrowFunctionExpr: ArrowFunctionExpr,
BOOL_TYPE: BOOL_TYPE,
get BinaryOperator () { return BinaryOperator; },
BinaryOperatorExpr: BinaryOperatorExpr,
BuiltinType: BuiltinType,
get BuiltinTypeName () { return BuiltinTypeName; },
CommaExpr: CommaExpr,
ConditionalExpr: ConditionalExpr,
DYNAMIC_TYPE: DYNAMIC_TYPE,
DeclareFunctionStmt: DeclareFunctionStmt,
DeclareVarStmt: DeclareVarStmt,
DynamicImportExpr: DynamicImportExpr,
Expression: Expression,
ExpressionStatement: ExpressionStatement,
ExpressionType: ExpressionType,
ExternalExpr: ExternalExpr,
ExternalReference: ExternalReference,
FUNCTION_TYPE: FUNCTION_TYPE,
FnParam: FnParam,
FunctionExpr: FunctionExpr,
INFERRED_TYPE: INFERRED_TYPE,
INT_TYPE: INT_TYPE,
IfStmt: IfStmt,
InstantiateExpr: InstantiateExpr,
InvokeFunctionExpr: InvokeFunctionExpr,
JSDocComment: JSDocComment,
LeadingComment: LeadingComment,
LiteralArrayExpr: LiteralArrayExpr,
LiteralExpr: LiteralExpr,
LiteralMapExpr: LiteralMapExpr,
LiteralMapPropertyAssignment: LiteralMapPropertyAssignment,
LiteralMapSpreadAssignment: LiteralMapSpreadAssignment,
LiteralPiece: LiteralPiece,
LocalizedString: LocalizedString,
MapType: MapType,
NONE_TYPE: NONE_TYPE,
NULL_EXPR: NULL_EXPR,
NUMBER_TYPE: NUMBER_TYPE,
NotExpr: NotExpr,
ParenthesizedExpr: ParenthesizedExpr,
PlaceholderPiece: PlaceholderPiece,
ReadKeyExpr: ReadKeyExpr,
ReadPropExpr: ReadPropExpr,
ReadVarExpr: ReadVarExpr,
RecursiveAstVisitor: RecursiveAstVisitor$1,
RegularExpressionLiteralExpr: RegularExpressionLiteralExpr,
ReturnStatement: ReturnStatement,
STRING_TYPE: STRING_TYPE,
SpreadElementExpr: SpreadElementExpr,
Statement: Statement,
get StmtModifier () { return StmtModifier; },
TYPED_NULL_EXPR: TYPED_NULL_EXPR,
TaggedTemplateLiteralExpr: TaggedTemplateLiteralExpr,
TemplateLiteralElementExpr: TemplateLiteralElementExpr,
TemplateLiteralExpr: TemplateLiteralExpr,
TransplantedType: TransplantedType,
Type: Type,
get TypeModifier () { return TypeModifier; },
TypeofExpr: TypeofExpr,
get UnaryOperator () { return UnaryOperator; },
UnaryOperatorExpr: UnaryOperatorExpr,
VoidExpr: VoidExpr,
WrappedNodeExpr: WrappedNodeExpr,
areAllEquivalent: areAllEquivalent,
arrowFn: arrowFn,
expressionType: expressionType,
fn: fn,
ifStmt: ifStmt,
importExpr: importExpr,
importType: importType,
isNull: isNull,
jsDocComment: jsDocComment,
leadingComment: leadingComment,
literal: literal,
literalArr: literalArr,
literalMap: literalMap,
localizedString: localizedString,
not: not,
nullSafeIsEquivalent: nullSafeIsEquivalent,
taggedTemplate: taggedTemplate,
transplantedType: transplantedType,
typeofExpr: typeofExpr,
unary: unary,
variable: variable
});
const CONSTANT_PREFIX = '_c';
const KEY_CONTEXT = {};
const POOL_INCLUSION_LENGTH_THRESHOLD_FOR_STRINGS = 50;
class FixupExpression extends Expression {
resolved;
original;
shared = false;
constructor(resolved) {
super(resolved.type);
this.resolved = resolved;
this.original = resolved;
}
visitExpression(visitor, context) {
if (context === KEY_CONTEXT) {
return this.original.visitExpression(visitor, context);
} else {
return this.resolved.visitExpression(visitor, context);
}
}
isEquivalent(e) {
return e instanceof FixupExpression && this.resolved.isEquivalent(e.resolved);
}
isConstant() {
return true;
}
clone() {
throw new Error(`Not supported.`);
}
fixup(expression) {
this.resolved = expression;
this.shared = true;
}
}
class ConstantPool {
isClosureCompilerEnabled;
statements = [];
literals = new Map();
literalFactories = new Map();
sharedConstants = new Map();
_claimedNames = new Map();
nextNameIndex = 0;
constructor(isClosureCompilerEnabled = false) {
this.isClosureCompilerEnabled = isClosureCompilerEnabled;
}
getConstLiteral(literal, forceShared) {
if (literal instanceof LiteralExpr && !isLongStringLiteral(literal) || literal instanceof FixupExpression) {
return literal;
}
const key = GenericKeyFn.INSTANCE.keyOf(literal);
let fixup = this.literals.get(key);
let newValue = false;
if (!fixup) {
fixup = new FixupExpression(literal);
this.literals.set(key, fixup);
newValue = true;
}
if (!newValue && !fixup.shared || newValue && forceShared) {
const name = this.freshName();
let value;
let usage;
if (this.isClosureCompilerEnabled && isLongStringLiteral(literal)) {
value = new FunctionExpr([], [new ReturnStatement(literal)]);
usage = variable(name).callFn([]);
} else {
value = literal;
usage = variable(name);
}
this.statements.push(new DeclareVarStmt(name, value, INFERRED_TYPE, StmtModifier.Final));
fixup.fixup(usage);
}
return fixup;
}
getSharedConstant(def, expr) {
const key = def.keyOf(expr);
if (!this.sharedConstants.has(key)) {
const id = this.freshName();
this.sharedConstants.set(key, variable(id));
this.statements.push(def.toSharedConstantDeclaration(id, expr));
}
return this.sharedConstants.get(key);
}
getSharedFunctionReference(fn, prefix, useUniqueName = true) {
const isArrow = fn instanceof ArrowFunctionExpr;
for (const current of this.statements) {
if (isArrow && current instanceof DeclareVarStmt && current.value?.isEquivalent(fn)) {
return variable(current.name);
}
if (!isArrow && current instanceof DeclareFunctionStmt && fn instanceof FunctionExpr && fn.isEquivalent(current)) {
return variable(current.name);
}
}
const name = useUniqueName ? this.uniqueName(prefix) : prefix;
this.statements.push(fn instanceof FunctionExpr ? fn.toDeclStmt(name, StmtModifier.Final) : new DeclareVarStmt(name, fn, INFERRED_TYPE, StmtModifier.Final, fn.sourceSpan));
return variable(name);
}
uniqueName(name, alwaysIncludeSuffix = true) {
const count = this._claimedNames.get(name) ?? 0;
const result = count === 0 && !alwaysIncludeSuffix ? `${name}` : `${name}${count}`;
this._claimedNames.set(name, count + 1);
return result;
}
freshName() {
return this.uniqueName(CONSTANT_PREFIX);
}
}
class GenericKeyFn {
static INSTANCE = new GenericKeyFn();
keyOf(expr) {
if (expr instanceof LiteralExpr && typeof expr.value === 'string') {
return `"${expr.value}"`;
} else if (expr instanceof LiteralExpr) {
return String(expr.value);
} else if (expr instanceof RegularExpressionLiteralExpr) {
return `/${expr.body}/${expr.flags ?? ''}`;
} else if (expr instanceof LiteralArrayExpr) {
const entries = [];
for (const entry of expr.entries) {
entries.push(this.keyOf(entry));
}
return `[${entries.join(',')}]`;
} else if (expr instanceof LiteralMapExpr) {
const entries = [];
for (const entry of expr.entries) {
if (entry instanceof LiteralMapSpreadAssignment) {
entries.push('...' + this.keyOf(entry.expression));
} else {
let key = entry.key;
if (entry.quoted) {
key = `"${key}"`;
}
entries.push(key + ':' + this.keyOf(entry.value));
}
}
return `{${entries.join(',')}}`;
} else if (expr instanceof ExternalExpr) {
return `import("${expr.value.moduleName}", ${expr.value.name})`;
} else if (expr instanceof ReadVarExpr) {
return `read(${expr.name})`;
} else if (expr instanceof TypeofExpr) {
return `typeof(${this.keyOf(expr.expr)})`;
} else if (expr instanceof SpreadElementExpr) {
return `...${this.keyOf(expr.expression)}`;
} else {
throw new Error(`${this.constructor.name} does not handle expressions of type ${expr.constructor.name}`);
}
}
}
function isLongStringLiteral(expr) {
return expr instanceof LiteralExpr && typeof expr.value === 'string' && expr.value.length >= POOL_INCLUSION_LENGTH_THRESHOLD_FOR_STRINGS;
}
const CORE = '@angular/core';
class Identifiers {
static core = {
name: null,
moduleName: CORE
};
static namespaceHTML = {
name: 'ɵɵnamespaceHTML',
moduleName: CORE
};
static namespaceMathML = {
name: 'ɵɵnamespaceMathML',
moduleName: CORE
};
static namespaceSVG = {
name: 'ɵɵnamespaceSVG',
moduleName: CORE
};
static element = {
name: 'ɵɵelement',
moduleName: CORE
};
static elementStart = {
name: 'ɵɵelementStart',
moduleName: CORE
};
static elementEnd = {
name: 'ɵɵelementEnd',
moduleName: CORE
};
static domElement = {
name: 'ɵɵdomElement',
moduleName: CORE
};
static domElementStart = {
name: 'ɵɵdomElementStart',
moduleName: CORE
};
static domElementEnd = {
name: 'ɵɵdomElementEnd',
moduleName: CORE
};
static domElementContainer = {
name: 'ɵɵdomElementContainer',
moduleName: CORE
};
static domElementContainerStart = {
name: 'ɵɵdomElementContainerStart',
moduleName: CORE
};
static domElementContainerEnd = {
name: 'ɵɵdomElementContainerEnd',
moduleName: CORE
};
static domTemplate = {
name: 'ɵɵdomTemplate',
moduleName: CORE
};
static domListener = {
name: 'ɵɵdomListener',
moduleName: CORE
};
static advance = {
name: 'ɵɵadvance',
moduleName: CORE
};
static syntheticHostProperty = {
name: 'ɵɵsyntheticHostProperty',
moduleName: CORE
};
static syntheticHostListener = {
name: 'ɵɵsyntheticHostListener',
moduleName: CORE
};
static attribute = {
name: 'ɵɵattribute',
moduleName: CORE
};
static classProp = {
name: 'ɵɵclassProp',
moduleName: CORE
};
static elementContainerStart = {
name: 'ɵɵelementContainerStart',
moduleName: CORE
};
static elementContainerEnd = {
name: 'ɵɵelementContainerEnd',
moduleName: CORE
};
static elementContainer = {
name: 'ɵɵelementContainer',
moduleName: CORE
};
static styleMap = {
name: 'ɵɵstyleMap',
moduleName: CORE
};
static classMap = {
name: 'ɵɵclassMap',
moduleName: CORE
};
static styleProp = {
name: 'ɵɵstyleProp',
moduleName: CORE
};
static interpolate = {
name: 'ɵɵinterpolate',
moduleName: CORE
};
static interpolate1 = {
name: 'ɵɵinterpolate1',
moduleName: CORE
};
static interpolate2 = {
name: 'ɵɵinterpolate2',
moduleName: CORE
};
static interpolate3 = {
name: 'ɵɵinterpolate3',
moduleName: CORE
};
static interpolate4 = {
name: 'ɵɵinterpolate4',
moduleName: CORE
};
static interpolate5 = {
name: 'ɵɵinterpolate5',
moduleName: CORE
};
static interpolate6 = {
name: 'ɵɵinterpolate6',
moduleName: CORE
};
static interpolate7 = {
name: 'ɵɵinterpolate7',
moduleName: CORE
};
static interpolate8 = {
name: 'ɵɵinterpolate8',
moduleName: CORE
};
static interpolateV = {
name: 'ɵɵinterpolateV',
moduleName: CORE
};
static nextContext = {
name: 'ɵɵnextContext',
moduleName: CORE
};
static resetView = {
name: 'ɵɵresetView',
moduleName: CORE
};
static templateCreate = {
name: 'ɵɵtemplate',
moduleName: CORE
};
static defer = {
name: 'ɵɵdefer',
moduleName: CORE
};
static deferWhen = {
name: 'ɵɵdeferWhen',
moduleName: CORE
};
static deferOnIdle = {
name: 'ɵɵdeferOnIdle',
moduleName: CORE
};
static deferOnImmediate = {
name: 'ɵɵdeferOnImmediate',
moduleName: CORE
};
static deferOnTimer = {
name: 'ɵɵdeferOnTimer',
moduleName: CORE
};
static deferOnHover = {
name: 'ɵɵdeferOnHover',
moduleName: CORE
};
static deferOnInteraction = {
name: 'ɵɵdeferOnInteraction',
moduleName: CORE
};
static deferOnViewport = {
name: 'ɵɵdeferOnViewport',
moduleName: CORE
};
static deferPrefetchWhen = {
name: 'ɵɵdeferPrefetchWhen',
moduleName: CORE
};
static deferPrefetchOnIdle = {
name: 'ɵɵdeferPrefetchOnIdle',
moduleName: CORE
};
static deferPrefetchOnImmediate = {
name: 'ɵɵdeferPrefetchOnImmediate',
moduleName: CORE
};
static deferPrefetchOnTimer = {
name: 'ɵɵdeferPrefetchOnTimer',
moduleName: CORE
};
static deferPrefetchOnHover = {
name: 'ɵɵdeferPrefetchOnHover',
moduleName: CORE
};
static deferPrefetchOnInteraction = {
name: 'ɵɵdeferPrefetchOnInteraction',
moduleName: CORE
};
static deferPrefetchOnViewport = {
name: 'ɵɵdeferPrefetchOnViewport',
moduleName: CORE
};
static deferHydrateWhen = {
name: 'ɵɵdeferHydrateWhen',
moduleName: CORE
};
static deferHydrateNever = {
name: 'ɵɵdeferHydrateNever',
moduleName: CORE
};
static deferHydrateOnIdle = {
name: 'ɵɵdeferHydrateOnIdle',
moduleName: CORE
};
static deferHydrateOnImmediate = {
name: 'ɵɵdeferHydrateOnImmediate',
moduleName: CORE
};
static deferHydrateOnTimer = {
name: 'ɵɵdeferHydrateOnTimer',
moduleName: CORE
};
static deferHydrateOnHover = {
name: 'ɵɵdeferHydrateOnHover',
moduleName: CORE
};
static deferHydrateOnInteraction = {
name: 'ɵɵdeferHydrateOnInteraction',
moduleName: CORE
};
static deferHydrateOnViewport = {
name: 'ɵɵdeferHydrateOnViewport',
moduleName: CORE
};
static deferEnableTimerScheduling = {
name: 'ɵɵdeferEnableTimerScheduling',
moduleName: CORE
};
static conditionalCreate = {
name: 'ɵɵconditionalCreate',
moduleName: CORE
};
static conditionalBranchCreate = {
name: 'ɵɵconditionalBranchCreate',
moduleName: CORE
};
static conditional = {
name: 'ɵɵconditional',
moduleName: CORE
};
static repeater = {
name: 'ɵɵrepeater',
moduleName: CORE
};
static repeaterCreate = {
name: 'ɵɵrepeaterCreate',
moduleName: CORE
};
static repeaterTrackByIndex = {
name: 'ɵɵrepeaterTrackByIndex',
moduleName: CORE
};
static repeaterTrackByIdentity = {
name: 'ɵɵrepeaterTrackByIdentity',
moduleName: CORE
};
static componentInstance = {
name: 'ɵɵcomponentInstance',
moduleName: CORE
};
static text = {
name: 'ɵɵtext',
moduleName: CORE
};
static enableBindings = {
name: 'ɵɵenableBindings',
moduleName: CORE
};
static disableBindings = {
name: 'ɵɵdisableBindings',
moduleName: CORE
};
static getCurrentView = {
name: 'ɵɵgetCurrentView',
moduleName: CORE
};
static textInterpolate = {
name: 'ɵɵtextInterpolate',
moduleName: CORE
};
static textInterpolate1 = {
name: 'ɵɵtextInterpolate1',
moduleName: CORE
};
static textInterpolate2 = {
name: 'ɵɵtextInterpolate2',
moduleName: CORE
};
static textInterpolate3 = {
name: 'ɵɵtextInterpolate3',
moduleName: CORE
};
static textInterpolate4 = {
name: 'ɵɵtextInterpolate4',
moduleName: CORE
};
static textInterpolate5 = {
name: 'ɵɵtextInterpolate5',
moduleName: CORE
};
static textInterpolate6 = {
name: 'ɵɵtextInterpolate6',
moduleName: CORE
};
static textInterpolate7 = {
name: 'ɵɵtextInterpolate7',
moduleName: CORE
};
static textInterpolate8 = {
name: 'ɵɵtextInterpolate8',
moduleName: CORE
};
static textInterpolateV = {
name: 'ɵɵtextInterpolateV',
moduleName: CORE
};
static restoreView = {
name: 'ɵɵrestoreView',
moduleName: CORE
};
static pureFunction0 = {
name: 'ɵɵpureFunction0',
moduleName: CORE
};
static pureFunction1 = {
name: 'ɵɵpureFunction1',
moduleName: CORE
};
static pureFunction2 = {
name: 'ɵɵpureFunction2',
moduleName: CORE
};
static pureFunction3 = {
name: 'ɵɵpureFunction3',
moduleName: CORE
};
static pureFunction4 = {
name: 'ɵɵpureFunction4',
moduleName: CORE
};
static pureFunction5 = {
name: 'ɵɵpureFunction5',
moduleName: CORE
};
static pureFunction6 = {
name: 'ɵɵpureFunction6',
moduleName: CORE
};
static pureFunction7 = {
name: 'ɵɵpureFunction7',
moduleName: CORE
};
static pureFunction8 = {
name: 'ɵɵpureFunction8',
moduleName: CORE
};
static pureFunctionV = {
name: 'ɵɵpureFunctionV',
moduleName: CORE
};
static pipeBind1 = {
name: 'ɵɵpipeBind1',
moduleName: CORE
};
static pipeBind2 = {
name: 'ɵɵpipeBind2',
moduleName: CORE
};
static pipeBind3 = {
name: 'ɵɵpipeBind3',
moduleName: CORE
};
static pipeBind4 = {
name: 'ɵɵpipeBind4',
moduleName: CORE
};
static pipeBindV = {
name: 'ɵɵpipeBindV',
moduleName: CORE
};
static domProperty = {
name: 'ɵɵdomProperty',
moduleName: CORE
};
static ariaProperty = {
name: 'ɵɵariaProperty',
moduleName: CORE
};
static property = {
name: 'ɵɵproperty',
moduleName: CORE
};
static control = {
name: 'ɵɵcontrol',
moduleName: CORE
};
static controlCreate = {
name: 'ɵɵcontrolCreate',
moduleName: CORE
};
static animationEnterListener = {
name: 'ɵɵanimateEnterListener',
moduleName: CORE
};
static animationLeaveListener = {
name: 'ɵɵanimateLeaveListener',
moduleName: CORE
};
static animationEnter = {
name: 'ɵɵanimateEnter',
moduleName: CORE
};
static animationLeave = {
name: 'ɵɵanimateLeave',
moduleName: CORE
};
static i18n = {
name: 'ɵɵi18n',
moduleName: CORE
};
static i18nAttributes = {
name: 'ɵɵi18nAttributes',
moduleName: CORE
};
static i18nExp = {
name: 'ɵɵi18nExp',
moduleName: CORE
};
static i18nStart = {
name: 'ɵɵi18nStart',
moduleName: CORE
};
static i18nEnd = {
name: 'ɵɵi18nEnd',
moduleName: CORE
};
static i18nApply = {
name: 'ɵɵi18nApply',
moduleName: CORE
};
static i18nPostprocess = {
name: 'ɵɵi18nPostprocess',
moduleName: CORE
};
static pipe = {
name: 'ɵɵpipe',
moduleName: CORE
};
static projection = {
name: 'ɵɵprojection',
moduleName: CORE
};
static projectionDef = {
name: 'ɵɵprojectionDef',
moduleName: CORE
};
static reference = {
name: 'ɵɵreference',
moduleName: CORE
};
static inject = {
name: 'ɵɵinject',
moduleName: CORE
};
static injectAttribute = {
name: 'ɵɵinjectAttribute',
moduleName: CORE
};
static directiveInject = {
name: 'ɵɵdirectiveInject',
moduleName: CORE
};
static invalidFactory = {
name: 'ɵɵinvalidFactory',
moduleName: CORE
};
static invalidFactoryDep = {
name: 'ɵɵinvalidFactoryDep',
moduleName: CORE
};
static templateRefExtractor = {
name: 'ɵɵtemplateRefExtractor',
moduleName: CORE
};
static forwardRef = {
name: 'forwardRef',
moduleName: CORE
};
static resolveForwardRef = {
name: 'resolveForwardRef',
moduleName: CORE
};
static replaceMetadata = {
name: 'ɵɵreplaceMetadata',
moduleName: CORE
};
static getReplaceMetadataURL = {
name: 'ɵɵgetReplaceMetadataURL',
moduleName: CORE
};
static ɵɵdefineInjectable = {
name: 'ɵɵdefineInjectable',
moduleName: CORE
};
static declareInjectable = {
name: 'ɵɵngDeclareInjectable',
moduleName: CORE
};
static InjectableDeclaration = {
name: 'ɵɵInjectableDeclaration',
moduleName: CORE
};
static resolveWindow = {
name: 'ɵɵresolveWindow',
moduleName: CORE
};
static resolveDocument = {
name: 'ɵɵresolveDocument',
moduleName: CORE
};
static resolveBody = {
name: 'ɵɵresolveBody',
moduleName: CORE
};
static getComponentDepsFactory = {
name: 'ɵɵgetComponentDepsFactory',
moduleName: CORE
};
static defineComponent = {
name: 'ɵɵdefineComponent',
moduleName: CORE
};
static declareComponent = {
name: 'ɵɵngDeclareComponent',
moduleName: CORE
};
static setComponentScope = {
name: 'ɵɵsetComponentScope',
moduleName: CORE
};
static ChangeDetectionStrategy = {
name: 'ChangeDetectionStrategy',
moduleName: CORE
};
static ViewEncapsulation = {
name: 'ViewEncapsulation',
moduleName: CORE
};
static ComponentDeclaration = {
name: 'ɵɵComponentDeclaration',
moduleName: CORE
};
static FactoryDeclaration = {
name: 'ɵɵFactoryDeclaration',
moduleName: CORE
};
static declareFactory = {
name: 'ɵɵngDeclareFactory',
moduleName: CORE
};
static FactoryTarget = {
name: 'ɵɵFactoryTarget',
moduleName: CORE
};
static defineDirective = {
name: 'ɵɵdefineDirective',
moduleName: CORE
};
static declareDirective = {
name: 'ɵɵngDeclareDirective',
moduleName: CORE
};
static DirectiveDeclaration = {
name: 'ɵɵDirectiveDeclaration',
moduleName: CORE
};
static InjectorDef = {
name: 'ɵɵInjectorDef',
moduleName: CORE
};
static InjectorDeclaration = {
name: 'ɵɵInjectorDeclaration',
moduleName: CORE
};
static defineInjector = {
name: 'ɵɵdefineInjector',
moduleName: CORE
};
static declareInjector = {
name: 'ɵɵngDeclareInjector',
moduleName: CORE
};
static NgModuleDeclaration = {
name: 'ɵɵNgModuleDeclaration',
moduleName: CORE
};
static ModuleWithProviders = {
name: 'ModuleWithProviders',
moduleName: CORE
};
static defineNgModule = {
name: 'ɵɵdefineNgModule',
moduleName: CORE
};
static declareNgModule = {
name: 'ɵɵngDeclareNgModule',
moduleName: CORE
};
static setNgModuleScope = {
name: 'ɵɵsetNgModuleScope',
moduleName: CORE
};
static registerNgModuleType = {
name: 'ɵɵregisterNgModuleType',
moduleName: CORE
};
static PipeDeclaration = {
name: 'ɵɵPipeDeclaration',
moduleName: CORE
};
static definePipe = {
name: 'ɵɵdefinePipe',
moduleName: CORE
};
static declarePipe = {
name: 'ɵɵngDeclarePipe',
moduleName: CORE
};
static declareClassMetadata = {
name: 'ɵɵngDeclareClassMetadata',
moduleName: CORE
};
static declareClassMetadataAsync = {
name: 'ɵɵngDeclareClassMetadataAsync',
moduleName: CORE
};
static setClassMetadata = {
name: 'ɵsetClassMetadata',
moduleName: CORE
};
static setClassMetadataAsync = {
name: 'ɵsetClassMetadataAsync',
moduleName: CORE
};
static setClassDebugInfo = {
name: 'ɵsetClassDebugInfo',
moduleName: CORE
};
static queryRefresh = {
name: 'ɵɵqueryRefresh',
moduleName: CORE
};
static viewQuery = {
name: 'ɵɵviewQuery',
moduleName: CORE
};
static loadQuery = {
name: 'ɵɵloadQuery',
moduleName: CORE
};
static contentQuery = {
name: 'ɵɵcontentQuery',
moduleName: CORE
};
static viewQuerySignal = {
name: 'ɵɵviewQuerySignal',
moduleName: CORE
};
static contentQuerySignal = {
name: 'ɵɵcontentQuerySignal',
moduleName: CORE
};
static queryAdvance = {
name: 'ɵɵqueryAdvance',
moduleName: CORE
};
static twoWayProperty = {
name: 'ɵɵtwoWayProperty',
moduleName: CORE
};
static twoWayBindingSet = {
name: 'ɵɵtwoWayBindingSet',
moduleName: CORE
};
static twoWayListener = {
name: 'ɵɵtwoWayListener',
moduleName: CORE
};
static declareLet = {
name: 'ɵɵdeclareLet',
moduleName: CORE
};
static storeLet = {
name: 'ɵɵstoreLet',
moduleName: CORE
};
static readContextLet = {
name: 'ɵɵreadContextLet',
moduleName: CORE
};
static attachSourceLocations = {
name: 'ɵɵattachSourceLocations',
moduleName: CORE
};
static NgOnChangesFeature = {
name: 'ɵɵNgOnChangesFeature',
moduleName: CORE
};
static InheritDefinitionFeature = {
name: 'ɵɵInheritDefinitionFeature',
moduleName: CORE
};
static ProvidersFeature = {
name: 'ɵɵProvidersFeature',
moduleName: CORE
};
static HostDirectivesFeature = {
name: 'ɵɵHostDirectivesFeature',
moduleName: CORE
};
static ExternalStylesFeature = {
name: 'ɵɵExternalStylesFeature',
moduleName: CORE
};
static listener = {
name: 'ɵɵlistener',
moduleName: CORE
};
static getInheritedFactory = {
name: 'ɵɵgetInheritedFactory',
moduleName: CORE
};
static sanitizeHtml = {
name: 'ɵɵsanitizeHtml',
moduleName: CORE
};
static sanitizeStyle = {
name: 'ɵɵsanitizeStyle',
moduleName: CORE
};
static validateAttribute = {
name: 'ɵɵvalidateAttribute',
moduleName: CORE
};
static sanitizeResourceUrl = {
name: 'ɵɵsanitizeResourceUrl',
moduleName: CORE
};
static sanitizeScript = {
name: 'ɵɵsanitizeScript',
moduleName: CORE
};
static sanitizeUrl = {
name: 'ɵɵsanitizeUrl',
moduleName: CORE
};
static sanitizeUrlOrResourceUrl = {
name: 'ɵɵsanitizeUrlOrResourceUrl',
moduleName: CORE
};
static trustConstantHtml = {
name: 'ɵɵtrustConstantHtml',
moduleName: CORE
};
static trustConstantResourceUrl = {
name: 'ɵɵtrustConstantResourceUrl',
moduleName: CORE
};
static inputDecorator = {
name: 'Input',
moduleName: CORE
};
static outputDecorator = {
name: 'Output',
moduleName: CORE
};
static viewChildDecorator = {
name: 'ViewChild',
moduleName: CORE
};
static viewChildrenDecorator = {
name: 'ViewChildren',
moduleName: CORE
};
static contentChildDecorator = {
name: 'ContentChild',
moduleName: CORE
};
static contentChildrenDecorator = {
name: 'ContentChildren',
moduleName: CORE
};
static InputSignalBrandWriteType = {
name: 'ɵINPUT_SIGNAL_BRAND_WRITE_TYPE',
moduleName: CORE
};
static UnwrapDirectiveSignalInputs = {
name: 'ɵUnwrapDirectiveSignalInputs',
moduleName: CORE
};
static unwrapWritableSignal = {
name: 'ɵunwrapWritableSignal',
moduleName: CORE
};
static assertType = {
name: 'ɵassertType',
moduleName: CORE
};
}
const DASH_CASE_REGEXP = /-+([a-z0-9])/g;
function dashCaseToCamelCase(input) {
return input.replace(DASH_CASE_REGEXP, (...m) => m[1].toUpperCase());
}
function splitAtColon(input, defaultValues) {
return _splitAt(input, ':', defaultValues);
}
function splitAtPeriod(input, defaultValues) {
return _splitAt(input, '.', defaultValues);
}
function _splitAt(input, character, defaultValues) {
const characterIndex = input.indexOf(character);
if (characterIndex == -1) return defaultValues;
return [input.slice(0, characterIndex).trim(), input.slice(characterIndex + 1).trim()];
}
function noUndefined(val) {
return val === undefined ? null : val;
}
function escapeRegExp(s) {
return s.replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
}
function utf8Encode(str) {
let encoded = [];
for (let index = 0; index < str.length; index++) {
let codePoint = str.charCodeAt(index);
if (codePoint >= 0xd800 && codePoint <= 0xdbff && str.length > index + 1) {
const low = str.charCodeAt(index + 1);
if (low >= 0xdc00 && low <= 0xdfff) {
index++;
codePoint = (codePoint - 0xd800 << 10) + low - 0xdc00 + 0x10000;
}
}
if (codePoint <= 0x7f) {
encoded.push(codePoint);
} else if (codePoint <= 0x7ff) {
encoded.push(codePoint >> 6 & 0x1f | 0xc0, codePoint & 0x3f | 0x80);
} else if (codePoint <= 0xffff) {
encoded.push(codePoint >> 12 | 0xe0, codePoint >> 6 & 0x3f | 0x80, codePoint & 0x3f | 0x80);
} else if (codePoint <= 0x1fffff) {
encoded.push(codePoint >> 18 & 0x07 | 0xf0, codePoint >> 12 & 0x3f | 0x80, codePoint >> 6 & 0x3f | 0x80, codePoint & 0x3f | 0x80);
}
}
return encoded;
}
function stringify(token) {
if (typeof token === 'string') {
return token;
}
if (Array.isArray(token)) {
return `[${token.map(stringify).join(', ')}]`;
}
if (token == null) {
return '' + token;
}
const name = token.overriddenName || token.name;
if (name) {
return `${name}`;
}
if (!token.toString) {
return 'object';
}
const result = token.toString();
if (result == null) {
return '' + result;
}
const newLineIndex = result.indexOf('\n');
return newLineIndex >= 0 ? result.slice(0, newLineIndex) : result;
}
class Version {
full;
major;
minor;
patch;
constructor(full) {
this.full = full;
const splits = full.split('.');
this.major = splits[0];
this.minor = splits[1];
this.patch = splits.slice(2).join('.');
}
}
const _global = globalThis;
const V1_TO_18 = /^([1-9]|1[0-8])\./;
function getJitStandaloneDefaultForVersion(version) {
if (version.startsWith('0.')) {
return true;
}
if (V1_TO_18.test(version)) {
return false;
}
return true;
}
const VERSION$1 = 3;
const JS_B64_PREFIX = '# sourceMappingURL=data:application/json;base64,';
class SourceMapGenerator {
file;
sourcesContent = new Map();
lines = [];
lastCol0 = 0;
hasMappings = false;
constructor(file = null) {
this.file = file;
}
addSource(url, content = null) {
if (!this.sourcesContent.has(url)) {
this.sourcesContent.set(url, content);
}
return this;
}
addLine() {
this.lines.push([]);
this.lastCol0 = 0;
return this;
}
addMapping(col0, sourceUrl, sourceLine0, sourceCol0) {
if (!this.currentLine) {
throw new Error(`A line must be added before mappings can be added`);
}
if (sourceUrl != null && !this.sourcesContent.has(sourceUrl)) {
throw new Error(`Unknown source file "${sourceUrl}"`);
}
if (col0 == null) {
throw new Error(`The column in the generated code must be provided`);
}
if (col0 < this.lastCol0) {
throw new Error(`Mapping should be added in output order`);
}
if (sourceUrl && (sourceLine0 == null || sourceCol0 == null)) {
throw new Error(`The source location must be provided when a source url is provided`);
}
this.hasMappings = true;
this.lastCol0 = col0;
this.currentLine.push({
col0,
sourceUrl,
sourceLine0,
sourceCol0
});
return this;
}
get currentLine() {
return this.lines.slice(-1)[0];
}
toJSON() {
if (!this.hasMappings) {
return null;
}
const sourcesIndex = new Map();
const sources = [];
const sourcesContent = [];
Array.from(this.sourcesContent.keys()).forEach((url, i) => {
sourcesIndex.set(url, i);
sources.push(url);
sourcesContent.push(this.sourcesContent.get(url) || null);
});
let mappings = '';
let lastCol0 = 0;
let lastSourceIndex = 0;
let lastSourceLine0 = 0;
let lastSourceCol0 = 0;
this.lines.forEach(segments => {
lastCol0 = 0;
mappings += segments.map(segment => {
let segAsStr = toBase64VLQ(segment.col0 - lastCol0);
lastCol0 = segment.col0;
if (segment.sourceUrl != null) {
segAsStr += toBase64VLQ(sourcesIndex.get(segment.sourceUrl) - lastSourceIndex);
lastSourceIndex = sourcesIndex.get(segment.sourceUrl);
segAsStr += toBase64VLQ(segment.sourceLine0 - lastSourceLine0);
lastSourceLine0 = segment.sourceLine0;
segAsStr += toBase64VLQ(segment.sourceCol0 - lastSourceCol0);
lastSourceCol0 = segment.sourceCol0;
}
return segAsStr;
}).join(',');
mappings += ';';
});
mappings = mappings.slice(0, -1);
return {
'file': this.file || '',
'version': VERSION$1,
'sourceRoot': '',
'sources': sources,
'sourcesContent': sourcesContent,
'mappings': mappings
};
}
toJsComment() {
return this.hasMappings ? '//' + JS_B64_PREFIX + toBase64String(JSON.stringify(this, null, 0)) : '';
}
}
function toBase64String(value) {
let b64 = '';
const encoded = utf8Encode(value);
for (let i = 0; i < encoded.length;) {
const i1 = encoded[i++];
const i2 = i < encoded.length ? encoded[i++] : null;
const i3 = i < encoded.length ? encoded[i++] : null;
b64 += toBase64Digit(i1 >> 2);
b64 += toBase64Digit((i1 & 3) << 4 | (i2 === null ? 0 : i2 >> 4));
b64 += i2 === null ? '=' : toBase64Digit((i2 & 15) << 2 | (i3 === null ? 0 : i3 >> 6));
b64 += i2 === null || i3 === null ? '=' : toBase64Digit(i3 & 63);
}
return b64;
}
function toBase64VLQ(value) {
value = value < 0 ? (-value << 1) + 1 : value << 1;
let out = '';
do {
let digit = value & 31;
value = value >> 5;
if (value > 0) {
digit = digit | 32;
}
out += toBase64Digit(digit);
} while (value > 0);
return out;
}
const B64_DIGITS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
function toBase64Digit(value) {
if (value < 0 || value >= 64) {
throw new Error(`Can only encode value in the range [0, 63]`);
}
return B64_DIGITS[value];
}
const _SINGLE_QUOTE_ESCAPE_STRING_RE = /'|\\|\n|\r|\$/g;
const _LEGAL_IDENTIFIER_RE = /^[$A-Z_][0-9A-Z_$]*$/i;
const _INDENT_WITH = ' ';
class _EmittedLine {
indent;
partsLength = 0;
parts = [];
srcSpans = [];
constructor(indent) {
this.indent = indent;
}
}
const BINARY_OPERATORS$1 = new Map([[BinaryOperator.And, '&&'], [BinaryOperator.Bigger, '>'], [BinaryOperator.BiggerEquals, '>='], [BinaryOperator.BitwiseOr, '|'], [BinaryOperator.BitwiseAnd, '&'], [BinaryOperator.Divide, '/'], [BinaryOperator.Assign, '='], [BinaryOperator.Equals, '=='], [BinaryOperator.Identical, '==='], [BinaryOperator.Lower, '<'], [BinaryOperator.LowerEquals, '<='], [BinaryOperator.Minus, '-'], [BinaryOperator.Modulo, '%'], [BinaryOperator.Exponentiation, '**'], [BinaryOperator.Multiply, '*'], [BinaryOperator.NotEquals, '!='], [BinaryOperator.NotIdentical, '!=='], [BinaryOperator.NullishCoalesce, '??'], [BinaryOperator.Or, '||'], [BinaryOperator.Plus, '+'], [BinaryOperator.In, 'in'], [BinaryOperator.AdditionAssignment, '+='], [BinaryOperator.SubtractionAssignment, '-='], [BinaryOperator.MultiplicationAssignment, '*='], [BinaryOperator.DivisionAssignment, '/='], [BinaryOperator.RemainderAssignment, '%='], [BinaryOperator.ExponentiationAssignment, '**='], [BinaryOperator.AndAssignment, '&&='], [BinaryOperator.OrAssignment, '||='], [BinaryOperator.NullishCoalesceAssignment, '??=']]);
class EmitterVisitorContext {
_indent;
static createRoot() {
return new EmitterVisitorContext(0);
}
_lines;
constructor(_indent) {
this._indent = _indent;
this._lines = [new _EmittedLine(_indent)];
}
get _currentLine() {
return this._lines[this._lines.length - 1];
}
println(from, lastPart = '') {
this.print(from || null, lastPart, true);
}
lineIsEmpty() {
return this._currentLine.parts.length === 0;
}
lineLength() {
return this._currentLine.indent * _INDENT_WITH.length + this._currentLine.partsLength;
}
print(from, part, newLine = false) {
if (part.length > 0) {
this._currentLine.parts.push(part);
this._currentLine.partsLength += part.length;
this._currentLine.srcSpans.push(from && from.sourceSpan || null);
}
if (newLine) {
this._lines.push(new _EmittedLine(this._indent));
}
}
removeEmptyLastLine() {
if (this.lineIsEmpty()) {
this._lines.pop();
}
}
incIndent() {
this._indent++;
if (this.lineIsEmpty()) {
this._currentLine.indent = this._indent;
}
}
decIndent() {
this._indent--;
if (this.lineIsEmpty()) {
this._currentLine.indent = this._indent;
}
}
toSource() {
return this.sourceLines.map(l => l.parts.length > 0 ? _createIndent(l.indent) + l.parts.join('') : '').join('\n');
}
toSourceMapGenerator(genFilePath, startsAtLine = 0) {
const map = new SourceMapGenerator(genFilePath);
let firstOffsetMapped = false;
const mapFirstOffsetIfNeeded = () => {
if (!firstOffsetMapped) {
map.addSource(genFilePath, ' ').addMapping(0, genFilePath, 0, 0);
firstOffsetMapped = true;
}
};
for (let i = 0; i < startsAtLine; i++) {
map.addLine();
mapFirstOffsetIfNeeded();
}
this.sourceLines.forEach((line, lineIdx) => {
map.addLine();
const spans = line.srcSpans;
const parts = line.parts;
let col0 = line.indent * _INDENT_WITH.length;
let spanIdx = 0;
while (spanIdx < spans.length && !spans[spanIdx]) {
col0 += parts[spanIdx].length;
spanIdx++;
}
if (spanIdx < spans.length && lineIdx === 0 && col0 === 0) {
firstOffsetMapped = true;
} else {
mapFirstOffsetIfNeeded();
}
while (spanIdx < spans.length) {
const span = spans[spanIdx];
const source = span.start.file;
const sourceLine = span.start.line;
const sourceCol = span.start.col;
map.addSource(source.url, source.content).addMapping(col0, source.url, sourceLine, sourceCol);
col0 += parts[spanIdx].length;
spanIdx++;
while (spanIdx < spans.length && (span === spans[spanIdx] || !spans[spanIdx])) {
col0 += parts[spanIdx].length;
spanIdx++;
}
}
});
return map;
}
spanOf(line, column) {
const emittedLine = this._lines[line];
if (emittedLine) {
let columnsLeft = column - _createIndent(emittedLine.indent).length;
for (let partIndex = 0; partIndex < emittedLine.parts.length; partIndex++) {
const part = emittedLine.parts[partIndex];
if (part.length > columnsLeft) {
return emittedLine.srcSpans[partIndex];
}
columnsLeft -= part.length;
}
}
return null;
}
get sourceLines() {
if (this._lines.length && this._lines[this._lines.length - 1].parts.length === 0) {
return this._lines.slice(0, -1);
}
return this._lines;
}
}
class AbstractEmitterVisitor {
_escapeDollarInStrings;
lastIfCondition = null;
constructor(_escapeDollarInStrings) {
this._escapeDollarInStrings = _escapeDollarInStrings;
}
printLeadingComments(stmt, ctx) {
if (stmt.leadingComments === undefined) {
return;
}
for (const comment of stmt.leadingComments) {
if (comment instanceof JSDocComment) {
ctx.print(stmt, `/*${comment.toString()}*/`, comment.trailingNewline);
} else {
if (comment.multiline) {
ctx.print(stmt, `/* ${comment.text} */`, comment.trailingNewline);
} else {
comment.text.split('\n').forEach(line => {
ctx.println(stmt, `// ${line}`);
});
}
}
}
}
visitExpressionStmt(stmt, ctx) {
this.printLeadingComments(stmt, ctx);
stmt.expr.visitExpression(this, ctx);
ctx.println(stmt, ';');
return null;
}
visitReturnStmt(stmt, ctx) {
this.printLeadingComments(stmt, ctx);
ctx.print(stmt, `return `);
stmt.value.visitExpression(this, ctx);
ctx.println(stmt, ';');
return null;
}
visitIfStmt(stmt, ctx) {
this.printLeadingComments(stmt, ctx);
ctx.print(stmt, `if (`);
this.lastIfCondition = stmt.condition;
stmt.condition.visitExpression(this, ctx);
this.lastIfCondition = null;
ctx.print(stmt, `) {`);
const hasElseCase = stmt.falseCase != null && stmt.falseCase.length > 0;
if (stmt.trueCase.length <= 1 && !hasElseCase) {
ctx.print(stmt, ` `);
this.visitAllStatements(stmt.trueCase, ctx);
ctx.removeEmptyLastLine();
ctx.print(stmt, ` `);
} else {
ctx.println();
ctx.incIndent();
this.visitAllStatements(stmt.trueCase, ctx);
ctx.decIndent();
if (hasElseCase) {
ctx.println(stmt, `} else {`);
ctx.incIndent();
this.visitAllStatements(stmt.falseCase, ctx);
ctx.decIndent();
}
}
ctx.println(stmt, `}`);
return null;
}
visitInvokeFunctionExpr(expr, ctx) {
const shouldParenthesize = expr.fn instanceof ArrowFunctionExpr;
if (shouldParenthesize) {
ctx.print(expr.fn, '(');
}
expr.fn.visitExpression(this, ctx);
if (shouldParenthesize) {
ctx.print(expr.fn, ')');
}
ctx.print(expr, `(`);
this.visitAllExpressions(expr.args, ctx, ',');
ctx.print(expr, `)`);
return null;
}
visitTaggedTemplateLiteralExpr(expr, ctx) {
expr.tag.visitExpression(this, ctx);
expr.template.visitExpression(this, ctx);
return null;
}
visitTemplateLiteralExpr(expr, ctx) {
ctx.print(expr, '`');
for (let i = 0; i < expr.elements.length; i++) {
expr.elements[i].visitExpression(this, ctx);
const expression = i < expr.expressions.length ? expr.expressions[i] : null;
if (expression !== null) {
ctx.print(expression, '${');
expression.visitExpression(this, ctx);
ctx.print(expression, '}');
}
}
ctx.print(expr, '`');
}
visitTemplateLiteralElementExpr(expr, ctx) {
ctx.print(expr, expr.rawText);
}
visitWrappedNodeExpr(ast, ctx) {
throw new Error('Abstract emitter cannot visit WrappedNodeExpr.');
}
visitTypeofExpr(expr, ctx) {
ctx.print(expr, 'typeof ');
expr.expr.visitExpression(this, ctx);
}
visitVoidExpr(expr, ctx) {
ctx.print(expr, 'void ');
expr.expr.visitExpression(this, ctx);
}
visitReadVarExpr(ast, ctx) {
ctx.print(ast, ast.name);
return null;
}
visitInstantiateExpr(ast, ctx) {
ctx.print(ast, `new `);
ast.classExpr.visitExpression(this, ctx);
ctx.print(ast, `(`);
this.visitAllExpressions(ast.args, ctx, ',');
ctx.print(ast, `)`);
return null;
}
visitLiteralExpr(ast, ctx) {
const value = ast.value;
if (typeof value === 'string') {
ctx.print(ast, escapeIdentifier(value, this._escapeDollarInStrings));
} else {
ctx.print(ast, `${value}`);
}
return null;
}
visitRegularExpressionLiteral(ast, ctx) {
ctx.print(ast, `/${ast.body}/${ast.flags || ''}`);
return null;
}
visitLocalizedString(ast, ctx) {
const head = ast.serializeI18nHead();
ctx.print(ast, '$localize `' + head.raw);
for (let i = 1; i < ast.messageParts.length; i++) {
ctx.print(ast, '${');
ast.expressions[i - 1].visitExpression(this, ctx);
ctx.print(ast, `}${ast.serializeI18nTemplatePart(i).raw}`);
}
ctx.print(ast, '`');
return null;
}
visitConditionalExpr(ast, ctx) {
ctx.print(ast, `(`);
ast.condition.visitExpression(this, ctx);
ctx.print(ast, '? ');
ast.trueCase.visitExpression(this, ctx);
ctx.print(ast, ': ');
ast.falseCase.visitExpression(this, ctx);
ctx.print(ast, `)`);
return null;
}
visitDynamicImportExpr(ast, ctx) {
ctx.print(ast, `import(${ast.url})`);
}
visitNotExpr(ast, ctx) {
ctx.print(ast, '!');
ast.condition.visitExpression(this, ctx);
return null;
}
visitUnaryOperatorExpr(ast, ctx) {
let opStr;
switch (ast.operator) {
case UnaryOperator.Plus:
opStr = '+';
break;
case UnaryOperator.Minus:
opStr = '-';
break;
default:
throw new Error(`Unknown operator ${ast.operator}`);
}
const parens = ast !== this.lastIfCondition;
if (parens) ctx.print(ast, `(`);
ctx.print(ast, opStr);
ast.expr.visitExpression(this, ctx);
if (parens) ctx.print(ast, `)`);
return null;
}
visitBinaryOperatorExpr(ast, ctx) {
const operator = BINARY_OPERATORS$1.get(ast.operator);
if (!operator) {
throw new Error(`Unknown operator ${ast.operator}`);
}
const parens = ast !== this.lastIfCondition;
if (parens) ctx.print(ast, `(`);
ast.lhs.visitExpression(this, ctx);
ctx.print(ast, ` ${operator} `);
ast.rhs.visitExpression(this, ctx);
if (parens) ctx.print(ast, `)`);
return null;
}
visitReadPropExpr(ast, ctx) {
ast.receiver.visitExpression(this, ctx);
ctx.print(ast, `.`);
ctx.print(ast, ast.name);
return null;
}
visitReadKeyExpr(ast, ctx) {
ast.receiver.visitExpression(this, ctx);
ctx.print(ast, `[`);
ast.index.visitExpression(this, ctx);
ctx.print(ast, `]`);
return null;
}
visitLiteralArrayExpr(ast, ctx) {
ctx.print(ast, `[`);
this.visitAllExpressions(ast.entries, ctx, ',');
ctx.print(ast, `]`);
return null;
}
visitLiteralMapExpr(ast, ctx) {
ctx.print(ast, `{`);
this.visitAllObjects(entry => {
if (entry instanceof LiteralMapSpreadAssignment) {
ctx.print(ast, '...');
entry.expression.visitExpression(this, ctx);
} else {
ctx.print(ast, `${escapeIdentifier(entry.key, this._escapeDollarInStrings, entry.quoted)}:`);
entry.value.visitExpression(this, ctx);
}
}, ast.entries, ctx, ',');
ctx.print(ast, `}`);
return null;
}
visitCommaExpr(ast, ctx) {
ctx.print(ast, '(');
this.visitAllExpressions(ast.parts, ctx, ',');
ctx.print(ast, ')');
return null;
}
visitParenthesizedExpr(ast, ctx) {
ast.expr.visitExpression(this, ctx);
}
visitSpreadElementExpr(ast, ctx) {
ctx.print(ast, '...');
ast.expression.visitExpression(this, ctx);
}
visitAllExpressions(expressions, ctx, separator) {
this.visitAllObjects(expr => expr.visitExpression(this, ctx), expressions, ctx, separator);
}
visitAllObjects(handler, expressions, ctx, separator) {
let incrementedIndent = false;
for (let i = 0; i < expressions.length; i++) {
if (i > 0) {
if (ctx.lineLength() > 80) {
ctx.print(null, separator, true);
if (!incrementedIndent) {
ctx.incIndent();
ctx.incIndent();
incrementedIndent = true;
}
} else {
ctx.print(null, separator, false);
}
}
handler(expressions[i]);
}
if (incrementedIndent) {
ctx.decIndent();
ctx.decIndent();
}
}
visitAllStatements(statements, ctx) {
statements.forEach(stmt => stmt.visitStatement(this, ctx));
}
}
function escapeIdentifier(input, escapeDollar, alwaysQuote = true) {
if (input == null) {
return null;
}
const body = input.replace(_SINGLE_QUOTE_ESCAPE_STRING_RE, (...match) => {
if (match[0] == '$') {
return escapeDollar ? '\\$' : '$';
} else if (match[0] == '\n') {
return '\\n';
} else if (match[0] == '\r') {
return '\\r';
} else {
return `\\${match[0]}`;
}
});
const requiresQuotes = alwaysQuote || !_LEGAL_IDENTIFIER_RE.test(body);
return requiresQuotes ? `'${body}'` : body;
}
function _createIndent(count) {
let res = '';
for (let i = 0; i < count; i++) {
res += _INDENT_WITH;
}
return res;
}
function typeWithParameters(type, numParams) {
if (numParams === 0) {
return expressionType(type);
}
const params = [];
for (let i = 0; i < numParams; i++) {
params.push(DYNAMIC_TYPE);
}
return expressionType(type, undefined, params);
}
function getSafePropertyAccessString(accessor, name) {
const escapedName = escapeIdentifier(name, false, false);
return escapedName !== name ? `${accessor}[${escapedName}]` : `${accessor}.${name}`;
}
function jitOnlyGuardedExpression(expr) {
return guardedExpression('ngJitMode', expr);
}
function devOnlyGuardedExpression(expr) {
return guardedExpression('ngDevMode', expr);
}
function guardedExpression(guard, expr) {
const guardExpr = new ExternalExpr({
name: guard,
moduleName: null
});
const guardNotDefined = new BinaryOperatorExpr(BinaryOperator.Identical, new TypeofExpr(guardExpr), literal('undefined'));
const guardUndefinedOrTrue = new BinaryOperatorExpr(BinaryOperator.Or, guardNotDefined, guardExpr, undefined, undefined);
return new BinaryOperatorExpr(BinaryOperator.And, guardUndefinedOrTrue, expr);
}
function wrapReference(value) {
const wrapped = new WrappedNodeExpr(value);
return {
value: wrapped,
type: wrapped
};
}
function refsToArray(refs, shouldForwardDeclare) {
const values = literalArr(refs.map(ref => ref.value));
return shouldForwardDeclare ? arrowFn([], values) : values;
}
function createMayBeForwardRefExpression(expression, forwardRef) {
return {
expression,
forwardRef
};
}
function convertFromMaybeForwardRefExpression({
expression,
forwardRef
}) {
switch (forwardRef) {
case 0:
case 1:
return expression;
case 2:
return generateForwardRef(expression);
}
}
function generateForwardRef(expr) {
return importExpr(Identifiers.forwardRef).callFn([arrowFn([], expr)]);
}
var R3FactoryDelegateType;
(function (R3FactoryDelegateType) {
R3FactoryDelegateType[R3FactoryDelegateType["Class"] = 0] = "Class";
R3FactoryDelegateType[R3FactoryDelegateType["Function"] = 1] = "Function";
})(R3FactoryDelegateType || (R3FactoryDelegateType = {}));
function compileFactoryFunction(meta) {
const t = variable('__ngFactoryType__');
let baseFactoryVar = null;
const typeForCtor = !isDelegatedFactoryMetadata(meta) ? new BinaryOperatorExpr(BinaryOperator.Or, t, meta.type.value) : t;
let ctorExpr = null;
if (meta.deps !== null) {
if (meta.deps !== 'invalid') {
ctorExpr = new InstantiateExpr(typeForCtor, injectDependencies(meta.deps, meta.target));
}
} else {
baseFactoryVar = variable(`ɵ${meta.name}_BaseFactory`);
ctorExpr = baseFactoryVar.callFn([typeForCtor]);
}
const body = [];
let retExpr = null;
function makeConditionalFactory(nonCtorExpr) {
const r = variable('__ngConditionalFactory__');
body.push(new DeclareVarStmt(r.name, NULL_EXPR, INFERRED_TYPE));
const ctorStmt = ctorExpr !== null ? r.set(ctorExpr).toStmt() : importExpr(Identifiers.invalidFactory).callFn([]).toStmt();
body.push(ifStmt(t, [ctorStmt], [r.set(nonCtorExpr).toStmt()]));
return r;
}
if (isDelegatedFactoryMetadata(meta)) {
const delegateArgs = injectDependencies(meta.delegateDeps, meta.target);
const factoryExpr = new (meta.delegateType === R3FactoryDelegateType.Class ? InstantiateExpr : InvokeFunctionExpr)(meta.delegate, delegateArgs);
retExpr = makeConditionalFactory(factoryExpr);
} else if (isExpressionFactoryMetadata(meta)) {
retExpr = makeConditionalFactory(meta.expression);
} else {
retExpr = ctorExpr;
}
if (retExpr === null) {
body.push(importExpr(Identifiers.invalidFactory).callFn([]).toStmt());
} else if (baseFactoryVar !== null) {
const getInheritedFactoryCall = importExpr(Identifiers.getInheritedFactory).callFn([meta.type.value]);
const baseFactory = new BinaryOperatorExpr(BinaryOperator.Or, baseFactoryVar, baseFactoryVar.set(getInheritedFactoryCall));
body.push(new ReturnStatement(baseFactory.callFn([typeForCtor])));
} else {
body.push(new ReturnStatement(retExpr));
}
let factoryFn = fn([new FnParam(t.name, DYNAMIC_TYPE)], body, INFERRED_TYPE, undefined, `${meta.name}_Factory`);
if (baseFactoryVar !== null) {
factoryFn = arrowFn([], [new DeclareVarStmt(baseFactoryVar.name), new ReturnStatement(factoryFn)]).callFn([], undefined, true);
}
return {
expression: factoryFn,
statements: [],
type: createFactoryType(meta)
};
}
function createFactoryType(meta) {
const ctorDepsType = meta.deps !== null && meta.deps !== 'invalid' ? createCtorDepsType(meta.deps) : NONE_TYPE;
return expressionType(importExpr(Identifiers.FactoryDeclaration, [typeWithParameters(meta.type.type, meta.typeArgumentCount), ctorDepsType]));
}
function injectDependencies(deps, target) {
return deps.map((dep, index) => compileInjectDependency(dep, target, index));
}
function compileInjectDependency(dep, target, index) {
if (dep.token === null) {
return importExpr(Identifiers.invalidFactoryDep).callFn([literal(index)]);
} else if (dep.attributeNameType === null) {
const flags = 0 | (dep.self ? 2 : 0) | (dep.skipSelf ? 4 : 0) | (dep.host ? 1 : 0) | (dep.optional ? 8 : 0) | (target === FactoryTarget.Pipe ? 16 : 0);
let flagsParam = flags !== 0 || dep.optional ? literal(flags) : null;
const injectArgs = [dep.token];
if (flagsParam) {
injectArgs.push(flagsParam);
}
const injectFn = getInjectFn(target);
return importExpr(injectFn).callFn(injectArgs);
} else {
return importExpr(Identifiers.injectAttribute).callFn([dep.token]);
}
}
function createCtorDepsType(deps) {
let hasTypes = false;
const attributeTypes = deps.map(dep => {
const type = createCtorDepType(dep);
if (type !== null) {
hasTypes = true;
return type;
} else {
return literal(null);
}
});
if (hasTypes) {
return expressionType(literalArr(attributeTypes));
} else {
return NONE_TYPE;
}
}
function createCtorDepType(dep) {
const entries = [];
if (dep.attributeNameType !== null) {
entries.push({
key: 'attribute',
value: dep.attributeNameType,
quoted: false
});
}
if (dep.optional) {
entries.push({
key: 'optional',
value: literal(true),
quoted: false
});
}
if (dep.host) {
entries.push({
key: 'host',
value: literal(true),
quoted: false
});
}
if (dep.self) {
entries.push({
key: 'self',
value: literal(true),
quoted: false
});
}
if (dep.skipSelf) {
entries.push({
key: 'skipSelf',
value: literal(true),
quoted: false
});
}
return entries.length > 0 ? literalMap(entries) : null;
}
function isDelegatedFactoryMetadata(meta) {
return meta.delegateType !== undefined;
}
function isExpressionFactoryMetadata(meta) {
return meta.expression !== undefined;
}
function getInjectFn(target) {
switch (target) {
case FactoryTarget.Component:
case FactoryTarget.Directive:
case FactoryTarget.Pipe:
return Identifiers.directiveInject;
case FactoryTarget.NgModule:
case FactoryTarget.Injectable:
default:
return Identifiers.inject;
}
}
class ParseSpan {
start;
end;
constructor(start, end) {
this.start = start;
this.end = end;
}
toAbsolute(absoluteOffset) {
return new AbsoluteSourceSpan(absoluteOffset + this.start, absoluteOffset + this.end);
}
}
class AST {
span;
sourceSpan;
constructor(span, sourceSpan) {
this.span = span;
this.sourceSpan = sourceSpan;
}
toString() {
return 'AST';
}
}
class ASTWithName extends AST {
nameSpan;
constructor(span, sourceSpan, nameSpan) {
super(span, sourceSpan);
this.nameSpan = nameSpan;
}
}
let EmptyExpr$1 = class EmptyExpr extends AST {
visit(visitor, context = null) {}
};
class ImplicitReceiver extends AST {
visit(visitor, context = null) {
return visitor.visitImplicitReceiver(this, context);
}
}
class ThisReceiver extends AST {
visit(visitor, context = null) {
return visitor.visitThisReceiver?.(this, context);
}
}
class Chain extends AST {
expressions;
constructor(span, sourceSpan, expressions) {
super(span, sourceSpan);
this.expressions = expressions;
}
visit(visitor, context = null) {
return visitor.visitChain(this, context);
}
}
class Conditional extends AST {
condition;
trueExp;
falseExp;
constructor(span, sourceSpan, condition, trueExp, falseExp) {
super(span, sourceSpan);
this.condition = condition;
this.trueExp = trueExp;
this.falseExp = falseExp;
}
visit(visitor, context = null) {
return visitor.visitConditional(this, context);
}
}
class PropertyRead extends ASTWithName {
receiver;
name;
constructor(span, sourceSpan, nameSpan, receiver, name) {
super(span, sourceSpan, nameSpan);
this.receiver = receiver;
this.name = name;
}
visit(visitor, context = null) {
return visitor.visitPropertyRead(this, context);
}
}
class SafePropertyRead extends ASTWithName {
receiver;
name;
constructor(span, sourceSpan, nameSpan, receiver, name) {
super(span, sourceSpan, nameSpan);
this.receiver = receiver;
this.name = name;
}
visit(visitor, context = null) {
return visitor.visitSafePropertyRead(this, context);
}
}
class KeyedRead extends AST {
receiver;
key;
constructor(span, sourceSpan, receiver, key) {
super(span, sourceSpan);
this.receiver = receiver;
this.key = key;
}
visit(visitor, context = null) {
return visitor.visitKeyedRead(this, context);
}
}
class SafeKeyedRead extends AST {
receiver;
key;
constructor(span, sourceSpan, receiver, key) {
super(span, sourceSpan);
this.receiver = receiver;
this.key = key;
}
visit(visitor, context = null) {
return visitor.visitSafeKeyedRead(this, context);
}
}
var BindingPipeType;
(function (BindingPipeType) {
BindingPipeType[BindingPipeType["ReferencedByName"] = 0] = "ReferencedByName";
BindingPipeType[BindingPipeType["ReferencedDirectly"] = 1] = "ReferencedDirectly";
})(BindingPipeType || (BindingPipeType = {}));
class BindingPipe extends ASTWithName {
exp;
name;
args;
type;
constructor(span, sourceSpan, exp, name, args, type, nameSpan) {
super(span, sourceSpan, nameSpan);
this.exp = exp;
this.name = name;
this.args = args;
this.type = type;
}
visit(visitor, context = null) {
return visitor.visitPipe(this, context);
}
}
class LiteralPrimitive extends AST {
value;
constructor(span, sourceSpan, value) {
super(span, sourceSpan);
this.value = value;
}
visit(visitor, context = null) {
return visitor.visitLiteralPrimitive(this, context);
}
}
class LiteralArray extends AST {
expressions;
constructor(span, sourceSpan, expressions) {
super(span, sourceSpan);
this.expressions = expressions;
}
visit(visitor, context = null) {
return visitor.visitLiteralArray(this, context);
}
}
class SpreadElement extends AST {
expression;
constructor(span, sourceSpan, expression) {
super(span, sourceSpan);
this.expression = expression;
}
visit(visitor, context = null) {
return visitor.visitSpreadElement(this, context);
}
}
class LiteralMap extends AST {
keys;
values;
constructor(span, sourceSpan, keys, values) {
super(span, sourceSpan);
this.keys = keys;
this.values = values;
}
visit(visitor, context = null) {
return visitor.visitLiteralMap(this, context);
}
}
let Interpolation$1 = class Interpolation extends AST {
strings;
expressions;
constructor(span, sourceSpan, strings, expressions) {
super(span, sourceSpan);
this.strings = strings;
this.expressions = expressions;
}
visit(visitor, context = null) {
return visitor.visitInterpolation(this, context);
}
};
class Binary extends AST {
operation;
left;
right;
constructor(span, sourceSpan, operation, left, right) {
super(span, sourceSpan);
this.operation = operation;
this.left = left;
this.right = right;
}
visit(visitor, context = null) {
return visitor.visitBinary(this, context);
}
static isAssignmentOperation(op) {
return op === '=' || op === '+=' || op === '-=' || op === '*=' || op === '/=' || op === '%=' || op === '**=' || op === '&&=' || op === '||=' || op === '??=';
}
}
class Unary extends Binary {
operator;
expr;
left = null;
right = null;
operation = null;
static createMinus(span, sourceSpan, expr) {
return new Unary(span, sourceSpan, '-', expr, '-', new LiteralPrimitive(span, sourceSpan, 0), expr);
}
static createPlus(span, sourceSpan, expr) {
return new Unary(span, sourceSpan, '+', expr, '-', expr, new LiteralPrimitive(span, sourceSpan, 0));
}
constructor(span, sourceSpan, operator, expr, binaryOp, binaryLeft, binaryRight) {
super(span, sourceSpan, binaryOp, binaryLeft, binaryRight);
this.operator = operator;
this.expr = expr;
}
visit(visitor, context = null) {
if (visitor.visitUnary !== undefined) {
return visitor.visitUnary(this, context);
}
return visitor.visitBinary(this, context);
}
}
class PrefixNot extends AST {
expression;
constructor(span, sourceSpan, expression) {
super(span, sourceSpan);
this.expression = expression;
}
visit(visitor, context = null) {
return visitor.visitPrefixNot(this, context);
}
}
class TypeofExpression extends AST {
expression;
constructor(span, sourceSpan, expression) {
super(span, sourceSpan);
this.expression = expression;
}
visit(visitor, context = null) {
return visitor.visitTypeofExpression(this, context);
}
}
class VoidExpression extends AST {
expression;
constructor(span, sourceSpan, expression) {
super(span, sourceSpan);
this.expression = expression;
}
visit(visitor, context = null) {
return visitor.visitVoidExpression(this, context);
}
}
class NonNullAssert extends AST {
expression;
constructor(span, sourceSpan, expression) {
super(span, sourceSpan);
this.expression = expression;
}
visit(visitor, context = null) {
return visitor.visitNonNullAssert(this, context);
}
}
class Call extends AST {
receiver;
args;
argumentSpan;
constructor(span, sourceSpan, receiver, args, argumentSpan) {
super(span, sourceSpan);
this.receiver = receiver;
this.args = args;
this.argumentSpan = argumentSpan;
}
visit(visitor, context = null) {
return visitor.visitCall(this, context);
}
}
class SafeCall extends AST {
receiver;
args;
argumentSpan;
constructor(span, sourceSpan, receiver, args, argumentSpan) {
super(span, sourceSpan);
this.receiver = receiver;
this.args = args;
this.argumentSpan = argumentSpan;
}
visit(visitor, context = null) {
return visitor.visitSafeCall(this, context);
}
}
class TaggedTemplateLiteral extends AST {
tag;
template;
constructor(span, sourceSpan, tag, template) {
super(span, sourceSpan);
this.tag = tag;
this.template = template;
}
visit(visitor, context) {
return visitor.visitTaggedTemplateLiteral(this, context);
}
}
class TemplateLiteral extends AST {
elements;
expressions;
constructor(span, sourceSpan, elements, expressions) {
super(span, sourceSpan);
this.elements = elements;
this.expressions = expressions;
}
visit(visitor, context) {
return visitor.visitTemplateLiteral(this, context);
}
}
class TemplateLiteralElement extends AST {
text;
constructor(span, sourceSpan, text) {
super(span, sourceSpan);
this.text = text;
}
visit(visitor, context) {
return visitor.visitTemplateLiteralElement(this, context);
}
}
class ParenthesizedExpression extends AST {
expression;
constructor(span, sourceSpan, expression) {
super(span, sourceSpan);
this.expression = expression;
}
visit(visitor, context) {
return visitor.visitParenthesizedExpression(this, context);
}
}
class RegularExpressionLiteral extends AST {
body;
flags;
constructor(span, sourceSpan, body, flags) {
super(span, sourceSpan);
this.body = body;
this.flags = flags;
}
visit(visitor, context) {
return visitor.visitRegularExpressionLiteral(this, context);
}
}
class AbsoluteSourceSpan {
start;
end;
constructor(start, end) {
this.start = start;
this.end = end;
}
}
class ASTWithSource extends AST {
ast;
source;
location;
errors;
constructor(ast, source, location, absoluteOffset, errors) {
super(new ParseSpan(0, source === null ? 0 : source.length), new AbsoluteSourceSpan(absoluteOffset, source === null ? absoluteOffset : absoluteOffset + source.length));
this.ast = ast;
this.source = source;
this.location = location;
this.errors = errors;
}
visit(visitor, context = null) {
if (visitor.visitASTWithSource) {
return visitor.visitASTWithSource(this, context);
}
return this.ast.visit(visitor, context);
}
toString() {
return `${this.source} in ${this.location}`;
}
}
class VariableBinding {
sourceSpan;
key;
value;
constructor(sourceSpan, key, value) {
this.sourceSpan = sourceSpan;
this.key = key;
this.value = value;
}
}
class ExpressionBinding {
sourceSpan;
key;
value;
constructor(sourceSpan, key, value) {
this.sourceSpan = sourceSpan;
this.key = key;
this.value = value;
}
}
class RecursiveAstVisitor {
visit(ast, context) {
ast.visit(this, context);
}
visitUnary(ast, context) {
this.visit(ast.expr, context);
}
visitBinary(ast, context) {
this.visit(ast.left, context);
this.visit(ast.right, context);
}
visitChain(ast, context) {
this.visitAll(ast.expressions, context);
}
visitConditional(ast, context) {
this.visit(ast.condition, context);
this.visit(ast.trueExp, context);
this.visit(ast.falseExp, context);
}
visitPipe(ast, context) {
this.visit(ast.exp, context);
this.visitAll(ast.args, context);
}
visitImplicitReceiver(ast, context) {}
visitThisReceiver(ast, context) {}
visitInterpolation(ast, context) {
this.visitAll(ast.expressions, context);
}
visitKeyedRead(ast, context) {
this.visit(ast.receiver, context);
this.visit(ast.key, context);
}
visitLiteralArray(ast, context) {
this.visitAll(ast.expressions, context);
}
visitLiteralMap(ast, context) {
this.visitAll(ast.values, context);
}
visitLiteralPrimitive(ast, context) {}
visitPrefixNot(ast, context) {
this.visit(ast.expression, context);
}
visitTypeofExpression(ast, context) {
this.visit(ast.expression, context);
}
visitVoidExpression(ast, context) {
this.visit(ast.expression, context);
}
visitNonNullAssert(ast, context) {
this.visit(ast.expression, context);
}
visitPropertyRead(ast, context) {
this.visit(ast.receiver, context);
}
visitSafePropertyRead(ast, context) {
this.visit(ast.receiver, context);
}
visitSafeKeyedRead(ast, context) {
this.visit(ast.receiver, context);
this.visit(ast.key, context);
}
visitCall(ast, context) {
this.visit(ast.receiver, context);
this.visitAll(ast.args, context);
}
visitSafeCall(ast, context) {
this.visit(ast.receiver, context);
this.visitAll(ast.args, context);
}
visitTemplateLiteral(ast, context) {
for (let i = 0; i < ast.elements.length; i++) {
this.visit(ast.elements[i], context);
const expression = i < ast.expressions.length ? ast.expressions[i] : null;
if (expression !== null) {
this.visit(expression, context);
}
}
}
visitTemplateLiteralElement(ast, context) {}
visitTaggedTemplateLiteral(ast, context) {
this.visit(ast.tag, context);
this.visit(ast.template, context);
}
visitParenthesizedExpression(ast, context) {
this.visit(ast.expression, context);
}
visitRegularExpressionLiteral(ast, context) {}
visitSpreadElement(ast, context) {
this.visit(ast.expression, context);
}
visitAll(asts, context) {
for (const ast of asts) {
this.visit(ast, context);
}
}
}
class ParsedProperty {
name;
expression;
type;
sourceSpan;
keySpan;
valueSpan;
isLiteral;
isLegacyAnimation;
isAnimation;
constructor(name, expression, type, sourceSpan, keySpan, valueSpan) {
this.name = name;
this.expression = expression;
this.type = type;
this.sourceSpan = sourceSpan;
this.keySpan = keySpan;
this.valueSpan = valueSpan;
this.isLiteral = this.type === ParsedPropertyType.LITERAL_ATTR;
this.isLegacyAnimation = this.type === ParsedPropertyType.LEGACY_ANIMATION;
this.isAnimation = this.type === ParsedPropertyType.ANIMATION;
}
}
var ParsedPropertyType;
(function (ParsedPropertyType) {
ParsedPropertyType[ParsedPropertyType["DEFAULT"] = 0] = "DEFAULT";
ParsedPropertyType[ParsedPropertyType["LITERAL_ATTR"] = 1] = "LITERAL_ATTR";
ParsedPropertyType[ParsedPropertyType["LEGACY_ANIMATION"] = 2] = "LEGACY_ANIMATION";
ParsedPropertyType[ParsedPropertyType["TWO_WAY"] = 3] = "TWO_WAY";
ParsedPropertyType[ParsedPropertyType["ANIMATION"] = 4] = "ANIMATION";
})(ParsedPropertyType || (ParsedPropertyType = {}));
var ParsedEventType;
(function (ParsedEventType) {
ParsedEventType[ParsedEventType["Regular"] = 0] = "Regular";
ParsedEventType[ParsedEventType["LegacyAnimation"] = 1] = "LegacyAnimation";
ParsedEventType[ParsedEventType["TwoWay"] = 2] = "TwoWay";
ParsedEventType[ParsedEventType["Animation"] = 3] = "Animation";
})(ParsedEventType || (ParsedEventType = {}));
class ParsedEvent {
name;
targetOrPhase;
type;
handler;
sourceSpan;
handlerSpan;
keySpan;
constructor(name, targetOrPhase, type, handler, sourceSpan, handlerSpan, keySpan) {
this.name = name;
this.targetOrPhase = targetOrPhase;
this.type = type;
this.handler = handler;
this.sourceSpan = sourceSpan;
this.handlerSpan = handlerSpan;
this.keySpan = keySpan;
}
}
class ParsedVariable {
name;
value;
sourceSpan;
keySpan;
valueSpan;
constructor(name, value, sourceSpan, keySpan, valueSpan) {
this.name = name;
this.value = value;
this.sourceSpan = sourceSpan;
this.keySpan = keySpan;
this.valueSpan = valueSpan;
}
}
var BindingType;
(function (BindingType) {
BindingType[BindingType["Property"] = 0] = "Property";
BindingType[BindingType["Attribute"] = 1] = "Attribute";
BindingType[BindingType["Class"] = 2] = "Class";
BindingType[BindingType["Style"] = 3] = "Style";
BindingType[BindingType["LegacyAnimation"] = 4] = "LegacyAnimation";
BindingType[BindingType["TwoWay"] = 5] = "TwoWay";
BindingType[BindingType["Animation"] = 6] = "Animation";
})(BindingType || (BindingType = {}));
class BoundElementProperty {
name;
type;
securityContext;
value;
unit;
sourceSpan;
keySpan;
valueSpan;
constructor(name, type, securityContext, value, unit, sourceSpan, keySpan, valueSpan) {
this.name = name;
this.type = type;
this.securityContext = securityContext;
this.value = value;
this.unit = unit;
this.sourceSpan = sourceSpan;
this.keySpan = keySpan;
this.valueSpan = valueSpan;
}
}
var TagContentType;
(function (TagContentType) {
TagContentType[TagContentType["RAW_TEXT"] = 0] = "RAW_TEXT";
TagContentType[TagContentType["ESCAPABLE_RAW_TEXT"] = 1] = "ESCAPABLE_RAW_TEXT";
TagContentType[TagContentType["PARSABLE_DATA"] = 2] = "PARSABLE_DATA";
})(TagContentType || (TagContentType = {}));
function splitNsName(elementName, fatal = true) {
if (elementName[0] != ':') {
return [null, elementName];
}
const colonIndex = elementName.indexOf(':', 1);
if (colonIndex === -1) {
if (fatal) {
throw new Error(`Unsupported format "${elementName}" expecting ":namespace:name"`);
} else {
return [null, elementName];
}
}
return [elementName.slice(1, colonIndex), elementName.slice(colonIndex + 1)];
}
function isNgContainer(tagName) {
return splitNsName(tagName)[1] === 'ng-container';
}
function isNgContent(tagName) {
return splitNsName(tagName)[1] === 'ng-content';
}
function isNgTemplate(tagName) {
return splitNsName(tagName)[1] === 'ng-template';
}
function getNsPrefix(fullName) {
return fullName === null ? null : splitNsName(fullName)[0];
}
function mergeNsAndName(prefix, localName) {
return prefix ? `:${prefix}:${localName}` : localName;
}
let Comment$1 = class Comment {
value;
sourceSpan;
constructor(value, sourceSpan) {
this.value = value;
this.sourceSpan = sourceSpan;
}
visit(_visitor) {
throw new Error('visit() not implemented for Comment');
}
};
let Text$3 = class Text {
value;
sourceSpan;
constructor(value, sourceSpan) {
this.value = value;
this.sourceSpan = sourceSpan;
}
visit(visitor) {
return visitor.visitText(this);
}
};
class BoundText {
value;
sourceSpan;
i18n;
constructor(value, sourceSpan, i18n) {
this.value = value;
this.sourceSpan = sourceSpan;
this.i18n = i18n;
}
visit(visitor) {
return visitor.visitBoundText(this);
}
}
class TextAttribute {
name;
value;
sourceSpan;
keySpan;
valueSpan;
i18n;
constructor(name, value, sourceSpan, keySpan, valueSpan, i18n) {
this.name = name;
this.value = value;
this.sourceSpan = sourceSpan;
this.keySpan = keySpan;
this.valueSpan = valueSpan;
this.i18n = i18n;
}
visit(visitor) {
return visitor.visitTextAttribute(this);
}
}
class BoundAttribute {
name;
type;
securityContext;
value;
unit;
sourceSpan;
keySpan;
valueSpan;
i18n;
constructor(name, type, securityContext, value, unit, sourceSpan, keySpan, valueSpan, i18n) {
this.name = name;
this.type = type;
this.securityContext = securityContext;
this.value = value;
this.unit = unit;
this.sourceSpan = sourceSpan;
this.keySpan = keySpan;
this.valueSpan = valueSpan;
this.i18n = i18n;
}
static fromBoundElementProperty(prop, i18n) {
if (prop.keySpan === undefined) {
throw new Error(`Unexpected state: keySpan must be defined for bound attributes but was not for ${prop.name}: ${prop.sourceSpan}`);
}
return new BoundAttribute(prop.name, prop.type, prop.securityContext, prop.value, prop.unit, prop.sourceSpan, prop.keySpan, prop.valueSpan, i18n);
}
visit(visitor) {
return visitor.visitBoundAttribute(this);
}
}
class BoundEvent {
name;
type;
handler;
target;
phase;
sourceSpan;
handlerSpan;
keySpan;
constructor(name, type, handler, target, phase, sourceSpan, handlerSpan, keySpan) {
this.name = name;
this.type = type;
this.handler = handler;
this.target = target;
this.phase = phase;
this.sourceSpan = sourceSpan;
this.handlerSpan = handlerSpan;
this.keySpan = keySpan;
}
static fromParsedEvent(event) {
const target = event.type === ParsedEventType.Regular ? event.targetOrPhase : null;
const phase = event.type === ParsedEventType.LegacyAnimation ? event.targetOrPhase : null;
if (event.keySpan === undefined) {
throw new Error(`Unexpected state: keySpan must be defined for bound event but was not for ${event.name}: ${event.sourceSpan}`);
}
return new BoundEvent(event.name, event.type, event.handler, target, phase, event.sourceSpan, event.handlerSpan, event.keySpan);
}
visit(visitor) {
return visitor.visitBoundEvent(this);
}
}
let Element$1 = class Element {
name;
attributes;
inputs;
outputs;
directives;
children;
references;
isSelfClosing;
sourceSpan;
startSourceSpan;
endSourceSpan;
isVoid;
i18n;
constructor(name, attributes, inputs, outputs, directives, children, references, isSelfClosing, sourceSpan, startSourceSpan, endSourceSpan, isVoid, i18n) {
this.name = name;
this.attributes = attributes;
this.inputs = inputs;
this.outputs = outputs;
this.directives = directives;
this.children = children;
this.references = references;
this.isSelfClosing = isSelfClosing;
this.sourceSpan = sourceSpan;
this.startSourceSpan = startSourceSpan;
this.endSourceSpan = endSourceSpan;
this.isVoid = isVoid;
this.i18n = i18n;
}
visit(visitor) {
return visitor.visitElement(this);
}
};
class DeferredTrigger {
nameSpan;
sourceSpan;
prefetchSpan;
whenOrOnSourceSpan;
hydrateSpan;
constructor(nameSpan, sourceSpan, prefetchSpan, whenOrOnSourceSpan, hydrateSpan) {
this.nameSpan = nameSpan;
this.sourceSpan = sourceSpan;
this.prefetchSpan = prefetchSpan;
this.whenOrOnSourceSpan = whenOrOnSourceSpan;
this.hydrateSpan = hydrateSpan;
}
visit(visitor) {
return visitor.visitDeferredTrigger(this);
}
}
class BoundDeferredTrigger extends DeferredTrigger {
value;
constructor(value, sourceSpan, prefetchSpan, whenSourceSpan, hydrateSpan) {
super(null, sourceSpan, prefetchSpan, whenSourceSpan, hydrateSpan);
this.value = value;
}
}
class NeverDeferredTrigger extends DeferredTrigger {}
class IdleDeferredTrigger extends DeferredTrigger {}
class ImmediateDeferredTrigger extends DeferredTrigger {}
class HoverDeferredTrigger extends DeferredTrigger {
reference;
constructor(reference, nameSpan, sourceSpan, prefetchSpan, onSourceSpan, hydrateSpan) {
super(nameSpan, sourceSpan, prefetchSpan, onSourceSpan, hydrateSpan);
this.reference = reference;
}
}
class TimerDeferredTrigger extends DeferredTrigger {
delay;
constructor(delay, nameSpan, sourceSpan, prefetchSpan, onSourceSpan, hydrateSpan) {
super(nameSpan, sourceSpan, prefetchSpan, onSourceSpan, hydrateSpan);
this.delay = delay;
}
}
class InteractionDeferredTrigger extends DeferredTrigger {
reference;
constructor(reference, nameSpan, sourceSpan, prefetchSpan, onSourceSpan, hydrateSpan) {
super(nameSpan, sourceSpan, prefetchSpan, onSourceSpan, hydrateSpan);
this.reference = reference;
}
}
class ViewportDeferredTrigger extends DeferredTrigger {
reference;
options;
constructor(reference, options, nameSpan, sourceSpan, prefetchSpan, onSourceSpan, hydrateSpan) {
super(nameSpan, sourceSpan, prefetchSpan, onSourceSpan, hydrateSpan);
this.reference = reference;
this.options = options;
}
}
class BlockNode {
nameSpan;
sourceSpan;
startSourceSpan;
endSourceSpan;
constructor(nameSpan, sourceSpan, startSourceSpan, endSourceSpan) {
this.nameSpan = nameSpan;
this.sourceSpan = sourceSpan;
this.startSourceSpan = startSourceSpan;
this.endSourceSpan = endSourceSpan;
}
}
class DeferredBlockPlaceholder extends BlockNode {
children;
minimumTime;
i18n;
constructor(children, minimumTime, nameSpan, sourceSpan, startSourceSpan, endSourceSpan, i18n) {
super(nameSpan, sourceSpan, startSourceSpan, endSourceSpan);
this.children = children;
this.minimumTime = minimumTime;
this.i18n = i18n;
}
visit(visitor) {
return visitor.visitDeferredBlockPlaceholder(this);
}
}
class DeferredBlockLoading extends BlockNode {
children;
afterTime;
minimumTime;
i18n;
constructor(children, afterTime, minimumTime, nameSpan, sourceSpan, startSourceSpan, endSourceSpan, i18n) {
super(nameSpan, sourceSpan, startSourceSpan, endSourceSpan);
this.children = children;
this.afterTime = afterTime;
this.minimumTime = minimumTime;
this.i18n = i18n;
}
visit(visitor) {
return visitor.visitDeferredBlockLoading(this);
}
}
class DeferredBlockError extends BlockNode {
children;
i18n;
constructor(children, nameSpan, sourceSpan, startSourceSpan, endSourceSpan, i18n) {
super(nameSpan, sourceSpan, startSourceSpan, endSourceSpan);
this.children = children;
this.i18n = i18n;
}
visit(visitor) {
return visitor.visitDeferredBlockError(this);
}
}
class DeferredBlock extends BlockNode {
children;
placeholder;
loading;
error;
mainBlockSpan;
i18n;
triggers;
prefetchTriggers;
hydrateTriggers;
definedTriggers;
definedPrefetchTriggers;
definedHydrateTriggers;
constructor(children, triggers, prefetchTriggers, hydrateTriggers, placeholder, loading, error, nameSpan, sourceSpan, mainBlockSpan, startSourceSpan, endSourceSpan, i18n) {
super(nameSpan, sourceSpan, startSourceSpan, endSourceSpan);
this.children = children;
this.placeholder = placeholder;
this.loading = loading;
this.error = error;
this.mainBlockSpan = mainBlockSpan;
this.i18n = i18n;
this.triggers = triggers;
this.prefetchTriggers = prefetchTriggers;
this.hydrateTriggers = hydrateTriggers;
this.definedTriggers = Object.keys(triggers);
this.definedPrefetchTriggers = Object.keys(prefetchTriggers);
this.definedHydrateTriggers = Object.keys(hydrateTriggers);
}
visit(visitor) {
return visitor.visitDeferredBlock(this);
}
visitAll(visitor) {
this.visitTriggers(this.definedHydrateTriggers, this.hydrateTriggers, visitor);
this.visitTriggers(this.definedTriggers, this.triggers, visitor);
this.visitTriggers(this.definedPrefetchTriggers, this.prefetchTriggers, visitor);
visitAll$1(visitor, this.children);
const remainingBlocks = [this.placeholder, this.loading, this.error].filter(x => x !== null);
visitAll$1(visitor, remainingBlocks);
}
visitTriggers(keys, triggers, visitor) {
visitAll$1(visitor, keys.map(k => triggers[k]));
}
}
class SwitchBlock extends BlockNode {
expression;
groups;
unknownBlocks;
constructor(expression, groups, unknownBlocks, sourceSpan, startSourceSpan, endSourceSpan, nameSpan) {
super(nameSpan, sourceSpan, startSourceSpan, endSourceSpan);
this.expression = expression;
this.groups = groups;
this.unknownBlocks = unknownBlocks;
}
visit(visitor) {
return visitor.visitSwitchBlock(this);
}
}
class SwitchBlockCase extends BlockNode {
expression;
constructor(expression, sourceSpan, startSourceSpan, endSourceSpan, nameSpan) {
super(nameSpan, sourceSpan, startSourceSpan, endSourceSpan);
this.expression = expression;
}
visit(visitor) {
return visitor.visitSwitchBlockCase(this);
}
}
class SwitchBlockCaseGroup extends BlockNode {
cases;
children;
i18n;
constructor(cases, children, sourceSpan, startSourceSpan, endSourceSpan, nameSpan, i18n) {
super(nameSpan, sourceSpan, startSourceSpan, endSourceSpan);
this.cases = cases;
this.children = children;
this.i18n = i18n;
}
visit(visitor) {
return visitor.visitSwitchBlockCaseGroup(this);
}
}
class ForLoopBlock extends BlockNode {
item;
expression;
trackBy;
trackKeywordSpan;
contextVariables;
children;
empty;
mainBlockSpan;
i18n;
constructor(item, expression, trackBy, trackKeywordSpan, contextVariables, children, empty, sourceSpan, mainBlockSpan, startSourceSpan, endSourceSpan, nameSpan, i18n) {
super(nameSpan, sourceSpan, startSourceSpan, endSourceSpan);
this.item = item;
this.expression = expression;
this.trackBy = trackBy;
this.trackKeywordSpan = trackKeywordSpan;
this.contextVariables = contextVariables;
this.children = children;
this.empty = empty;
this.mainBlockSpan = mainBlockSpan;
this.i18n = i18n;
}
visit(visitor) {
return visitor.visitForLoopBlock(this);
}
}
class ForLoopBlockEmpty extends BlockNode {
children;
i18n;
constructor(children, sourceSpan, startSourceSpan, endSourceSpan, nameSpan, i18n) {
super(nameSpan, sourceSpan, startSourceSpan, endSourceSpan);
this.children = children;
this.i18n = i18n;
}
visit(visitor) {
return visitor.visitForLoopBlockEmpty(this);
}
}
class IfBlock extends BlockNode {
branches;
constructor(branches, sourceSpan, startSourceSpan, endSourceSpan, nameSpan) {
super(nameSpan, sourceSpan, startSourceSpan, endSourceSpan);
this.branches = branches;
}
visit(visitor) {
return visitor.visitIfBlock(this);
}
}
class IfBlockBranch extends BlockNode {
expression;
children;
expressionAlias;
i18n;
constructor(expression, children, expressionAlias, sourceSpan, startSourceSpan, endSourceSpan, nameSpan, i18n) {
super(nameSpan, sourceSpan, startSourceSpan, endSourceSpan);
this.expression = expression;
this.children = children;
this.expressionAlias = expressionAlias;
this.i18n = i18n;
}
visit(visitor) {
return visitor.visitIfBlockBranch(this);
}
}
class UnknownBlock {
name;
sourceSpan;
nameSpan;
constructor(name, sourceSpan, nameSpan) {
this.name = name;
this.sourceSpan = sourceSpan;
this.nameSpan = nameSpan;
}
visit(visitor) {
return visitor.visitUnknownBlock(this);
}
}
let LetDeclaration$1 = class LetDeclaration {
name;
value;
sourceSpan;
nameSpan;
valueSpan;
constructor(name, value, sourceSpan, nameSpan, valueSpan) {
this.name = name;
this.value = value;
this.sourceSpan = sourceSpan;
this.nameSpan = nameSpan;
this.valueSpan = valueSpan;
}
visit(visitor) {
return visitor.visitLetDeclaration(this);
}
};
let Component$1 = class Component {
componentName;
tagName;
fullName;
attributes;
inputs;
outputs;
directives;
children;
references;
isSelfClosing;
sourceSpan;
startSourceSpan;
endSourceSpan;
i18n;
constructor(componentName, tagName, fullName, attributes, inputs, outputs, directives, children, references, isSelfClosing, sourceSpan, startSourceSpan, endSourceSpan, i18n) {
this.componentName = componentName;
this.tagName = tagName;
this.fullName = fullName;
this.attributes = attributes;
this.inputs = inputs;
this.outputs = outputs;
this.directives = directives;
this.children = children;
this.references = references;
this.isSelfClosing = isSelfClosing;
this.sourceSpan = sourceSpan;
this.startSourceSpan = startSourceSpan;
this.endSourceSpan = endSourceSpan;
this.i18n = i18n;
}
visit(visitor) {
return visitor.visitComponent(this);
}
};
let Directive$1 = class Directive {
name;
attributes;
inputs;
outputs;
references;
sourceSpan;
startSourceSpan;
endSourceSpan;
i18n;
constructor(name, attributes, inputs, outputs, references, sourceSpan, startSourceSpan, endSourceSpan, i18n) {
this.name = name;
this.attributes = attributes;
this.inputs = inputs;
this.outputs = outputs;
this.references = references;
this.sourceSpan = sourceSpan;
this.startSourceSpan = startSourceSpan;
this.endSourceSpan = endSourceSpan;
this.i18n = i18n;
}
visit(visitor) {
return visitor.visitDirective(this);
}
};
class Template {
tagName;
attributes;
inputs;
outputs;
directives;
templateAttrs;
children;
references;
variables;
isSelfClosing;
sourceSpan;
startSourceSpan;
endSourceSpan;
i18n;
constructor(tagName, attributes, inputs, outputs, directives, templateAttrs, children, references, variables, isSelfClosing, sourceSpan, startSourceSpan, endSourceSpan, i18n) {
this.tagName = tagName;
this.attributes = attributes;
this.inputs = inputs;
this.outputs = outputs;
this.directives = directives;
this.templateAttrs = templateAttrs;
this.children = children;
this.references = references;
this.variables = variables;
this.isSelfClosing = isSelfClosing;
this.sourceSpan = sourceSpan;
this.startSourceSpan = startSourceSpan;
this.endSourceSpan = endSourceSpan;
this.i18n = i18n;
}
visit(visitor) {
return visitor.visitTemplate(this);
}
}
class Content {
selector;
attributes;
children;
isSelfClosing;
sourceSpan;
startSourceSpan;
endSourceSpan;
i18n;
name = 'ng-content';
constructor(selector, attributes, children, isSelfClosing, sourceSpan, startSourceSpan, endSourceSpan, i18n) {
this.selector = selector;
this.attributes = attributes;
this.children = children;
this.isSelfClosing = isSelfClosing;
this.sourceSpan = sourceSpan;
this.startSourceSpan = startSourceSpan;
this.endSourceSpan = endSourceSpan;
this.i18n = i18n;
}
visit(visitor) {
return visitor.visitContent(this);
}
}
class Variable {
name;
value;
sourceSpan;
keySpan;
valueSpan;
constructor(name, value, sourceSpan, keySpan, valueSpan) {
this.name = name;
this.value = value;
this.sourceSpan = sourceSpan;
this.keySpan = keySpan;
this.valueSpan = valueSpan;
}
visit(visitor) {
return visitor.visitVariable(this);
}
}
class Reference {
name;
value;
sourceSpan;
keySpan;
valueSpan;
constructor(name, value, sourceSpan, keySpan, valueSpan) {
this.name = name;
this.value = value;
this.sourceSpan = sourceSpan;
this.keySpan = keySpan;
this.valueSpan = valueSpan;
}
visit(visitor) {
return visitor.visitReference(this);
}
}
let Icu$1 = class Icu {
vars;
placeholders;
sourceSpan;
i18n;
constructor(vars, placeholders, sourceSpan, i18n) {
this.vars = vars;
this.placeholders = placeholders;
this.sourceSpan = sourceSpan;
this.i18n = i18n;
}
visit(visitor) {
return visitor.visitIcu(this);
}
};
class HostElement {
tagNames;
bindings;
listeners;
sourceSpan;
constructor(tagNames, bindings, listeners, sourceSpan) {
this.tagNames = tagNames;
this.bindings = bindings;
this.listeners = listeners;
this.sourceSpan = sourceSpan;
if (tagNames.length === 0) {
throw new Error('HostElement must have at least one tag name.');
}
}
visit() {
throw new Error(`HostElement cannot be visited`);
}
}
let RecursiveVisitor$1 = class RecursiveVisitor {
visitElement(element) {
visitAll$1(this, element.attributes);
visitAll$1(this, element.inputs);
visitAll$1(this, element.outputs);
visitAll$1(this, element.directives);
visitAll$1(this, element.children);
visitAll$1(this, element.references);
}
visitTemplate(template) {
visitAll$1(this, template.attributes);
visitAll$1(this, template.inputs);
visitAll$1(this, template.outputs);
visitAll$1(this, template.directives);
visitAll$1(this, template.children);
visitAll$1(this, template.references);
visitAll$1(this, template.variables);
}
visitDeferredBlock(deferred) {
deferred.visitAll(this);
}
visitDeferredBlockPlaceholder(block) {
visitAll$1(this, block.children);
}
visitDeferredBlockError(block) {
visitAll$1(this, block.children);
}
visitDeferredBlockLoading(block) {
visitAll$1(this, block.children);
}
visitSwitchBlock(block) {
visitAll$1(this, block.groups);
}
visitSwitchBlockCase(block) {}
visitSwitchBlockCaseGroup(block) {
visitAll$1(this, block.cases);
visitAll$1(this, block.children);
}
visitForLoopBlock(block) {
const blockItems = [block.item, ...block.contextVariables, ...block.children];
block.empty && blockItems.push(block.empty);
visitAll$1(this, blockItems);
}
visitForLoopBlockEmpty(block) {
visitAll$1(this, block.children);
}
visitIfBlock(block) {
visitAll$1(this, block.branches);
}
visitIfBlockBranch(block) {
const blockItems = block.children;
block.expressionAlias && blockItems.push(block.expressionAlias);
visitAll$1(this, blockItems);
}
visitContent(content) {
visitAll$1(this, content.children);
}
visitComponent(component) {
visitAll$1(this, component.attributes);
visitAll$1(this, component.inputs);
visitAll$1(this, component.outputs);
visitAll$1(this, component.directives);
visitAll$1(this, component.children);
visitAll$1(this, component.references);
}
visitDirective(directive) {
visitAll$1(this, directive.attributes);
visitAll$1(this, directive.inputs);
visitAll$1(this, directive.outputs);
visitAll$1(this, directive.references);
}
visitVariable(variable) {}
visitReference(reference) {}
visitTextAttribute(attribute) {}
visitBoundAttribute(attribute) {}
visitBoundEvent(attribute) {}
visitText(text) {}
visitBoundText(text) {}
visitIcu(icu) {}
visitDeferredTrigger(trigger) {}
visitUnknownBlock(block) {}
visitLetDeclaration(decl) {}
};
function visitAll$1(visitor, nodes) {
const result = [];
if (visitor.visit) {
for (const node of nodes) {
visitor.visit(node);
}
} else {
for (const node of nodes) {
const newNode = node.visit(visitor);
if (newNode) {
result.push(newNode);
}
}
}
return result;
}
class Message {
nodes;
placeholders;
placeholderToMessage;
meaning;
description;
customId;
sources;
id;
legacyIds = [];
messageString;
constructor(nodes, placeholders, placeholderToMessage, meaning, description, customId) {
this.nodes = nodes;
this.placeholders = placeholders;
this.placeholderToMessage = placeholderToMessage;
this.meaning = meaning;
this.description = description;
this.customId = customId;
this.id = this.customId;
this.messageString = serializeMessage(this.nodes);
if (nodes.length) {
this.sources = [{
filePath: nodes[0].sourceSpan.start.file.url,
startLine: nodes[0].sourceSpan.start.line + 1,
startCol: nodes[0].sourceSpan.start.col + 1,
endLine: nodes[nodes.length - 1].sourceSpan.end.line + 1,
endCol: nodes[0].sourceSpan.start.col + 1
}];
} else {
this.sources = [];
}
}
}
let Text$2 = class Text {
value;
sourceSpan;
constructor(value, sourceSpan) {
this.value = value;
this.sourceSpan = sourceSpan;
}
visit(visitor, context) {
return visitor.visitText(this, context);
}
};
class Container {
children;
sourceSpan;
constructor(children, sourceSpan) {
this.children = children;
this.sourceSpan = sourceSpan;
}
visit(visitor, context) {
return visitor.visitContainer(this, context);
}
}
class Icu {
expression;
type;
cases;
sourceSpan;
expressionPlaceholder;
constructor(expression, type, cases, sourceSpan, expressionPlaceholder) {
this.expression = expression;
this.type = type;
this.cases = cases;
this.sourceSpan = sourceSpan;
this.expressionPlaceholder = expressionPlaceholder;
}
visit(visitor, context) {
return visitor.visitIcu(this, context);
}
}
class TagPlaceholder {
tag;
attrs;
startName;
closeName;
children;
isVoid;
sourceSpan;
startSourceSpan;
endSourceSpan;
constructor(tag, attrs, startName, closeName, children, isVoid, sourceSpan, startSourceSpan, endSourceSpan) {
this.tag = tag;
this.attrs = attrs;
this.startName = startName;
this.closeName = closeName;
this.children = children;
this.isVoid = isVoid;
this.sourceSpan = sourceSpan;
this.startSourceSpan = startSourceSpan;
this.endSourceSpan = endSourceSpan;
}
visit(visitor, context) {
return visitor.visitTagPlaceholder(this, context);
}
}
class Placeholder {
value;
name;
sourceSpan;
constructor(value, name, sourceSpan) {
this.value = value;
this.name = name;
this.sourceSpan = sourceSpan;
}
visit(visitor, context) {
return visitor.visitPlaceholder(this, context);
}
}
class IcuPlaceholder {
value;
name;
sourceSpan;
previousMessage;
constructor(value, name, sourceSpan) {
this.value = value;
this.name = name;
this.sourceSpan = sourceSpan;
}
visit(visitor, context) {
return visitor.visitIcuPlaceholder(this, context);
}
}
class BlockPlaceholder {
name;
parameters;
startName;
closeName;
children;
sourceSpan;
startSourceSpan;
endSourceSpan;
constructor(name, parameters, startName, closeName, children, sourceSpan, startSourceSpan, endSourceSpan) {
this.name = name;
this.parameters = parameters;
this.startName = startName;
this.closeName = closeName;
this.children = children;
this.sourceSpan = sourceSpan;
this.startSourceSpan = startSourceSpan;
this.endSourceSpan = endSourceSpan;
}
visit(visitor, context) {
return visitor.visitBlockPlaceholder(this, context);
}
}
class CloneVisitor {
visitText(text, context) {
return new Text$2(text.value, text.sourceSpan);
}
visitContainer(container, context) {
const children = container.children.map(n => n.visit(this, context));
return new Container(children, container.sourceSpan);
}
visitIcu(icu, context) {
const cases = {};
Object.keys(icu.cases).forEach(key => cases[key] = icu.cases[key].visit(this, context));
const msg = new Icu(icu.expression, icu.type, cases, icu.sourceSpan, icu.expressionPlaceholder);
return msg;
}
visitTagPlaceholder(ph, context) {
const children = ph.children.map(n => n.visit(this, context));
return new TagPlaceholder(ph.tag, ph.attrs, ph.startName, ph.closeName, children, ph.isVoid, ph.sourceSpan, ph.startSourceSpan, ph.endSourceSpan);
}
visitPlaceholder(ph, context) {
return new Placeholder(ph.value, ph.name, ph.sourceSpan);
}
visitIcuPlaceholder(ph, context) {
return new IcuPlaceholder(ph.value, ph.name, ph.sourceSpan);
}
visitBlockPlaceholder(ph, context) {
const children = ph.children.map(n => n.visit(this, context));
return new BlockPlaceholder(ph.name, ph.parameters, ph.startName, ph.closeName, children, ph.sourceSpan, ph.startSourceSpan, ph.endSourceSpan);
}
}
class RecurseVisitor {
visitText(text, context) {}
visitContainer(container, context) {
container.children.forEach(child => child.visit(this));
}
visitIcu(icu, context) {
Object.keys(icu.cases).forEach(k => {
icu.cases[k].visit(this);
});
}
visitTagPlaceholder(ph, context) {
ph.children.forEach(child => child.visit(this));
}
visitPlaceholder(ph, context) {}
visitIcuPlaceholder(ph, context) {}
visitBlockPlaceholder(ph, context) {
ph.children.forEach(child => child.visit(this));
}
}
function serializeMessage(messageNodes) {
const visitor = new LocalizeMessageStringVisitor();
const str = messageNodes.map(n => n.visit(visitor)).join('');
return str;
}
class LocalizeMessageStringVisitor {
visitText(text) {
return text.value;
}
visitContainer(container) {
return container.children.map(child => child.visit(this)).join('');
}
visitIcu(icu) {
const strCases = Object.keys(icu.cases).map(k => `${k} {${icu.cases[k].visit(this)}}`);
return `{${icu.expressionPlaceholder}, ${icu.type}, ${strCases.join(' ')}}`;
}
visitTagPlaceholder(ph) {
const children = ph.children.map(child => child.visit(this)).join('');
return `{$${ph.startName}}${children}{$${ph.closeName}}`;
}
visitPlaceholder(ph) {
return `{$${ph.name}}`;
}
visitIcuPlaceholder(ph) {
return `{$${ph.name}}`;
}
visitBlockPlaceholder(ph) {
const children = ph.children.map(child => child.visit(this)).join('');
return `{$${ph.startName}}${children}{$${ph.closeName}}`;
}
}
class Serializer {
createNameMapper(message) {
return null;
}
}
class SimplePlaceholderMapper extends RecurseVisitor {
mapName;
internalToPublic = {};
publicToNextId = {};
publicToInternal = {};
constructor(message, mapName) {
super();
this.mapName = mapName;
message.nodes.forEach(node => node.visit(this));
}
toPublicName(internalName) {
return this.internalToPublic.hasOwnProperty(internalName) ? this.internalToPublic[internalName] : null;
}
toInternalName(publicName) {
return this.publicToInternal.hasOwnProperty(publicName) ? this.publicToInternal[publicName] : null;
}
visitText(text, context) {
return null;
}
visitTagPlaceholder(ph, context) {
this.visitPlaceholderName(ph.startName);
super.visitTagPlaceholder(ph, context);
this.visitPlaceholderName(ph.closeName);
}
visitPlaceholder(ph, context) {
this.visitPlaceholderName(ph.name);
}
visitBlockPlaceholder(ph, context) {
this.visitPlaceholderName(ph.startName);
super.visitBlockPlaceholder(ph, context);
this.visitPlaceholderName(ph.closeName);
}
visitIcuPlaceholder(ph, context) {
this.visitPlaceholderName(ph.name);
}
visitPlaceholderName(internalName) {
if (!internalName || this.internalToPublic.hasOwnProperty(internalName)) {
return;
}
let publicName = this.mapName(internalName);
if (this.publicToInternal.hasOwnProperty(publicName)) {
const nextId = this.publicToNextId[publicName];
this.publicToNextId[publicName] = nextId + 1;
publicName = `${publicName}_${nextId}`;
} else {
this.publicToNextId[publicName] = 1;
}
this.internalToPublic[internalName] = publicName;
this.publicToInternal[publicName] = internalName;
}
}
let _Visitor$2 = class _Visitor {
visitTag(tag) {
const strAttrs = this._serializeAttributes(tag.attrs);
if (tag.children.length == 0) {
return `<${tag.name}${strAttrs}/>`;
}
const strChildren = tag.children.map(node => node.visit(this));
return `<${tag.name}${strAttrs}>${strChildren.join('')}</${tag.name}>`;
}
visitText(text) {
return text.value;
}
visitDeclaration(decl) {
return `<?xml${this._serializeAttributes(decl.attrs)} ?>`;
}
_serializeAttributes(attrs) {
const strAttrs = Object.keys(attrs).map(name => `${name}="${attrs[name]}"`).join(' ');
return strAttrs.length > 0 ? ' ' + strAttrs : '';
}
visitDoctype(doctype) {
return `<!DOCTYPE ${doctype.rootTag} [\n${doctype.dtd}\n]>`;
}
};
const _visitor = new _Visitor$2();
function serialize$1(nodes) {
return nodes.map(node => node.visit(_visitor)).join('');
}
class Declaration {
attrs = {};
constructor(unescapedAttrs) {
Object.keys(unescapedAttrs).forEach(k => {
this.attrs[k] = escapeXml(unescapedAttrs[k]);
});
}
visit(visitor) {
return visitor.visitDeclaration(this);
}
}
class Doctype {
rootTag;
dtd;
constructor(rootTag, dtd) {
this.rootTag = rootTag;
this.dtd = dtd;
}
visit(visitor) {
return visitor.visitDoctype(this);
}
}
class Tag {
name;
children;
attrs = {};
constructor(name, unescapedAttrs = {}, children = []) {
this.name = name;
this.children = children;
Object.keys(unescapedAttrs).forEach(k => {
this.attrs[k] = escapeXml(unescapedAttrs[k]);
});
}
visit(visitor) {
return visitor.visitTag(this);
}
}
let Text$1 = class Text {
value;
constructor(unescapedValue) {
this.value = escapeXml(unescapedValue);
}
visit(visitor) {
return visitor.visitText(this);
}
};
class CR extends Text$1 {
constructor(ws = 0) {
super(`\n${new Array(ws + 1).join(' ')}`);
}
}
const _ESCAPED_CHARS = [[/&/g, '&amp;'], [/"/g, '&quot;'], [/'/g, '&apos;'], [/</g, '&lt;'], [/>/g, '&gt;']];
function escapeXml(text) {
return _ESCAPED_CHARS.reduce((text, entry) => text.replace(entry[0], entry[1]), text);
}
const _XMB_HANDLER = 'angular';
const _MESSAGES_TAG = 'messagebundle';
const _MESSAGE_TAG = 'msg';
const _PLACEHOLDER_TAG$3 = 'ph';
const _EXAMPLE_TAG = 'ex';
const _SOURCE_TAG$2 = 'source';
const _DOCTYPE = `<!ELEMENT messagebundle (msg)*>
<!ATTLIST messagebundle class CDATA #IMPLIED>
<!ELEMENT msg (#PCDATA|ph|source)*>
<!ATTLIST msg id CDATA #IMPLIED>
<!ATTLIST msg seq CDATA #IMPLIED>
<!ATTLIST msg name CDATA #IMPLIED>
<!ATTLIST msg desc CDATA #IMPLIED>
<!ATTLIST msg meaning CDATA #IMPLIED>
<!ATTLIST msg obsolete (obsolete) #IMPLIED>
<!ATTLIST msg xml:space (default|preserve) "default">
<!ATTLIST msg is_hidden CDATA #IMPLIED>
<!ELEMENT source (#PCDATA)>
<!ELEMENT ph (#PCDATA|ex)*>
<!ATTLIST ph name CDATA #REQUIRED>
<!ELEMENT ex (#PCDATA)>`;
class Xmb extends Serializer {
write(messages, locale) {
const exampleVisitor = new ExampleVisitor();
const visitor = new _Visitor$1();
const rootNode = new Tag(_MESSAGES_TAG);
rootNode.attrs['handler'] = _XMB_HANDLER;
messages.forEach(message => {
const attrs = {
id: message.id
};
if (message.description) {
attrs['desc'] = message.description;
}
if (message.meaning) {
attrs['meaning'] = message.meaning;
}
let sourceTags = [];
message.sources.forEach(source => {
sourceTags.push(new Tag(_SOURCE_TAG$2, {}, [new Text$1(`${source.filePath}:${source.startLine}${source.endLine !== source.startLine ? ',' + source.endLine : ''}`)]));
});
rootNode.children.push(new CR(2), new Tag(_MESSAGE_TAG, attrs, [...sourceTags, ...visitor.serialize(message.nodes)]));
});
rootNode.children.push(new CR());
return serialize$1([new Declaration({
version: '1.0',
encoding: 'UTF-8'
}), new CR(), new Doctype(_MESSAGES_TAG, _DOCTYPE), new CR(), exampleVisitor.addDefaultExamples(rootNode), new CR()]);
}
load(content, url) {
throw new Error('Unsupported');
}
digest(message) {
return digest(message);
}
createNameMapper(message) {
return new SimplePlaceholderMapper(message, toPublicName);
}
}
let _Visitor$1 = class _Visitor {
visitText(text, context) {
return [new Text$1(text.value)];
}
visitContainer(container, context) {
const nodes = [];
container.children.forEach(node => nodes.push(...node.visit(this)));
return nodes;
}
visitIcu(icu, context) {
const nodes = [new Text$1(`{${icu.expressionPlaceholder}, ${icu.type}, `)];
Object.keys(icu.cases).forEach(c => {
nodes.push(new Text$1(`${c} {`), ...icu.cases[c].visit(this), new Text$1(`} `));
});
nodes.push(new Text$1(`}`));
return nodes;
}
visitTagPlaceholder(ph, context) {
const startTagAsText = new Text$1(`<${ph.tag}>`);
const startEx = new Tag(_EXAMPLE_TAG, {}, [startTagAsText]);
const startTagPh = new Tag(_PLACEHOLDER_TAG$3, {
name: ph.startName
}, [startEx, startTagAsText]);
if (ph.isVoid) {
return [startTagPh];
}
const closeTagAsText = new Text$1(`</${ph.tag}>`);
const closeEx = new Tag(_EXAMPLE_TAG, {}, [closeTagAsText]);
const closeTagPh = new Tag(_PLACEHOLDER_TAG$3, {
name: ph.closeName
}, [closeEx, closeTagAsText]);
return [startTagPh, ...this.serialize(ph.children), closeTagPh];
}
visitPlaceholder(ph, context) {
const interpolationAsText = new Text$1(`{{${ph.value}}}`);
const exTag = new Tag(_EXAMPLE_TAG, {}, [interpolationAsText]);
return [new Tag(_PLACEHOLDER_TAG$3, {
name: ph.name
}, [exTag, interpolationAsText])];
}
visitBlockPlaceholder(ph, context) {
const startAsText = new Text$1(`@${ph.name}`);
const startEx = new Tag(_EXAMPLE_TAG, {}, [startAsText]);
const startTagPh = new Tag(_PLACEHOLDER_TAG$3, {
name: ph.startName
}, [startEx, startAsText]);
const closeAsText = new Text$1(`}`);
const closeEx = new Tag(_EXAMPLE_TAG, {}, [closeAsText]);
const closeTagPh = new Tag(_PLACEHOLDER_TAG$3, {
name: ph.closeName
}, [closeEx, closeAsText]);
return [startTagPh, ...this.serialize(ph.children), closeTagPh];
}
visitIcuPlaceholder(ph, context) {
const icuExpression = ph.value.expression;
const icuType = ph.value.type;
const icuCases = Object.keys(ph.value.cases).map(value => value + ' {...}').join(' ');
const icuAsText = new Text$1(`{${icuExpression}, ${icuType}, ${icuCases}}`);
const exTag = new Tag(_EXAMPLE_TAG, {}, [icuAsText]);
return [new Tag(_PLACEHOLDER_TAG$3, {
name: ph.name
}, [exTag, icuAsText])];
}
serialize(nodes) {
return [].concat(...nodes.map(node => node.visit(this)));
}
};
function digest(message) {
return decimalDigest(message);
}
class ExampleVisitor {
addDefaultExamples(node) {
node.visit(this);
return node;
}
visitTag(tag) {
if (tag.name === _PLACEHOLDER_TAG$3) {
if (!tag.children || tag.children.length == 0) {
const exText = new Text$1(tag.attrs['name'] || '...');
tag.children = [new Tag(_EXAMPLE_TAG, {}, [exText])];
}
} else if (tag.children) {
tag.children.forEach(node => node.visit(this));
}
}
visitText(text) {}
visitDeclaration(decl) {}
visitDoctype(doctype) {}
}
function toPublicName(internalName) {
return internalName.toUpperCase().replace(/[^A-Z0-9_]/g, '_');
}
const I18N_ATTR = 'i18n';
const I18N_ATTR_PREFIX = 'i18n-';
const I18N_ICU_VAR_PREFIX = 'VAR_';
function isI18nAttribute(name) {
return name === I18N_ATTR || name.startsWith(I18N_ATTR_PREFIX);
}
function hasI18nAttrs(node) {
return node.attrs.some(attr => isI18nAttribute(attr.name));
}
function icuFromI18nMessage(message) {
return message.nodes[0];
}
function formatI18nPlaceholderNamesInMap(params = {}, useCamelCase) {
const _params = {};
if (params && Object.keys(params).length) {
Object.keys(params).forEach(key => _params[formatI18nPlaceholderName(key, useCamelCase)] = params[key]);
}
return _params;
}
function formatI18nPlaceholderName(name, useCamelCase = true) {
const publicName = toPublicName(name);
if (!useCamelCase) {
return publicName;
}
const chunks = publicName.split('_');
if (chunks.length === 1) {
return name.toLowerCase();
}
let postfix;
if (/^\d+$/.test(chunks[chunks.length - 1])) {
postfix = chunks.pop();
}
let raw = chunks.shift().toLowerCase();
if (chunks.length) {
raw += chunks.map(c => c.charAt(0).toUpperCase() + c.slice(1).toLowerCase()).join('');
}
return postfix ? `${raw}_${postfix}` : raw;
}
const UNSAFE_OBJECT_KEY_NAME_REGEXP = /[-.]/;
const TEMPORARY_NAME = '_t';
const CONTEXT_NAME = 'ctx';
const RENDER_FLAGS = 'rf';
function temporaryAllocator(pushStatement, name) {
let temp = null;
return () => {
if (!temp) {
pushStatement(new DeclareVarStmt(TEMPORARY_NAME, undefined, DYNAMIC_TYPE));
temp = variable(name);
}
return temp;
};
}
function asLiteral(value) {
if (Array.isArray(value)) {
return literalArr(value.map(asLiteral));
}
return literal(value, INFERRED_TYPE);
}
function conditionallyCreateDirectiveBindingLiteral(map, forInputs) {
const keys = Object.getOwnPropertyNames(map);
if (keys.length === 0) {
return null;
}
return literalMap(keys.map(key => {
const value = map[key];
let declaredName;
let publicName;
let minifiedName;
let expressionValue;
if (typeof value === 'string') {
declaredName = key;
minifiedName = key;
publicName = value;
expressionValue = asLiteral(publicName);
} else {
minifiedName = key;
declaredName = value.classPropertyName;
publicName = value.bindingPropertyName;
const differentDeclaringName = publicName !== declaredName;
const hasDecoratorInputTransform = value.transformFunction !== null;
let flags = InputFlags.None;
if (value.isSignal) {
flags |= InputFlags.SignalBased;
}
if (hasDecoratorInputTransform) {
flags |= InputFlags.HasDecoratorInputTransform;
}
if (forInputs && (differentDeclaringName || hasDecoratorInputTransform || flags !== InputFlags.None)) {
const result = [literal(flags), asLiteral(publicName)];
if (differentDeclaringName || hasDecoratorInputTransform) {
result.push(asLiteral(declaredName));
if (hasDecoratorInputTransform) {
result.push(value.transformFunction);
}
}
expressionValue = literalArr(result);
} else {
expressionValue = asLiteral(publicName);
}
}
return {
key: minifiedName,
quoted: UNSAFE_OBJECT_KEY_NAME_REGEXP.test(minifiedName),
value: expressionValue
};
}));
}
class DefinitionMap {
values = [];
set(key, value) {
if (value) {
const existing = this.values.find(value => value.key === key);
if (existing) {
existing.value = value;
} else {
this.values.push({
key: key,
value,
quoted: false
});
}
}
}
toLiteralMap() {
return literalMap(this.values);
}
}
function createCssSelectorFromNode(node) {
const elementName = node instanceof Element$1 ? node.name : 'ng-template';
const attributes = getAttrsForDirectiveMatching(node);
const cssSelector = new CssSelector();
const elementNameNoNs = splitNsName(elementName)[1];
cssSelector.setElement(elementNameNoNs);
Object.getOwnPropertyNames(attributes).forEach(name => {
const nameNoNs = splitNsName(name)[1];
const value = attributes[name];
cssSelector.addAttribute(nameNoNs, value);
if (name.toLowerCase() === 'class') {
const classes = value.trim().split(/\s+/);
classes.forEach(className => cssSelector.addClassName(className));
}
});
return cssSelector;
}
function getAttrsForDirectiveMatching(elOrTpl) {
const attributesMap = {};
if (elOrTpl instanceof Template && elOrTpl.tagName !== 'ng-template') {
elOrTpl.templateAttrs.forEach(a => attributesMap[a.name] = '');
} else {
elOrTpl.attributes.forEach(a => {
if (!isI18nAttribute(a.name)) {
attributesMap[a.name] = a.value;
}
});
elOrTpl.inputs.forEach(i => {
if (i.type === BindingType.Property || i.type === BindingType.TwoWay) {
attributesMap[i.name] = '';
}
});
elOrTpl.outputs.forEach(o => {
attributesMap[o.name] = '';
});
}
return attributesMap;
}
function compileInjectable(meta, resolveForwardRefs) {
let result = null;
const factoryMeta = {
name: meta.name,
type: meta.type,
typeArgumentCount: meta.typeArgumentCount,
deps: [],
target: FactoryTarget.Injectable
};
if (meta.useClass !== undefined) {
const useClassOnSelf = meta.useClass.expression.isEquivalent(meta.type.value);
let deps = undefined;
if (meta.deps !== undefined) {
deps = meta.deps;
}
if (deps !== undefined) {
result = compileFactoryFunction({
...factoryMeta,
delegate: meta.useClass.expression,
delegateDeps: deps,
delegateType: R3FactoryDelegateType.Class
});
} else if (useClassOnSelf) {
result = compileFactoryFunction(factoryMeta);
} else {
result = {
statements: [],
expression: delegateToFactory(meta.type.value, meta.useClass.expression, resolveForwardRefs)
};
}
} else if (meta.useFactory !== undefined) {
if (meta.deps !== undefined) {
result = compileFactoryFunction({
...factoryMeta,
delegate: meta.useFactory,
delegateDeps: meta.deps || [],
delegateType: R3FactoryDelegateType.Function
});
} else {
result = {
statements: [],
expression: arrowFn([], meta.useFactory.callFn([]))
};
}
} else if (meta.useValue !== undefined) {
result = compileFactoryFunction({
...factoryMeta,
expression: meta.useValue.expression
});
} else if (meta.useExisting !== undefined) {
result = compileFactoryFunction({
...factoryMeta,
expression: importExpr(Identifiers.inject).callFn([meta.useExisting.expression])
});
} else {
result = {
statements: [],
expression: delegateToFactory(meta.type.value, meta.type.value, resolveForwardRefs)
};
}
const token = meta.type.value;
const injectableProps = new DefinitionMap();
injectableProps.set('token', token);
injectableProps.set('factory', result.expression);
if (meta.providedIn.expression.value !== null) {
injectableProps.set('providedIn', convertFromMaybeForwardRefExpression(meta.providedIn));
}
const expression = importExpr(Identifiers.ɵɵdefineInjectable).callFn([injectableProps.toLiteralMap()], undefined, true);
return {
expression,
type: createInjectableType(meta),
statements: result.statements
};
}
function createInjectableType(meta) {
return new ExpressionType(importExpr(Identifiers.InjectableDeclaration, [typeWithParameters(meta.type.type, meta.typeArgumentCount)]));
}
function delegateToFactory(type, useType, unwrapForwardRefs) {
if (type.node === useType.node) {
return useType.prop('ɵfac');
}
if (!unwrapForwardRefs) {
return createFactoryFunction(useType);
}
const unwrappedType = importExpr(Identifiers.resolveForwardRef).callFn([useType]);
return createFactoryFunction(unwrappedType);
}
function createFactoryFunction(type) {
const t = new FnParam('__ngFactoryType__', DYNAMIC_TYPE);
return arrowFn([t], type.prop('ɵfac').callFn([variable(t.name)]));
}
const $EOF = 0;
const $BSPACE = 8;
const $TAB = 9;
const $LF = 10;
const $VTAB = 11;
const $FF = 12;
const $CR = 13;
const $SPACE = 32;
const $BANG = 33;
const $DQ = 34;
const $HASH = 35;
const $$ = 36;
const $PERCENT = 37;
const $AMPERSAND = 38;
const $SQ = 39;
const $LPAREN = 40;
const $RPAREN = 41;
const $STAR = 42;
const $PLUS = 43;
const $COMMA = 44;
const $MINUS = 45;
const $PERIOD = 46;
const $SLASH = 47;
const $COLON = 58;
const $SEMICOLON = 59;
const $LT = 60;
const $EQ = 61;
const $GT = 62;
const $QUESTION = 63;
const $0 = 48;
const $7 = 55;
const $9 = 57;
const $A = 65;
const $E = 69;
const $F = 70;
const $X = 88;
const $Z = 90;
const $LBRACKET = 91;
const $BACKSLASH = 92;
const $RBRACKET = 93;
const $CARET = 94;
const $_ = 95;
const $a = 97;
const $b = 98;
const $e = 101;
const $f = 102;
const $n = 110;
const $r = 114;
const $t = 116;
const $u = 117;
const $v = 118;
const $x = 120;
const $z = 122;
const $LBRACE = 123;
const $BAR = 124;
const $RBRACE = 125;
const $NBSP = 160;
const $AT = 64;
const $BT = 96;
function isWhitespace(code) {
return code >= $TAB && code <= $SPACE || code == $NBSP;
}
function isDigit(code) {
return $0 <= code && code <= $9;
}
function isAsciiLetter(code) {
return code >= $a && code <= $z || code >= $A && code <= $Z;
}
function isAsciiHexDigit(code) {
return code >= $a && code <= $f || code >= $A && code <= $F || isDigit(code);
}
function isNewLine(code) {
return code === $LF || code === $CR;
}
function isOctalDigit(code) {
return $0 <= code && code <= $7;
}
function isQuote(code) {
return code === $SQ || code === $DQ || code === $BT;
}
class ParseLocation {
file;
offset;
line;
col;
constructor(file, offset, line, col) {
this.file = file;
this.offset = offset;
this.line = line;
this.col = col;
}
toString() {
return this.offset != null ? `${this.file.url}@${this.line}:${this.col}` : this.file.url;
}
moveBy(delta) {
const source = this.file.content;
const len = source.length;
let offset = this.offset;
let line = this.line;
let col = this.col;
while (offset > 0 && delta < 0) {
offset--;
delta++;
const ch = source.charCodeAt(offset);
if (ch == $LF) {
line--;
const priorLine = source.substring(0, offset - 1).lastIndexOf(String.fromCharCode($LF));
col = priorLine > 0 ? offset - priorLine : offset;
} else {
col--;
}
}
while (offset < len && delta > 0) {
const ch = source.charCodeAt(offset);
offset++;
delta--;
if (ch == $LF) {
line++;
col = 0;
} else {
col++;
}
}
return new ParseLocation(this.file, offset, line, col);
}
getContext(maxChars, maxLines) {
const content = this.file.content;
let startOffset = this.offset;
if (startOffset != null) {
if (startOffset > content.length - 1) {
startOffset = content.length - 1;
}
let endOffset = startOffset;
let ctxChars = 0;
let ctxLines = 0;
while (ctxChars < maxChars && startOffset > 0) {
startOffset--;
ctxChars++;
if (content[startOffset] == '\n') {
if (++ctxLines == maxLines) {
break;
}
}
}
ctxChars = 0;
ctxLines = 0;
while (ctxChars < maxChars && endOffset < content.length - 1) {
endOffset++;
ctxChars++;
if (content[endOffset] == '\n') {
if (++ctxLines == maxLines) {
break;
}
}
}
return {
before: content.substring(startOffset, this.offset),
after: content.substring(this.offset, endOffset + 1)
};
}
return null;
}
}
class ParseSourceFile {
content;
url;
constructor(content, url) {
this.content = content;
this.url = url;
}
}
class ParseSourceSpan {
start;
end;
fullStart;
details;
constructor(start, end, fullStart = start, details = null) {
this.start = start;
this.end = end;
this.fullStart = fullStart;
this.details = details;
}
toString() {
return this.start.file.content.substring(this.start.offset, this.end.offset);
}
}
var ParseErrorLevel;
(function (ParseErrorLevel) {
ParseErrorLevel[ParseErrorLevel["WARNING"] = 0] = "WARNING";
ParseErrorLevel[ParseErrorLevel["ERROR"] = 1] = "ERROR";
})(ParseErrorLevel || (ParseErrorLevel = {}));
class ParseError extends Error {
span;
msg;
level;
relatedError;
constructor(span, msg, level = ParseErrorLevel.ERROR, relatedError) {
super(msg);
this.span = span;
this.msg = msg;
this.level = level;
this.relatedError = relatedError;
Object.setPrototypeOf(this, new.target.prototype);
}
contextualMessage() {
const ctx = this.span.start.getContext(100, 3);
return ctx ? `${this.msg} ("${ctx.before}[${ParseErrorLevel[this.level]} ->]${ctx.after}")` : this.msg;
}
toString() {
const details = this.span.details ? `, ${this.span.details}` : '';
return `${this.contextualMessage()}: ${this.span.start}${details}`;
}
}
function r3JitTypeSourceSpan(kind, typeName, sourceUrl) {
const sourceFileName = `in ${kind} ${typeName} in ${sourceUrl}`;
const sourceFile = new ParseSourceFile('', sourceFileName);
return new ParseSourceSpan(new ParseLocation(sourceFile, -1, -1, -1), new ParseLocation(sourceFile, -1, -1, -1));
}
let _anonymousTypeIndex = 0;
function identifierName(compileIdentifier) {
if (!compileIdentifier || !compileIdentifier.reference) {
return null;
}
const ref = compileIdentifier.reference;
if (ref['__anonymousType']) {
return ref['__anonymousType'];
}
if (ref['__forward_ref__']) {
return '__forward_ref__';
}
let identifier = stringify(ref);
if (identifier.indexOf('(') >= 0) {
identifier = `anonymous_${_anonymousTypeIndex++}`;
ref['__anonymousType'] = identifier;
} else {
identifier = sanitizeIdentifier(identifier);
}
return identifier;
}
function sanitizeIdentifier(name) {
return name.replace(/\W/g, '_');
}
const makeTemplateObjectPolyfill = '(this&&this.__makeTemplateObject||function(e,t){return Object.defineProperty?Object.defineProperty(e,"raw",{value:t}):e.raw=t,e})';
class AbstractJsEmitterVisitor extends AbstractEmitterVisitor {
constructor() {
super(false);
}
visitWrappedNodeExpr(ast, ctx) {
throw new Error('Cannot emit a WrappedNodeExpr in Javascript.');
}
visitDeclareVarStmt(stmt, ctx) {
ctx.print(stmt, `var ${stmt.name}`);
if (stmt.value) {
ctx.print(stmt, ' = ');
stmt.value.visitExpression(this, ctx);
}
ctx.println(stmt, `;`);
return null;
}
visitTaggedTemplateLiteralExpr(ast, ctx) {
const elements = ast.template.elements;
ast.tag.visitExpression(this, ctx);
ctx.print(ast, `(${makeTemplateObjectPolyfill}(`);
ctx.print(ast, `[${elements.map(part => escapeIdentifier(part.text, false)).join(', ')}], `);
ctx.print(ast, `[${elements.map(part => escapeIdentifier(part.rawText, false)).join(', ')}])`);
ast.template.expressions.forEach(expression => {
ctx.print(ast, ', ');
expression.visitExpression(this, ctx);
});
ctx.print(ast, ')');
return null;
}
visitTemplateLiteralExpr(expr, ctx) {
ctx.print(expr, '`');
for (let i = 0; i < expr.elements.length; i++) {
expr.elements[i].visitExpression(this, ctx);
const expression = i < expr.expressions.length ? expr.expressions[i] : null;
if (expression !== null) {
ctx.print(expression, '${');
expression.visitExpression(this, ctx);
ctx.print(expression, '}');
}
}
ctx.print(expr, '`');
}
visitTemplateLiteralElementExpr(expr, ctx) {
ctx.print(expr, expr.rawText);
return null;
}
visitFunctionExpr(ast, ctx) {
ctx.print(ast, `function${ast.name ? ' ' + ast.name : ''}(`);
this._visitParams(ast.params, ctx);
ctx.println(ast, `) {`);
ctx.incIndent();
this.visitAllStatements(ast.statements, ctx);
ctx.decIndent();
ctx.print(ast, `}`);
return null;
}
visitArrowFunctionExpr(ast, ctx) {
ctx.print(ast, '(');
this._visitParams(ast.params, ctx);
ctx.print(ast, ') =>');
if (Array.isArray(ast.body)) {
ctx.println(ast, `{`);
ctx.incIndent();
this.visitAllStatements(ast.body, ctx);
ctx.decIndent();
ctx.print(ast, `}`);
} else {
const isObjectLiteral = ast.body instanceof LiteralMapExpr;
if (isObjectLiteral) {
ctx.print(ast, '(');
}
ast.body.visitExpression(this, ctx);
if (isObjectLiteral) {
ctx.print(ast, ')');
}
}
return null;
}
visitDeclareFunctionStmt(stmt, ctx) {
ctx.print(stmt, `function ${stmt.name}(`);
this._visitParams(stmt.params, ctx);
ctx.println(stmt, `) {`);
ctx.incIndent();
this.visitAllStatements(stmt.statements, ctx);
ctx.decIndent();
ctx.println(stmt, `}`);
return null;
}
visitLocalizedString(ast, ctx) {
ctx.print(ast, `$localize(${makeTemplateObjectPolyfill}(`);
const parts = [ast.serializeI18nHead()];
for (let i = 1; i < ast.messageParts.length; i++) {
parts.push(ast.serializeI18nTemplatePart(i));
}
ctx.print(ast, `[${parts.map(part => escapeIdentifier(part.cooked, false)).join(', ')}], `);
ctx.print(ast, `[${parts.map(part => escapeIdentifier(part.raw, false)).join(', ')}])`);
ast.expressions.forEach(expression => {
ctx.print(ast, ', ');
expression.visitExpression(this, ctx);
});
ctx.print(ast, ')');
return null;
}
_visitParams(params, ctx) {
this.visitAllObjects(param => ctx.print(null, param.name), params, ctx, ',');
}
}
let policy;
function getPolicy() {
if (policy === undefined) {
const trustedTypes = _global['trustedTypes'];
policy = null;
if (trustedTypes) {
try {
policy = trustedTypes.createPolicy('angular#unsafe-jit', {
createScript: s => s
});
} catch {}
}
}
return policy;
}
function trustedScriptFromString(script) {
return getPolicy()?.createScript(script) || script;
}
function newTrustedFunctionForJIT(...args) {
if (!_global['trustedTypes']) {
return new Function(...args);
}
const fnArgs = args.slice(0, -1).join(',');
const fnBody = args[args.length - 1];
const body = `(function anonymous(${fnArgs}
) { ${fnBody}
})`;
const fn = _global['eval'](trustedScriptFromString(body));
if (fn.bind === undefined) {
return new Function(...args);
}
fn.toString = () => body;
return fn.bind(_global);
}
class JitEvaluator {
evaluateStatements(sourceUrl, statements, refResolver, createSourceMaps) {
const converter = new JitEmitterVisitor(refResolver);
const ctx = EmitterVisitorContext.createRoot();
if (statements.length > 0 && !isUseStrictStatement(statements[0])) {
statements = [literal('use strict').toStmt(), ...statements];
}
converter.visitAllStatements(statements, ctx);
converter.createReturnStmt(ctx);
return this.evaluateCode(sourceUrl, ctx, converter.getArgs(), createSourceMaps);
}
evaluateCode(sourceUrl, ctx, vars, createSourceMap) {
let fnBody = `"use strict";${ctx.toSource()}\n//# sourceURL=${sourceUrl}`;
const fnArgNames = [];
const fnArgValues = [];
for (const argName in vars) {
fnArgValues.push(vars[argName]);
fnArgNames.push(argName);
}
if (createSourceMap) {
const emptyFn = newTrustedFunctionForJIT(...fnArgNames.concat('return null;')).toString();
const headerLines = emptyFn.slice(0, emptyFn.indexOf('return null;')).split('\n').length - 1;
fnBody += `\n${ctx.toSourceMapGenerator(sourceUrl, headerLines).toJsComment()}`;
}
const fn = newTrustedFunctionForJIT(...fnArgNames.concat(fnBody));
return this.executeFunction(fn, fnArgValues);
}
executeFunction(fn, args) {
return fn(...args);
}
}
class JitEmitterVisitor extends AbstractJsEmitterVisitor {
refResolver;
_evalArgNames = [];
_evalArgValues = [];
_evalExportedVars = [];
constructor(refResolver) {
super();
this.refResolver = refResolver;
}
createReturnStmt(ctx) {
const stmt = new ReturnStatement(new LiteralMapExpr(this._evalExportedVars.map(resultVar => new LiteralMapPropertyAssignment(resultVar, variable(resultVar), false))));
stmt.visitStatement(this, ctx);
}
getArgs() {
const result = {};
for (let i = 0; i < this._evalArgNames.length; i++) {
result[this._evalArgNames[i]] = this._evalArgValues[i];
}
return result;
}
visitExternalExpr(ast, ctx) {
this._emitReferenceToExternal(ast, this.refResolver.resolveExternalReference(ast.value), ctx);
return null;
}
visitWrappedNodeExpr(ast, ctx) {
this._emitReferenceToExternal(ast, ast.node, ctx);
return null;
}
visitDeclareVarStmt(stmt, ctx) {
if (stmt.hasModifier(StmtModifier.Exported)) {
this._evalExportedVars.push(stmt.name);
}
return super.visitDeclareVarStmt(stmt, ctx);
}
visitDeclareFunctionStmt(stmt, ctx) {
if (stmt.hasModifier(StmtModifier.Exported)) {
this._evalExportedVars.push(stmt.name);
}
return super.visitDeclareFunctionStmt(stmt, ctx);
}
_emitReferenceToExternal(ast, value, ctx) {
let id = this._evalArgValues.indexOf(value);
if (id === -1) {
id = this._evalArgValues.length;
this._evalArgValues.push(value);
const name = identifierName({
reference: value
}) || 'val';
this._evalArgNames.push(`jit_${name}_${id}`);
}
ctx.print(ast, this._evalArgNames[id]);
}
}
function isUseStrictStatement(statement) {
return statement.isEquivalent(literal('use strict').toStmt());
}
function compileInjector(meta) {
const definitionMap = new DefinitionMap();
if (meta.providers !== null) {
definitionMap.set('providers', meta.providers);
}
if (meta.imports.length > 0) {
definitionMap.set('imports', literalArr(meta.imports));
}
const expression = importExpr(Identifiers.defineInjector).callFn([definitionMap.toLiteralMap()], undefined, true);
const type = createInjectorType(meta);
return {
expression,
type,
statements: []
};
}
function createInjectorType(meta) {
return new ExpressionType(importExpr(Identifiers.InjectorDeclaration, [new ExpressionType(meta.type.type)]));
}
class R3JitReflector {
context;
constructor(context) {
this.context = context;
}
resolveExternalReference(ref) {
if (ref.moduleName !== '@angular/core') {
throw new Error(`Cannot resolve external reference to ${ref.moduleName}, only references to @angular/core are supported.`);
}
if (!this.context.hasOwnProperty(ref.name)) {
throw new Error(`No value provided for @angular/core symbol '${ref.name}'.`);
}
return this.context[ref.name];
}
}
var R3SelectorScopeMode;
(function (R3SelectorScopeMode) {
R3SelectorScopeMode[R3SelectorScopeMode["Inline"] = 0] = "Inline";
R3SelectorScopeMode[R3SelectorScopeMode["SideEffect"] = 1] = "SideEffect";
R3SelectorScopeMode[R3SelectorScopeMode["Omit"] = 2] = "Omit";
})(R3SelectorScopeMode || (R3SelectorScopeMode = {}));
var R3NgModuleMetadataKind;
(function (R3NgModuleMetadataKind) {
R3NgModuleMetadataKind[R3NgModuleMetadataKind["Global"] = 0] = "Global";
R3NgModuleMetadataKind[R3NgModuleMetadataKind["Local"] = 1] = "Local";
})(R3NgModuleMetadataKind || (R3NgModuleMetadataKind = {}));
function compileNgModule(meta) {
const statements = [];
const definitionMap = new DefinitionMap();
definitionMap.set('type', meta.type.value);
if (meta.kind === R3NgModuleMetadataKind.Global && meta.bootstrap.length > 0) {
definitionMap.set('bootstrap', refsToArray(meta.bootstrap, meta.containsForwardDecls));
}
if (meta.selectorScopeMode === R3SelectorScopeMode.Inline) {
if (meta.declarations.length > 0) {
definitionMap.set('declarations', refsToArray(meta.declarations, meta.containsForwardDecls));
}
if (meta.imports.length > 0) {
definitionMap.set('imports', refsToArray(meta.imports, meta.containsForwardDecls));
}
if (meta.exports.length > 0) {
definitionMap.set('exports', refsToArray(meta.exports, meta.containsForwardDecls));
}
} else if (meta.selectorScopeMode === R3SelectorScopeMode.SideEffect) {
const setNgModuleScopeCall = generateSetNgModuleScopeCall(meta);
if (setNgModuleScopeCall !== null) {
statements.push(setNgModuleScopeCall);
}
} else ;
if (meta.schemas !== null && meta.schemas.length > 0) {
definitionMap.set('schemas', literalArr(meta.schemas.map(ref => ref.value)));
}
if (meta.id !== null) {
definitionMap.set('id', meta.id);
statements.push(importExpr(Identifiers.registerNgModuleType).callFn([meta.type.value, meta.id]).toStmt());
}
const expression = importExpr(Identifiers.defineNgModule).callFn([definitionMap.toLiteralMap()], undefined, true);
const type = createNgModuleType(meta);
return {
expression,
type,
statements
};
}
function compileNgModuleDeclarationExpression(meta) {
const definitionMap = new DefinitionMap();
definitionMap.set('type', new WrappedNodeExpr(meta.type));
if (meta.bootstrap !== undefined) {
definitionMap.set('bootstrap', new WrappedNodeExpr(meta.bootstrap));
}
if (meta.declarations !== undefined) {
definitionMap.set('declarations', new WrappedNodeExpr(meta.declarations));
}
if (meta.imports !== undefined) {
definitionMap.set('imports', new WrappedNodeExpr(meta.imports));
}
if (meta.exports !== undefined) {
definitionMap.set('exports', new WrappedNodeExpr(meta.exports));
}
if (meta.schemas !== undefined) {
definitionMap.set('schemas', new WrappedNodeExpr(meta.schemas));
}
if (meta.id !== undefined) {
definitionMap.set('id', new WrappedNodeExpr(meta.id));
}
return importExpr(Identifiers.defineNgModule).callFn([definitionMap.toLiteralMap()]);
}
function createNgModuleType(meta) {
if (meta.kind === R3NgModuleMetadataKind.Local) {
return new ExpressionType(meta.type.value);
}
const {
type: moduleType,
declarations,
exports,
imports,
includeImportTypes,
publicDeclarationTypes
} = meta;
return new ExpressionType(importExpr(Identifiers.NgModuleDeclaration, [new ExpressionType(moduleType.type), publicDeclarationTypes === null ? tupleTypeOf(declarations) : tupleOfTypes(publicDeclarationTypes), includeImportTypes ? tupleTypeOf(imports) : NONE_TYPE, tupleTypeOf(exports)]));
}
function generateSetNgModuleScopeCall(meta) {
const scopeMap = new DefinitionMap();
if (meta.kind === R3NgModuleMetadataKind.Global) {
if (meta.declarations.length > 0) {
scopeMap.set('declarations', refsToArray(meta.declarations, meta.containsForwardDecls));
}
} else {
if (meta.declarationsExpression) {
scopeMap.set('declarations', meta.declarationsExpression);
}
}
if (meta.kind === R3NgModuleMetadataKind.Global) {
if (meta.imports.length > 0) {
scopeMap.set('imports', refsToArray(meta.imports, meta.containsForwardDecls));
}
} else {
if (meta.importsExpression) {
scopeMap.set('imports', meta.importsExpression);
}
}
if (meta.kind === R3NgModuleMetadataKind.Global) {
if (meta.exports.length > 0) {
scopeMap.set('exports', refsToArray(meta.exports, meta.containsForwardDecls));
}
} else {
if (meta.exportsExpression) {
scopeMap.set('exports', meta.exportsExpression);
}
}
if (meta.kind === R3NgModuleMetadataKind.Local && meta.bootstrapExpression) {
scopeMap.set('bootstrap', meta.bootstrapExpression);
}
if (Object.keys(scopeMap.values).length === 0) {
return null;
}
const fnCall = new InvokeFunctionExpr(importExpr(Identifiers.setNgModuleScope), [meta.type.value, scopeMap.toLiteralMap()]);
const guardedCall = jitOnlyGuardedExpression(fnCall);
const iife = new FunctionExpr([], [guardedCall.toStmt()]);
const iifeCall = new InvokeFunctionExpr(iife, []);
return iifeCall.toStmt();
}
function tupleTypeOf(exp) {
const types = exp.map(ref => typeofExpr(ref.type));
return exp.length > 0 ? expressionType(literalArr(types)) : NONE_TYPE;
}
function tupleOfTypes(types) {
const typeofTypes = types.map(type => typeofExpr(type));
return types.length > 0 ? expressionType(literalArr(typeofTypes)) : NONE_TYPE;
}
function compilePipeFromMetadata(metadata) {
const definitionMapValues = [];
definitionMapValues.push({
key: 'name',
value: literal(metadata.pipeName ?? metadata.name),
quoted: false
});
definitionMapValues.push({
key: 'type',
value: metadata.type.value,
quoted: false
});
definitionMapValues.push({
key: 'pure',
value: literal(metadata.pure),
quoted: false
});
if (metadata.isStandalone === false) {
definitionMapValues.push({
key: 'standalone',
value: literal(false),
quoted: false
});
}
const expression = importExpr(Identifiers.definePipe).callFn([literalMap(definitionMapValues)], undefined, true);
const type = createPipeType(metadata);
return {
expression,
type,
statements: []
};
}
function createPipeType(metadata) {
return new ExpressionType(importExpr(Identifiers.PipeDeclaration, [typeWithParameters(metadata.type.type, metadata.typeArgumentCount), new ExpressionType(new LiteralExpr(metadata.pipeName)), new ExpressionType(new LiteralExpr(metadata.isStandalone))]));
}
var R3TemplateDependencyKind;
(function (R3TemplateDependencyKind) {
R3TemplateDependencyKind[R3TemplateDependencyKind["Directive"] = 0] = "Directive";
R3TemplateDependencyKind[R3TemplateDependencyKind["Pipe"] = 1] = "Pipe";
R3TemplateDependencyKind[R3TemplateDependencyKind["NgModule"] = 2] = "NgModule";
})(R3TemplateDependencyKind || (R3TemplateDependencyKind = {}));
const animationKeywords = new Set(['inherit', 'initial', 'revert', 'unset', 'alternate', 'alternate-reverse', 'normal', 'reverse', 'backwards', 'both', 'forwards', 'none', 'paused', 'running', 'ease', 'ease-in', 'ease-in-out', 'ease-out', 'linear', 'step-start', 'step-end', 'end', 'jump-both', 'jump-end', 'jump-none', 'jump-start', 'start']);
const scopedAtRuleIdentifiers = ['@media', '@supports', '@document', '@layer', '@container', '@scope', '@starting-style'];
class ShadowCss {
shimCssText(cssText, selector, hostSelector = '') {
const comments = [];
cssText = cssText.replace(_commentRe, m => {
if (m.match(_commentWithHashRe)) {
comments.push(m);
} else {
const newLinesMatches = m.match(_newLinesRe);
comments.push((newLinesMatches?.join('') ?? '') + '\n');
}
return COMMENT_PLACEHOLDER;
});
cssText = this._insertDirectives(cssText);
const scopedCssText = this._scopeCssText(cssText, selector, hostSelector);
let commentIdx = 0;
return scopedCssText.replace(_commentWithHashPlaceHolderRe, () => comments[commentIdx++]);
}
_insertDirectives(cssText) {
cssText = this._insertPolyfillDirectivesInCssText(cssText);
return this._insertPolyfillRulesInCssText(cssText);
}
_scopeKeyframesRelatedCss(cssText, scopeSelector) {
const unscopedKeyframesSet = new Set();
const scopedKeyframesCssText = processRules(cssText, rule => this._scopeLocalKeyframeDeclarations(rule, scopeSelector, unscopedKeyframesSet));
return processRules(scopedKeyframesCssText, rule => this._scopeAnimationRule(rule, scopeSelector, unscopedKeyframesSet));
}
_scopeLocalKeyframeDeclarations(rule, scopeSelector, unscopedKeyframesSet) {
return {
...rule,
selector: rule.selector.replace(/(^@(?:-webkit-)?keyframes(?:\s+))(['"]?)(.+)\2(\s*)$/, (_, start, quote, keyframeName, endSpaces) => {
unscopedKeyframesSet.add(unescapeQuotes(keyframeName, quote));
return `${start}${quote}${scopeSelector}_${keyframeName}${quote}${endSpaces}`;
})
};
}
_scopeAnimationKeyframe(keyframe, scopeSelector, unscopedKeyframesSet) {
return keyframe.replace(/^(\s*)(['"]?)(.+?)\2(\s*)$/, (_, spaces1, quote, name, spaces2) => {
name = `${unscopedKeyframesSet.has(unescapeQuotes(name, quote)) ? scopeSelector + '_' : ''}${name}`;
return `${spaces1}${quote}${name}${quote}${spaces2}`;
});
}
_animationDeclarationKeyframesRe = /(^|\s+|,)(?:(?:(['"])((?:\\\\|\\\2|(?!\2).)+)\2)|(-?[A-Za-z][\w\-]*))(?=[,\s]|$)/g;
_scopeAnimationRule(rule, scopeSelector, unscopedKeyframesSet) {
let content = rule.content.replace(/((?:^|\s+|;)(?:-webkit-)?animation\s*:\s*),*([^;]+)/g, (_, start, animationDeclarations) => start + animationDeclarations.replace(this._animationDeclarationKeyframesRe, (original, leadingSpaces, quote = '', quotedName, nonQuotedName) => {
if (quotedName) {
return `${leadingSpaces}${this._scopeAnimationKeyframe(`${quote}${quotedName}${quote}`, scopeSelector, unscopedKeyframesSet)}`;
} else {
return animationKeywords.has(nonQuotedName) ? original : `${leadingSpaces}${this._scopeAnimationKeyframe(nonQuotedName, scopeSelector, unscopedKeyframesSet)}`;
}
}));
content = content.replace(/((?:^|\s+|;)(?:-webkit-)?animation-name(?:\s*):(?:\s*))([^;]+)/g, (_match, start, commaSeparatedKeyframes) => `${start}${commaSeparatedKeyframes.split(',').map(keyframe => this._scopeAnimationKeyframe(keyframe, scopeSelector, unscopedKeyframesSet)).join(',')}`);
return {
...rule,
content
};
}
_insertPolyfillDirectivesInCssText(cssText) {
return cssText.replace(_cssContentNextSelectorRe, function (...m) {
return m[2] + '{';
});
}
_insertPolyfillRulesInCssText(cssText) {
return cssText.replace(_cssContentRuleRe, (...m) => {
const rule = m[0].replace(m[1], '').replace(m[2], '');
return m[4] + rule;
});
}
_scopeCssText(cssText, scopeSelector, hostSelector) {
const unscopedRules = this._extractUnscopedRulesFromCssText(cssText);
cssText = this._insertPolyfillHostInCssText(cssText);
cssText = this._convertColonHost(cssText);
cssText = this._convertColonHostContext(cssText);
cssText = this._convertShadowDOMSelectors(cssText);
if (scopeSelector) {
cssText = this._scopeKeyframesRelatedCss(cssText, scopeSelector);
cssText = this._scopeSelectors(cssText, scopeSelector, hostSelector);
}
cssText = cssText + '\n' + unscopedRules;
return cssText.trim();
}
_extractUnscopedRulesFromCssText(cssText) {
let r = '';
let m;
_cssContentUnscopedRuleRe.lastIndex = 0;
while ((m = _cssContentUnscopedRuleRe.exec(cssText)) !== null) {
const rule = m[0].replace(m[2], '').replace(m[1], m[4]);
r += rule + '\n\n';
}
return r;
}
_convertColonHost(cssText) {
return cssText.replace(_cssColonHostRe, (_, hostSelectors, otherSelectors) => {
if (hostSelectors) {
const convertedSelectors = [];
for (const hostSelector of this._splitOnTopLevelCommas(hostSelectors, true)) {
const trimmedHostSelector = hostSelector.trim();
if (!trimmedHostSelector) break;
const convertedSelector = _polyfillHostNoCombinator + trimmedHostSelector.replace(_polyfillHost, '') + otherSelectors;
convertedSelectors.push(convertedSelector);
}
return convertedSelectors.join(',');
} else {
return _polyfillHostNoCombinator + otherSelectors;
}
});
}
*_splitOnTopLevelCommas(text, returnOnClosingParen) {
const length = text.length;
let parens = 0;
let prev = 0;
for (let i = 0; i < length; i++) {
const charCode = text.charCodeAt(i);
if (charCode === $LPAREN) {
parens++;
} else if (charCode === $RPAREN) {
parens--;
if (parens < 0 && returnOnClosingParen) {
yield text.slice(prev, i);
return;
}
} else if (charCode === $COMMA && parens === 0) {
yield text.slice(prev, i);
prev = i + 1;
}
}
yield text.slice(prev);
}
_convertColonHostContext(cssText) {
const results = [];
for (const part of this._splitOnTopLevelCommas(cssText, false)) {
results.push(this._convertColonHostContextInSelectorPart(part));
}
return results.join(',');
}
_convertColonHostContextInSelectorPart(cssText) {
return cssText.replace(_cssColonHostContextReGlobal, (selectorText, pseudoPrefix) => {
const contextSelectorGroups = [[]];
let startIndex = selectorText.indexOf(_polyfillHostContext);
while (startIndex !== -1) {
const afterPrefix = selectorText.substring(startIndex + _polyfillHostContext.length);
if (!afterPrefix || afterPrefix[0] !== '(') {
selectorText = afterPrefix;
startIndex = selectorText.indexOf(_polyfillHostContext);
continue;
}
const newContextSelectors = [];
let endIndex = 0;
for (const selector of this._splitOnTopLevelCommas(afterPrefix.substring(1), true)) {
endIndex = endIndex + selector.length + 1;
const trimmed = selector.trim();
if (trimmed) {
newContextSelectors.push(trimmed);
}
}
const contextSelectorGroupsLength = contextSelectorGroups.length;
repeatGroups(contextSelectorGroups, newContextSelectors.length);
for (let i = 0; i < newContextSelectors.length; i++) {
for (let j = 0; j < contextSelectorGroupsLength; j++) {
contextSelectorGroups[j + i * contextSelectorGroupsLength].push(newContextSelectors[i]);
}
}
selectorText = afterPrefix.substring(endIndex + 1);
startIndex = selectorText.indexOf(_polyfillHostContext);
}
return contextSelectorGroups.map(contextSelectors => _combineHostContextSelectors(contextSelectors, selectorText, pseudoPrefix)).join(', ');
});
}
_convertShadowDOMSelectors(cssText) {
return _shadowDOMSelectorsRe.reduce((result, pattern) => result.replace(pattern, ' '), cssText);
}
_scopeSelectors(cssText, scopeSelector, hostSelector) {
return processRules(cssText, rule => {
let selector = rule.selector;
let content = rule.content;
if (rule.selector[0] !== '@') {
selector = this._scopeSelector({
selector,
scopeSelector,
hostSelector,
isParentSelector: true
});
} else if (scopedAtRuleIdentifiers.some(atRule => rule.selector.startsWith(atRule))) {
content = this._scopeSelectors(rule.content, scopeSelector, hostSelector);
} else if (rule.selector.startsWith('@font-face') || rule.selector.startsWith('@page')) {
content = this._stripScopingSelectors(rule.content);
}
return new CssRule(selector, content);
});
}
_stripScopingSelectors(cssText) {
return processRules(cssText, rule => {
const selector = rule.selector.replace(_shadowDeepSelectors, ' ').replace(_polyfillHostNoCombinatorRe, ' ');
return new CssRule(selector, rule.content);
});
}
_safeSelector;
_shouldScopeIndicator;
_scopeSelector({
selector,
scopeSelector,
hostSelector,
isParentSelector = false
}) {
const selectorSplitRe = / ?,(?!(?:[^)(]*(?:\([^)(]*(?:\([^)(]*(?:\([^)(]*\)[^)(]*)*\)[^)(]*)*\)[^)(]*)*\))) ?/;
return selector.split(selectorSplitRe).map(part => part.split(_shadowDeepSelectors)).map(deepParts => {
const [shallowPart, ...otherParts] = deepParts;
const applyScope = shallowPart => {
if (this._selectorNeedsScoping(shallowPart, scopeSelector)) {
return this._applySelectorScope({
selector: shallowPart,
scopeSelector,
hostSelector,
isParentSelector
});
} else {
return shallowPart;
}
};
return [applyScope(shallowPart), ...otherParts].join(' ');
}).join(', ');
}
_selectorNeedsScoping(selector, scopeSelector) {
const re = this._makeScopeMatcher(scopeSelector);
return !re.test(selector);
}
_makeScopeMatcher(scopeSelector) {
const lre = /\[/g;
const rre = /\]/g;
scopeSelector = scopeSelector.replace(lre, '\\[').replace(rre, '\\]');
return new RegExp('^(' + scopeSelector + ')' + _selectorReSuffix, 'm');
}
_applySimpleSelectorScope(selector, scopeSelector, hostSelector) {
_polyfillHostRe.lastIndex = 0;
if (_polyfillHostRe.test(selector)) {
const replaceBy = `[${hostSelector}]`;
let result = selector;
while (result.match(_polyfillHostNoCombinatorRe)) {
result = result.replace(_polyfillHostNoCombinatorRe, (_hnc, selector) => {
return selector.replace(/([^:\)]*)(:*)(.*)/, (_, before, colon, after) => {
return before + replaceBy + colon + after;
});
});
}
return result.replace(_polyfillHostRe, replaceBy);
}
return scopeSelector + ' ' + selector;
}
_applySelectorScope({
selector,
scopeSelector,
hostSelector,
isParentSelector
}) {
const isRe = /\[is=([^\]]*)\]/g;
scopeSelector = scopeSelector.replace(isRe, (_, ...parts) => parts[0]);
const attrName = `[${scopeSelector}]`;
const _scopeSelectorPart = p => {
let scopedP = p.trim();
if (!scopedP) {
return p;
}
if (p.includes(_polyfillHostNoCombinator)) {
scopedP = this._applySimpleSelectorScope(p, scopeSelector, hostSelector);
if (!p.match(_polyfillHostNoCombinatorOutsidePseudoFunction)) {
const [_, before, colon, after] = scopedP.match(/([^:]*)(:*)([\s\S]*)/);
scopedP = before + attrName + colon + after;
}
} else {
const t = p.replace(_polyfillHostRe, '');
if (t.length > 0) {
const matches = t.match(/([^:]*)(:*)([\s\S]*)/);
if (matches) {
scopedP = matches[1] + attrName + matches[2] + matches[3];
}
}
}
return scopedP;
};
const _pseudoFunctionAwareScopeSelectorPart = selectorPart => {
let scopedPart = '';
const pseudoSelectorParts = [];
let pseudoSelectorMatch;
while ((pseudoSelectorMatch = _cssPrefixWithPseudoSelectorFunction.exec(selectorPart)) !== null) {
let openedBrackets = 1;
let index = _cssPrefixWithPseudoSelectorFunction.lastIndex;
while (index < selectorPart.length) {
const currentSymbol = selectorPart[index];
index++;
if (currentSymbol === '(') {
openedBrackets++;
continue;
}
if (currentSymbol === ')') {
openedBrackets--;
if (openedBrackets === 0) {
break;
}
continue;
}
}
pseudoSelectorParts.push(`${pseudoSelectorMatch[0]}${selectorPart.slice(_cssPrefixWithPseudoSelectorFunction.lastIndex, index)}`);
_cssPrefixWithPseudoSelectorFunction.lastIndex = index;
}
if (pseudoSelectorParts.join('') === selectorPart) {
scopedPart = pseudoSelectorParts.map(selectorPart => {
const [cssPseudoSelectorFunction] = selectorPart.match(_cssPrefixWithPseudoSelectorFunction) ?? [];
const selectorToScope = selectorPart.slice(cssPseudoSelectorFunction?.length, -1);
if (selectorToScope.includes(_polyfillHostNoCombinator)) {
this._shouldScopeIndicator = true;
}
const scopedInnerPart = this._scopeSelector({
selector: selectorToScope,
scopeSelector,
hostSelector
});
return `${cssPseudoSelectorFunction}${scopedInnerPart})`;
}).join('');
} else {
this._shouldScopeIndicator = this._shouldScopeIndicator || selectorPart.includes(_polyfillHostNoCombinator);
scopedPart = this._shouldScopeIndicator ? _scopeSelectorPart(selectorPart) : selectorPart;
}
return scopedPart;
};
if (isParentSelector) {
this._safeSelector = new SafeSelector(selector);
selector = this._safeSelector.content();
}
let scopedSelector = '';
let startIndex = 0;
let res;
const sep = /( |>|\+|~(?!=))(?!([^)(]*(?:\([^)(]*(?:\([^)(]*(?:\([^)(]*\)[^)(]*)*\)[^)(]*)*\)[^)(]*)*\)))\s*/g;
const hasHost = selector.includes(_polyfillHostNoCombinator);
if (isParentSelector || this._shouldScopeIndicator) {
this._shouldScopeIndicator = !hasHost;
}
while ((res = sep.exec(selector)) !== null) {
const separator = res[1];
const part = selector.slice(startIndex, res.index);
if (part.match(/__esc-ph-(\d+)__/) && selector[res.index + 1]?.match(/[a-fA-F\d]/)) {
continue;
}
const scopedPart = _pseudoFunctionAwareScopeSelectorPart(part);
scopedSelector += `${scopedPart} ${separator} `;
startIndex = sep.lastIndex;
}
const part = selector.substring(startIndex);
scopedSelector += _pseudoFunctionAwareScopeSelectorPart(part);
return this._safeSelector.restore(scopedSelector);
}
_insertPolyfillHostInCssText(selector) {
return selector.replace(_colonHostContextRe, _polyfillHostContext).replace(_colonHostRe, _polyfillHost);
}
}
class SafeSelector {
placeholders = [];
index = 0;
_content;
constructor(selector) {
selector = this._escapeRegexMatches(selector, /(\[[^\]]*\])/g);
selector = selector.replace(/(\\.)/g, (_, keep) => {
const replaceBy = `__esc-ph-${this.index}__`;
this.placeholders.push(keep);
this.index++;
return replaceBy;
});
this._content = selector.replace(nthRegex, (_, pseudo, exp) => {
const replaceBy = `__ph-${this.index}__`;
this.placeholders.push(`(${exp})`);
this.index++;
return pseudo + replaceBy;
});
}
restore(content) {
return content.replace(/__(?:ph|esc-ph)-(\d+)__/g, (_ph, index) => this.placeholders[+index]);
}
content() {
return this._content;
}
_escapeRegexMatches(content, pattern) {
return content.replace(pattern, (_, keep) => {
const replaceBy = `__ph-${this.index}__`;
this.placeholders.push(keep);
this.index++;
return replaceBy;
});
}
}
const _cssScopedPseudoFunctionPrefix = '(:(where|is)\\()?';
const _cssPrefixWithPseudoSelectorFunction = /:(where|is)\(/gi;
const _cssContentNextSelectorRe = /polyfill-next-selector[^}]*content:[\s]*?(['"])(.*?)\1[;\s]*}([^{]*?){/gim;
const _cssContentRuleRe = /(polyfill-rule)[^}]*(content:[\s]*(['"])(.*?)\3)[;\s]*[^}]*}/gim;
const _cssContentUnscopedRuleRe = /(polyfill-unscoped-rule)[^}]*(content:[\s]*(['"])(.*?)\3)[;\s]*[^}]*}/gim;
const _polyfillHost = '-shadowcsshost';
const _polyfillHostContext = '-shadowcsscontext';
const _noParens = '[^)(]*';
const _level1Parens = String.raw`(?:\(${_noParens}\)|${_noParens})+?`;
const _level2Parens = String.raw`(?:\(${_level1Parens}\)|${_noParens})+?`;
const _parenSuffix = String.raw`(?:\((${_level2Parens})\))`;
const nthRegex = new RegExp(String.raw`(:nth-[-\w]+)` + _parenSuffix, 'g');
const _cssColonHostRe = new RegExp(_polyfillHost + _parenSuffix + '?([^,{]*)', 'gim');
const _hostContextPattern = _polyfillHostContext + _parenSuffix + '?([^{]*)';
const _cssColonHostContextReGlobal = new RegExp(`${_cssScopedPseudoFunctionPrefix}(${_hostContextPattern})`, 'gim');
const _polyfillHostNoCombinator = _polyfillHost + '-no-combinator';
const _polyfillHostNoCombinatorOutsidePseudoFunction = new RegExp(`${_polyfillHostNoCombinator}(?![^(]*\\))`, 'g');
const _polyfillHostNoCombinatorRe = /-shadowcsshost-no-combinator([^\s,]*)/;
const _shadowDOMSelectorsRe = [/::shadow/g, /::content/g, /\/shadow-deep\//g, /\/shadow\//g];
const _shadowDeepSelectors = /(?:>>>)|(?:\/deep\/)|(?:::ng-deep)/g;
const _selectorReSuffix = '([>\\s~+[.,{:][\\s\\S]*)?$';
const _polyfillHostRe = /-shadowcsshost/gim;
const _colonHostRe = /:host/gim;
const _colonHostContextRe = /:host-context/gim;
const _newLinesRe = /\r?\n/g;
const _commentRe = /\/\*[\s\S]*?\*\//g;
const _commentWithHashRe = /\/\*\s*#\s*source(Mapping)?URL=/g;
const COMMENT_PLACEHOLDER = '%COMMENT%';
const _commentWithHashPlaceHolderRe = new RegExp(COMMENT_PLACEHOLDER, 'g');
const BLOCK_PLACEHOLDER = '%BLOCK%';
const _ruleRe = new RegExp(`(\\s*(?:${COMMENT_PLACEHOLDER}\\s*)*)([^;\\{\\}]+?)(\\s*)((?:{%BLOCK%}?\\s*;?)|(?:\\s*;))`, 'g');
const CONTENT_PAIRS = new Map([['{', '}']]);
const COMMA_IN_PLACEHOLDER = '%COMMA_IN_PLACEHOLDER%';
const SEMI_IN_PLACEHOLDER = '%SEMI_IN_PLACEHOLDER%';
const COLON_IN_PLACEHOLDER = '%COLON_IN_PLACEHOLDER%';
const _cssCommaInPlaceholderReGlobal = new RegExp(COMMA_IN_PLACEHOLDER, 'g');
const _cssSemiInPlaceholderReGlobal = new RegExp(SEMI_IN_PLACEHOLDER, 'g');
const _cssColonInPlaceholderReGlobal = new RegExp(COLON_IN_PLACEHOLDER, 'g');
class CssRule {
selector;
content;
constructor(selector, content) {
this.selector = selector;
this.content = content;
}
}
function processRules(input, ruleCallback) {
const escaped = escapeInStrings(input);
const inputWithEscapedBlocks = escapeBlocks(escaped, CONTENT_PAIRS, BLOCK_PLACEHOLDER);
let nextBlockIndex = 0;
const escapedResult = inputWithEscapedBlocks.escapedString.replace(_ruleRe, (...m) => {
const selector = m[2];
let content = '';
let suffix = m[4];
let contentPrefix = '';
if (suffix && suffix.startsWith('{' + BLOCK_PLACEHOLDER)) {
content = inputWithEscapedBlocks.blocks[nextBlockIndex++];
suffix = suffix.substring(BLOCK_PLACEHOLDER.length + 1);
contentPrefix = '{';
}
const rule = ruleCallback(new CssRule(selector, content));
return `${m[1]}${rule.selector}${m[3]}${contentPrefix}${rule.content}${suffix}`;
});
return unescapeInStrings(escapedResult);
}
class StringWithEscapedBlocks {
escapedString;
blocks;
constructor(escapedString, blocks) {
this.escapedString = escapedString;
this.blocks = blocks;
}
}
function escapeBlocks(input, charPairs, placeholder) {
const resultParts = [];
const escapedBlocks = [];
let openCharCount = 0;
let nonBlockStartIndex = 0;
let blockStartIndex = -1;
let openChar;
let closeChar;
for (let i = 0; i < input.length; i++) {
const char = input[i];
if (char === '\\') {
i++;
} else if (char === closeChar) {
openCharCount--;
if (openCharCount === 0) {
escapedBlocks.push(input.substring(blockStartIndex, i));
resultParts.push(placeholder);
nonBlockStartIndex = i;
blockStartIndex = -1;
openChar = closeChar = undefined;
}
} else if (char === openChar) {
openCharCount++;
} else if (openCharCount === 0 && charPairs.has(char)) {
openChar = char;
closeChar = charPairs.get(char);
openCharCount = 1;
blockStartIndex = i + 1;
resultParts.push(input.substring(nonBlockStartIndex, blockStartIndex));
}
}
if (blockStartIndex !== -1) {
escapedBlocks.push(input.substring(blockStartIndex));
resultParts.push(placeholder);
} else {
resultParts.push(input.substring(nonBlockStartIndex));
}
return new StringWithEscapedBlocks(resultParts.join(''), escapedBlocks);
}
const ESCAPE_IN_STRING_MAP = {
';': SEMI_IN_PLACEHOLDER,
',': COMMA_IN_PLACEHOLDER,
':': COLON_IN_PLACEHOLDER
};
function escapeInStrings(input) {
let result = input;
let currentQuoteChar = null;
for (let i = 0; i < result.length; i++) {
const char = result[i];
if (char === '\\') {
i++;
} else {
if (currentQuoteChar !== null) {
if (char === currentQuoteChar) {
currentQuoteChar = null;
} else {
const placeholder = ESCAPE_IN_STRING_MAP[char];
if (placeholder) {
result = `${result.substr(0, i)}${placeholder}${result.substr(i + 1)}`;
i += placeholder.length - 1;
}
}
} else if (char === "'" || char === '"') {
currentQuoteChar = char;
}
}
}
return result;
}
function unescapeInStrings(input) {
let result = input.replace(_cssCommaInPlaceholderReGlobal, ',');
result = result.replace(_cssSemiInPlaceholderReGlobal, ';');
result = result.replace(_cssColonInPlaceholderReGlobal, ':');
return result;
}
function unescapeQuotes(str, isQuoted) {
return !isQuoted ? str : str.replace(/((?:^|[^\\])(?:\\\\)*)\\(?=['"])/g, '$1');
}
function _combineHostContextSelectors(contextSelectors, otherSelectors, pseudoPrefix = '') {
const hostMarker = _polyfillHostNoCombinator;
_polyfillHostRe.lastIndex = 0;
const otherSelectorsHasHost = _polyfillHostRe.test(otherSelectors);
if (contextSelectors.length === 0) {
return hostMarker + otherSelectors;
}
const combined = [contextSelectors.pop() || ''];
while (contextSelectors.length > 0) {
const length = combined.length;
const contextSelector = contextSelectors.pop();
for (let i = 0; i < length; i++) {
const previousSelectors = combined[i];
combined[length * 2 + i] = previousSelectors + ' ' + contextSelector;
combined[length + i] = contextSelector + ' ' + previousSelectors;
combined[i] = contextSelector + previousSelectors;
}
}
return combined.map(s => otherSelectorsHasHost ? `${pseudoPrefix}${s}${otherSelectors}` : `${pseudoPrefix}${s}${hostMarker}${otherSelectors}, ${pseudoPrefix}${s} ${hostMarker}${otherSelectors}`).join(',');
}
function repeatGroups(groups, multiples) {
const length = groups.length;
for (let i = 1; i < multiples; i++) {
for (let j = 0; j < length; j++) {
groups[j + i * length] = groups[j].slice(0);
}
}
}
var OpKind;
(function (OpKind) {
OpKind[OpKind["ListEnd"] = 0] = "ListEnd";
OpKind[OpKind["Statement"] = 1] = "Statement";
OpKind[OpKind["Variable"] = 2] = "Variable";
OpKind[OpKind["ElementStart"] = 3] = "ElementStart";
OpKind[OpKind["Element"] = 4] = "Element";
OpKind[OpKind["Template"] = 5] = "Template";
OpKind[OpKind["ElementEnd"] = 6] = "ElementEnd";
OpKind[OpKind["ContainerStart"] = 7] = "ContainerStart";
OpKind[OpKind["Container"] = 8] = "Container";
OpKind[OpKind["ContainerEnd"] = 9] = "ContainerEnd";
OpKind[OpKind["DisableBindings"] = 10] = "DisableBindings";
OpKind[OpKind["ConditionalCreate"] = 11] = "ConditionalCreate";
OpKind[OpKind["ConditionalBranchCreate"] = 12] = "ConditionalBranchCreate";
OpKind[OpKind["Conditional"] = 13] = "Conditional";
OpKind[OpKind["EnableBindings"] = 14] = "EnableBindings";
OpKind[OpKind["Text"] = 15] = "Text";
OpKind[OpKind["Listener"] = 16] = "Listener";
OpKind[OpKind["InterpolateText"] = 17] = "InterpolateText";
OpKind[OpKind["Binding"] = 18] = "Binding";
OpKind[OpKind["Property"] = 19] = "Property";
OpKind[OpKind["StyleProp"] = 20] = "StyleProp";
OpKind[OpKind["ClassProp"] = 21] = "ClassProp";
OpKind[OpKind["StyleMap"] = 22] = "StyleMap";
OpKind[OpKind["ClassMap"] = 23] = "ClassMap";
OpKind[OpKind["Advance"] = 24] = "Advance";
OpKind[OpKind["Pipe"] = 25] = "Pipe";
OpKind[OpKind["Attribute"] = 26] = "Attribute";
OpKind[OpKind["ExtractedAttribute"] = 27] = "ExtractedAttribute";
OpKind[OpKind["Defer"] = 28] = "Defer";
OpKind[OpKind["DeferOn"] = 29] = "DeferOn";
OpKind[OpKind["DeferWhen"] = 30] = "DeferWhen";
OpKind[OpKind["I18nMessage"] = 31] = "I18nMessage";
OpKind[OpKind["DomProperty"] = 32] = "DomProperty";
OpKind[OpKind["Namespace"] = 33] = "Namespace";
OpKind[OpKind["ProjectionDef"] = 34] = "ProjectionDef";
OpKind[OpKind["Projection"] = 35] = "Projection";
OpKind[OpKind["RepeaterCreate"] = 36] = "RepeaterCreate";
OpKind[OpKind["Repeater"] = 37] = "Repeater";
OpKind[OpKind["TwoWayProperty"] = 38] = "TwoWayProperty";
OpKind[OpKind["TwoWayListener"] = 39] = "TwoWayListener";
OpKind[OpKind["DeclareLet"] = 40] = "DeclareLet";
OpKind[OpKind["StoreLet"] = 41] = "StoreLet";
OpKind[OpKind["I18nStart"] = 42] = "I18nStart";
OpKind[OpKind["I18n"] = 43] = "I18n";
OpKind[OpKind["I18nEnd"] = 44] = "I18nEnd";
OpKind[OpKind["I18nExpression"] = 45] = "I18nExpression";
OpKind[OpKind["I18nApply"] = 46] = "I18nApply";
OpKind[OpKind["IcuStart"] = 47] = "IcuStart";
OpKind[OpKind["IcuEnd"] = 48] = "IcuEnd";
OpKind[OpKind["IcuPlaceholder"] = 49] = "IcuPlaceholder";
OpKind[OpKind["I18nContext"] = 50] = "I18nContext";
OpKind[OpKind["I18nAttributes"] = 51] = "I18nAttributes";
OpKind[OpKind["SourceLocation"] = 52] = "SourceLocation";
OpKind[OpKind["Animation"] = 53] = "Animation";
OpKind[OpKind["AnimationString"] = 54] = "AnimationString";
OpKind[OpKind["AnimationBinding"] = 55] = "AnimationBinding";
OpKind[OpKind["AnimationListener"] = 56] = "AnimationListener";
OpKind[OpKind["Control"] = 57] = "Control";
OpKind[OpKind["ControlCreate"] = 58] = "ControlCreate";
})(OpKind || (OpKind = {}));
var ExpressionKind;
(function (ExpressionKind) {
ExpressionKind[ExpressionKind["LexicalRead"] = 0] = "LexicalRead";
ExpressionKind[ExpressionKind["Context"] = 1] = "Context";
ExpressionKind[ExpressionKind["TrackContext"] = 2] = "TrackContext";
ExpressionKind[ExpressionKind["ReadVariable"] = 3] = "ReadVariable";
ExpressionKind[ExpressionKind["NextContext"] = 4] = "NextContext";
ExpressionKind[ExpressionKind["Reference"] = 5] = "Reference";
ExpressionKind[ExpressionKind["StoreLet"] = 6] = "StoreLet";
ExpressionKind[ExpressionKind["ContextLetReference"] = 7] = "ContextLetReference";
ExpressionKind[ExpressionKind["GetCurrentView"] = 8] = "GetCurrentView";
ExpressionKind[ExpressionKind["RestoreView"] = 9] = "RestoreView";
ExpressionKind[ExpressionKind["ResetView"] = 10] = "ResetView";
ExpressionKind[ExpressionKind["PureFunctionExpr"] = 11] = "PureFunctionExpr";
ExpressionKind[ExpressionKind["PureFunctionParameterExpr"] = 12] = "PureFunctionParameterExpr";
ExpressionKind[ExpressionKind["PipeBinding"] = 13] = "PipeBinding";
ExpressionKind[ExpressionKind["PipeBindingVariadic"] = 14] = "PipeBindingVariadic";
ExpressionKind[ExpressionKind["SafePropertyRead"] = 15] = "SafePropertyRead";
ExpressionKind[ExpressionKind["SafeKeyedRead"] = 16] = "SafeKeyedRead";
ExpressionKind[ExpressionKind["SafeInvokeFunction"] = 17] = "SafeInvokeFunction";
ExpressionKind[ExpressionKind["SafeTernaryExpr"] = 18] = "SafeTernaryExpr";
ExpressionKind[ExpressionKind["EmptyExpr"] = 19] = "EmptyExpr";
ExpressionKind[ExpressionKind["AssignTemporaryExpr"] = 20] = "AssignTemporaryExpr";
ExpressionKind[ExpressionKind["ReadTemporaryExpr"] = 21] = "ReadTemporaryExpr";
ExpressionKind[ExpressionKind["SlotLiteralExpr"] = 22] = "SlotLiteralExpr";
ExpressionKind[ExpressionKind["ConditionalCase"] = 23] = "ConditionalCase";
ExpressionKind[ExpressionKind["ConstCollected"] = 24] = "ConstCollected";
ExpressionKind[ExpressionKind["TwoWayBindingSet"] = 25] = "TwoWayBindingSet";
})(ExpressionKind || (ExpressionKind = {}));
var VariableFlags;
(function (VariableFlags) {
VariableFlags[VariableFlags["None"] = 0] = "None";
VariableFlags[VariableFlags["AlwaysInline"] = 1] = "AlwaysInline";
})(VariableFlags || (VariableFlags = {}));
var SemanticVariableKind;
(function (SemanticVariableKind) {
SemanticVariableKind[SemanticVariableKind["Context"] = 0] = "Context";
SemanticVariableKind[SemanticVariableKind["Identifier"] = 1] = "Identifier";
SemanticVariableKind[SemanticVariableKind["SavedView"] = 2] = "SavedView";
SemanticVariableKind[SemanticVariableKind["Alias"] = 3] = "Alias";
})(SemanticVariableKind || (SemanticVariableKind = {}));
var CompatibilityMode;
(function (CompatibilityMode) {
CompatibilityMode[CompatibilityMode["Normal"] = 0] = "Normal";
CompatibilityMode[CompatibilityMode["TemplateDefinitionBuilder"] = 1] = "TemplateDefinitionBuilder";
})(CompatibilityMode || (CompatibilityMode = {}));
var BindingKind;
(function (BindingKind) {
BindingKind[BindingKind["Attribute"] = 0] = "Attribute";
BindingKind[BindingKind["ClassName"] = 1] = "ClassName";
BindingKind[BindingKind["StyleProperty"] = 2] = "StyleProperty";
BindingKind[BindingKind["Property"] = 3] = "Property";
BindingKind[BindingKind["Template"] = 4] = "Template";
BindingKind[BindingKind["I18n"] = 5] = "I18n";
BindingKind[BindingKind["LegacyAnimation"] = 6] = "LegacyAnimation";
BindingKind[BindingKind["TwoWayProperty"] = 7] = "TwoWayProperty";
BindingKind[BindingKind["Animation"] = 8] = "Animation";
})(BindingKind || (BindingKind = {}));
var I18nParamResolutionTime;
(function (I18nParamResolutionTime) {
I18nParamResolutionTime[I18nParamResolutionTime["Creation"] = 0] = "Creation";
I18nParamResolutionTime[I18nParamResolutionTime["Postproccessing"] = 1] = "Postproccessing";
})(I18nParamResolutionTime || (I18nParamResolutionTime = {}));
var I18nExpressionFor;
(function (I18nExpressionFor) {
I18nExpressionFor[I18nExpressionFor["I18nText"] = 0] = "I18nText";
I18nExpressionFor[I18nExpressionFor["I18nAttribute"] = 1] = "I18nAttribute";
})(I18nExpressionFor || (I18nExpressionFor = {}));
var I18nParamValueFlags;
(function (I18nParamValueFlags) {
I18nParamValueFlags[I18nParamValueFlags["None"] = 0] = "None";
I18nParamValueFlags[I18nParamValueFlags["ElementTag"] = 1] = "ElementTag";
I18nParamValueFlags[I18nParamValueFlags["TemplateTag"] = 2] = "TemplateTag";
I18nParamValueFlags[I18nParamValueFlags["OpenTag"] = 4] = "OpenTag";
I18nParamValueFlags[I18nParamValueFlags["CloseTag"] = 8] = "CloseTag";
I18nParamValueFlags[I18nParamValueFlags["ExpressionIndex"] = 16] = "ExpressionIndex";
})(I18nParamValueFlags || (I18nParamValueFlags = {}));
var Namespace;
(function (Namespace) {
Namespace[Namespace["HTML"] = 0] = "HTML";
Namespace[Namespace["SVG"] = 1] = "SVG";
Namespace[Namespace["Math"] = 2] = "Math";
})(Namespace || (Namespace = {}));
var DeferTriggerKind;
(function (DeferTriggerKind) {
DeferTriggerKind[DeferTriggerKind["Idle"] = 0] = "Idle";
DeferTriggerKind[DeferTriggerKind["Immediate"] = 1] = "Immediate";
DeferTriggerKind[DeferTriggerKind["Timer"] = 2] = "Timer";
DeferTriggerKind[DeferTriggerKind["Hover"] = 3] = "Hover";
DeferTriggerKind[DeferTriggerKind["Interaction"] = 4] = "Interaction";
DeferTriggerKind[DeferTriggerKind["Viewport"] = 5] = "Viewport";
DeferTriggerKind[DeferTriggerKind["Never"] = 6] = "Never";
})(DeferTriggerKind || (DeferTriggerKind = {}));
var I18nContextKind;
(function (I18nContextKind) {
I18nContextKind[I18nContextKind["RootI18n"] = 0] = "RootI18n";
I18nContextKind[I18nContextKind["Icu"] = 1] = "Icu";
I18nContextKind[I18nContextKind["Attr"] = 2] = "Attr";
})(I18nContextKind || (I18nContextKind = {}));
var TemplateKind;
(function (TemplateKind) {
TemplateKind[TemplateKind["NgTemplate"] = 0] = "NgTemplate";
TemplateKind[TemplateKind["Structural"] = 1] = "Structural";
TemplateKind[TemplateKind["Block"] = 2] = "Block";
})(TemplateKind || (TemplateKind = {}));
const ConsumesSlot = Symbol('ConsumesSlot');
const DependsOnSlotContext = Symbol('DependsOnSlotContext');
const ConsumesVarsTrait = Symbol('ConsumesVars');
const UsesVarOffset = Symbol('UsesVarOffset');
const TRAIT_CONSUMES_SLOT = {
[ConsumesSlot]: true,
numSlotsUsed: 1
};
const TRAIT_DEPENDS_ON_SLOT_CONTEXT = {
[DependsOnSlotContext]: true
};
const TRAIT_CONSUMES_VARS = {
[ConsumesVarsTrait]: true
};
function hasConsumesSlotTrait(op) {
return op[ConsumesSlot] === true;
}
function hasDependsOnSlotContextTrait(value) {
return value[DependsOnSlotContext] === true;
}
function hasConsumesVarsTrait(value) {
return value[ConsumesVarsTrait] === true;
}
function hasUsesVarOffsetTrait(expr) {
return expr[UsesVarOffset] === true;
}
function createStatementOp(statement) {
return {
kind: OpKind.Statement,
statement,
...NEW_OP
};
}
function createVariableOp(xref, variable, initializer, flags) {
return {
kind: OpKind.Variable,
xref,
variable,
initializer,
flags,
...NEW_OP
};
}
const NEW_OP = {
debugListId: null,
prev: null,
next: null
};
function createInterpolateTextOp(xref, interpolation, sourceSpan) {
return {
kind: OpKind.InterpolateText,
target: xref,
interpolation,
sourceSpan,
...TRAIT_DEPENDS_ON_SLOT_CONTEXT,
...TRAIT_CONSUMES_VARS,
...NEW_OP
};
}
class Interpolation {
strings;
expressions;
i18nPlaceholders;
constructor(strings, expressions, i18nPlaceholders) {
this.strings = strings;
this.expressions = expressions;
this.i18nPlaceholders = i18nPlaceholders;
if (i18nPlaceholders.length !== 0 && i18nPlaceholders.length !== expressions.length) {
throw new Error(`Expected ${expressions.length} placeholders to match interpolation expression count, but got ${i18nPlaceholders.length}`);
}
}
}
function createBindingOp(target, kind, name, expression, unit, securityContext, isTextAttribute, isStructuralTemplateAttribute, templateKind, i18nMessage, sourceSpan) {
return {
kind: OpKind.Binding,
bindingKind: kind,
target,
name,
expression,
unit,
securityContext,
isTextAttribute,
isStructuralTemplateAttribute,
templateKind,
i18nContext: null,
i18nMessage,
sourceSpan,
...NEW_OP
};
}
function createPropertyOp(target, name, expression, bindingKind, securityContext, isStructuralTemplateAttribute, templateKind, i18nContext, i18nMessage, sourceSpan) {
return {
kind: OpKind.Property,
target,
name,
expression,
bindingKind,
securityContext,
sanitizer: null,
isStructuralTemplateAttribute,
templateKind,
i18nContext,
i18nMessage,
sourceSpan,
...TRAIT_DEPENDS_ON_SLOT_CONTEXT,
...TRAIT_CONSUMES_VARS,
...NEW_OP
};
}
function createTwoWayPropertyOp(target, name, expression, securityContext, isStructuralTemplateAttribute, templateKind, i18nContext, i18nMessage, sourceSpan) {
return {
kind: OpKind.TwoWayProperty,
target,
name,
expression,
securityContext,
sanitizer: null,
isStructuralTemplateAttribute,
templateKind,
i18nContext,
i18nMessage,
sourceSpan,
...TRAIT_DEPENDS_ON_SLOT_CONTEXT,
...TRAIT_CONSUMES_VARS,
...NEW_OP
};
}
function createStylePropOp(xref, name, expression, unit, sourceSpan) {
return {
kind: OpKind.StyleProp,
target: xref,
name,
expression,
unit,
sourceSpan,
...TRAIT_DEPENDS_ON_SLOT_CONTEXT,
...TRAIT_CONSUMES_VARS,
...NEW_OP
};
}
function createClassPropOp(xref, name, expression, sourceSpan) {
return {
kind: OpKind.ClassProp,
target: xref,
name,
expression,
sourceSpan,
...TRAIT_DEPENDS_ON_SLOT_CONTEXT,
...TRAIT_CONSUMES_VARS,
...NEW_OP
};
}
function createStyleMapOp(xref, expression, sourceSpan) {
return {
kind: OpKind.StyleMap,
target: xref,
expression,
sourceSpan,
...TRAIT_DEPENDS_ON_SLOT_CONTEXT,
...TRAIT_CONSUMES_VARS,
...NEW_OP
};
}
function createClassMapOp(xref, expression, sourceSpan) {
return {
kind: OpKind.ClassMap,
target: xref,
expression,
sourceSpan,
...TRAIT_DEPENDS_ON_SLOT_CONTEXT,
...TRAIT_CONSUMES_VARS,
...NEW_OP
};
}
function createAttributeOp(target, namespace, name, expression, securityContext, isTextAttribute, isStructuralTemplateAttribute, templateKind, i18nMessage, sourceSpan) {
return {
kind: OpKind.Attribute,
target,
namespace,
name,
expression,
securityContext,
sanitizer: null,
isTextAttribute,
isStructuralTemplateAttribute,
templateKind,
i18nContext: null,
i18nMessage,
sourceSpan,
...TRAIT_DEPENDS_ON_SLOT_CONTEXT,
...TRAIT_CONSUMES_VARS,
...NEW_OP
};
}
function createAdvanceOp(delta, sourceSpan) {
return {
kind: OpKind.Advance,
delta,
sourceSpan,
...NEW_OP
};
}
function createConditionalOp(target, test, conditions, sourceSpan) {
return {
kind: OpKind.Conditional,
target,
test,
conditions,
processed: null,
sourceSpan,
contextValue: null,
...NEW_OP,
...TRAIT_DEPENDS_ON_SLOT_CONTEXT,
...TRAIT_CONSUMES_VARS
};
}
function createRepeaterOp(repeaterCreate, targetSlot, collection, sourceSpan) {
return {
kind: OpKind.Repeater,
target: repeaterCreate,
targetSlot,
collection,
sourceSpan,
...NEW_OP,
...TRAIT_DEPENDS_ON_SLOT_CONTEXT
};
}
function createAnimationBindingOp(name, target, animationKind, expression, securityContext, sourceSpan, animationBindingKind) {
return {
kind: OpKind.AnimationBinding,
name,
target,
animationKind,
expression,
i18nMessage: null,
securityContext,
sanitizer: null,
sourceSpan,
animationBindingKind,
...NEW_OP
};
}
function createDeferWhenOp(target, expr, modifier, sourceSpan) {
return {
kind: OpKind.DeferWhen,
target,
expr,
modifier,
sourceSpan,
...NEW_OP,
...TRAIT_DEPENDS_ON_SLOT_CONTEXT,
...TRAIT_CONSUMES_VARS
};
}
function createI18nExpressionOp(context, target, i18nOwner, handle, expression, icuPlaceholder, i18nPlaceholder, resolutionTime, usage, name, sourceSpan) {
return {
kind: OpKind.I18nExpression,
context,
target,
i18nOwner,
handle,
expression,
icuPlaceholder,
i18nPlaceholder,
resolutionTime,
usage,
name,
sourceSpan,
...NEW_OP,
...TRAIT_CONSUMES_VARS,
...TRAIT_DEPENDS_ON_SLOT_CONTEXT
};
}
function createI18nApplyOp(owner, handle, sourceSpan) {
return {
kind: OpKind.I18nApply,
owner,
handle,
sourceSpan,
...NEW_OP
};
}
function createStoreLetOp(target, declaredName, value, sourceSpan) {
return {
kind: OpKind.StoreLet,
target,
declaredName,
value,
sourceSpan,
...TRAIT_DEPENDS_ON_SLOT_CONTEXT,
...TRAIT_CONSUMES_VARS,
...NEW_OP
};
}
function createControlOp(op) {
return {
kind: OpKind.Control,
target: op.target,
name: op.name,
expression: op.expression,
bindingKind: op.bindingKind,
securityContext: op.securityContext,
sanitizer: null,
isStructuralTemplateAttribute: op.isStructuralTemplateAttribute,
templateKind: op.templateKind,
i18nContext: op.i18nContext,
i18nMessage: op.i18nMessage,
sourceSpan: op.sourceSpan,
...TRAIT_DEPENDS_ON_SLOT_CONTEXT,
...TRAIT_CONSUMES_VARS,
...NEW_OP
};
}
function isIrExpression(expr) {
return expr instanceof ExpressionBase;
}
class ExpressionBase extends Expression {
constructor(sourceSpan = null) {
super(null, sourceSpan);
}
}
class LexicalReadExpr extends ExpressionBase {
name;
kind = ExpressionKind.LexicalRead;
constructor(name) {
super();
this.name = name;
}
visitExpression(visitor, context) {}
isEquivalent(other) {
return this.name === other.name;
}
isConstant() {
return false;
}
transformInternalExpressions() {}
clone() {
return new LexicalReadExpr(this.name);
}
}
class ReferenceExpr extends ExpressionBase {
target;
targetSlot;
offset;
kind = ExpressionKind.Reference;
constructor(target, targetSlot, offset) {
super();
this.target = target;
this.targetSlot = targetSlot;
this.offset = offset;
}
visitExpression() {}
isEquivalent(e) {
return e instanceof ReferenceExpr && e.target === this.target;
}
isConstant() {
return false;
}
transformInternalExpressions() {}
clone() {
return new ReferenceExpr(this.target, this.targetSlot, this.offset);
}
}
class StoreLetExpr extends ExpressionBase {
target;
value;
sourceSpan;
kind = ExpressionKind.StoreLet;
[ConsumesVarsTrait] = true;
[DependsOnSlotContext] = true;
constructor(target, value, sourceSpan) {
super();
this.target = target;
this.value = value;
this.sourceSpan = sourceSpan;
}
visitExpression() {}
isEquivalent(e) {
return e instanceof StoreLetExpr && e.target === this.target && e.value.isEquivalent(this.value);
}
isConstant() {
return false;
}
transformInternalExpressions(transform, flags) {
this.value = transformExpressionsInExpression(this.value, transform, flags);
}
clone() {
return new StoreLetExpr(this.target, this.value, this.sourceSpan);
}
}
class ContextLetReferenceExpr extends ExpressionBase {
target;
targetSlot;
kind = ExpressionKind.ContextLetReference;
constructor(target, targetSlot) {
super();
this.target = target;
this.targetSlot = targetSlot;
}
visitExpression() {}
isEquivalent(e) {
return e instanceof ContextLetReferenceExpr && e.target === this.target;
}
isConstant() {
return false;
}
transformInternalExpressions() {}
clone() {
return new ContextLetReferenceExpr(this.target, this.targetSlot);
}
}
class ContextExpr extends ExpressionBase {
view;
kind = ExpressionKind.Context;
constructor(view) {
super();
this.view = view;
}
visitExpression() {}
isEquivalent(e) {
return e instanceof ContextExpr && e.view === this.view;
}
isConstant() {
return false;
}
transformInternalExpressions() {}
clone() {
return new ContextExpr(this.view);
}
}
class TrackContextExpr extends ExpressionBase {
view;
kind = ExpressionKind.TrackContext;
constructor(view) {
super();
this.view = view;
}
visitExpression() {}
isEquivalent(e) {
return e instanceof TrackContextExpr && e.view === this.view;
}
isConstant() {
return false;
}
transformInternalExpressions() {}
clone() {
return new TrackContextExpr(this.view);
}
}
class NextContextExpr extends ExpressionBase {
kind = ExpressionKind.NextContext;
steps = 1;
constructor() {
super();
}
visitExpression() {}
isEquivalent(e) {
return e instanceof NextContextExpr && e.steps === this.steps;
}
isConstant() {
return false;
}
transformInternalExpressions() {}
clone() {
const expr = new NextContextExpr();
expr.steps = this.steps;
return expr;
}
}
class GetCurrentViewExpr extends ExpressionBase {
kind = ExpressionKind.GetCurrentView;
constructor() {
super();
}
visitExpression() {}
isEquivalent(e) {
return e instanceof GetCurrentViewExpr;
}
isConstant() {
return false;
}
transformInternalExpressions() {}
clone() {
return new GetCurrentViewExpr();
}
}
class RestoreViewExpr extends ExpressionBase {
view;
kind = ExpressionKind.RestoreView;
constructor(view) {
super();
this.view = view;
}
visitExpression(visitor, context) {
if (typeof this.view !== 'number') {
this.view.visitExpression(visitor, context);
}
}
isEquivalent(e) {
if (!(e instanceof RestoreViewExpr) || typeof e.view !== typeof this.view) {
return false;
}
if (typeof this.view === 'number') {
return this.view === e.view;
} else {
return this.view.isEquivalent(e.view);
}
}
isConstant() {
return false;
}
transformInternalExpressions(transform, flags) {
if (typeof this.view !== 'number') {
this.view = transformExpressionsInExpression(this.view, transform, flags);
}
}
clone() {
return new RestoreViewExpr(this.view instanceof Expression ? this.view.clone() : this.view);
}
}
class ResetViewExpr extends ExpressionBase {
expr;
kind = ExpressionKind.ResetView;
constructor(expr) {
super();
this.expr = expr;
}
visitExpression(visitor, context) {
this.expr.visitExpression(visitor, context);
}
isEquivalent(e) {
return e instanceof ResetViewExpr && this.expr.isEquivalent(e.expr);
}
isConstant() {
return false;
}
transformInternalExpressions(transform, flags) {
this.expr = transformExpressionsInExpression(this.expr, transform, flags);
}
clone() {
return new ResetViewExpr(this.expr.clone());
}
}
class TwoWayBindingSetExpr extends ExpressionBase {
target;
value;
kind = ExpressionKind.TwoWayBindingSet;
constructor(target, value) {
super();
this.target = target;
this.value = value;
}
visitExpression(visitor, context) {
this.target.visitExpression(visitor, context);
this.value.visitExpression(visitor, context);
}
isEquivalent(other) {
return this.target.isEquivalent(other.target) && this.value.isEquivalent(other.value);
}
isConstant() {
return false;
}
transformInternalExpressions(transform, flags) {
this.target = transformExpressionsInExpression(this.target, transform, flags);
this.value = transformExpressionsInExpression(this.value, transform, flags);
}
clone() {
return new TwoWayBindingSetExpr(this.target, this.value);
}
}
class ReadVariableExpr extends ExpressionBase {
xref;
kind = ExpressionKind.ReadVariable;
name = null;
constructor(xref) {
super();
this.xref = xref;
}
visitExpression() {}
isEquivalent(other) {
return other instanceof ReadVariableExpr && other.xref === this.xref;
}
isConstant() {
return false;
}
transformInternalExpressions() {}
clone() {
const expr = new ReadVariableExpr(this.xref);
expr.name = this.name;
return expr;
}
}
class PureFunctionExpr extends ExpressionBase {
kind = ExpressionKind.PureFunctionExpr;
[ConsumesVarsTrait] = true;
[UsesVarOffset] = true;
varOffset = null;
body;
args;
fn = null;
constructor(expression, args) {
super();
this.body = expression;
this.args = args;
}
visitExpression(visitor, context) {
this.body?.visitExpression(visitor, context);
for (const arg of this.args) {
arg.visitExpression(visitor, context);
}
}
isEquivalent(other) {
if (!(other instanceof PureFunctionExpr) || other.args.length !== this.args.length) {
return false;
}
return other.body !== null && this.body !== null && other.body.isEquivalent(this.body) && other.args.every((arg, idx) => arg.isEquivalent(this.args[idx]));
}
isConstant() {
return false;
}
transformInternalExpressions(transform, flags) {
if (this.body !== null) {
this.body = transformExpressionsInExpression(this.body, transform, flags | VisitorContextFlag.InChildOperation);
} else if (this.fn !== null) {
this.fn = transformExpressionsInExpression(this.fn, transform, flags);
}
for (let i = 0; i < this.args.length; i++) {
this.args[i] = transformExpressionsInExpression(this.args[i], transform, flags);
}
}
clone() {
const expr = new PureFunctionExpr(this.body?.clone() ?? null, this.args.map(arg => arg.clone()));
expr.fn = this.fn?.clone() ?? null;
expr.varOffset = this.varOffset;
return expr;
}
}
class PureFunctionParameterExpr extends ExpressionBase {
index;
kind = ExpressionKind.PureFunctionParameterExpr;
constructor(index) {
super();
this.index = index;
}
visitExpression() {}
isEquivalent(other) {
return other instanceof PureFunctionParameterExpr && other.index === this.index;
}
isConstant() {
return true;
}
transformInternalExpressions() {}
clone() {
return new PureFunctionParameterExpr(this.index);
}
}
class PipeBindingExpr extends ExpressionBase {
target;
targetSlot;
name;
args;
kind = ExpressionKind.PipeBinding;
[ConsumesVarsTrait] = true;
[UsesVarOffset] = true;
varOffset = null;
constructor(target, targetSlot, name, args) {
super();
this.target = target;
this.targetSlot = targetSlot;
this.name = name;
this.args = args;
}
visitExpression(visitor, context) {
for (const arg of this.args) {
arg.visitExpression(visitor, context);
}
}
isEquivalent() {
return false;
}
isConstant() {
return false;
}
transformInternalExpressions(transform, flags) {
for (let idx = 0; idx < this.args.length; idx++) {
this.args[idx] = transformExpressionsInExpression(this.args[idx], transform, flags);
}
}
clone() {
const r = new PipeBindingExpr(this.target, this.targetSlot, this.name, this.args.map(a => a.clone()));
r.varOffset = this.varOffset;
return r;
}
}
class PipeBindingVariadicExpr extends ExpressionBase {
target;
targetSlot;
name;
args;
numArgs;
kind = ExpressionKind.PipeBindingVariadic;
[ConsumesVarsTrait] = true;
[UsesVarOffset] = true;
varOffset = null;
constructor(target, targetSlot, name, args, numArgs) {
super();
this.target = target;
this.targetSlot = targetSlot;
this.name = name;
this.args = args;
this.numArgs = numArgs;
}
visitExpression(visitor, context) {
this.args.visitExpression(visitor, context);
}
isEquivalent() {
return false;
}
isConstant() {
return false;
}
transformInternalExpressions(transform, flags) {
this.args = transformExpressionsInExpression(this.args, transform, flags);
}
clone() {
const r = new PipeBindingVariadicExpr(this.target, this.targetSlot, this.name, this.args.clone(), this.numArgs);
r.varOffset = this.varOffset;
return r;
}
}
class SafePropertyReadExpr extends ExpressionBase {
receiver;
name;
kind = ExpressionKind.SafePropertyRead;
constructor(receiver, name) {
super();
this.receiver = receiver;
this.name = name;
}
get index() {
return this.name;
}
visitExpression(visitor, context) {
this.receiver.visitExpression(visitor, context);
}
isEquivalent() {
return false;
}
isConstant() {
return false;
}
transformInternalExpressions(transform, flags) {
this.receiver = transformExpressionsInExpression(this.receiver, transform, flags);
}
clone() {
return new SafePropertyReadExpr(this.receiver.clone(), this.name);
}
}
class SafeKeyedReadExpr extends ExpressionBase {
receiver;
index;
kind = ExpressionKind.SafeKeyedRead;
constructor(receiver, index, sourceSpan) {
super(sourceSpan);
this.receiver = receiver;
this.index = index;
}
visitExpression(visitor, context) {
this.receiver.visitExpression(visitor, context);
this.index.visitExpression(visitor, context);
}
isEquivalent() {
return false;
}
isConstant() {
return false;
}
transformInternalExpressions(transform, flags) {
this.receiver = transformExpressionsInExpression(this.receiver, transform, flags);
this.index = transformExpressionsInExpression(this.index, transform, flags);
}
clone() {
return new SafeKeyedReadExpr(this.receiver.clone(), this.index.clone(), this.sourceSpan);
}
}
class SafeInvokeFunctionExpr extends ExpressionBase {
receiver;
args;
kind = ExpressionKind.SafeInvokeFunction;
constructor(receiver, args) {
super();
this.receiver = receiver;
this.args = args;
}
visitExpression(visitor, context) {
this.receiver.visitExpression(visitor, context);
for (const a of this.args) {
a.visitExpression(visitor, context);
}
}
isEquivalent() {
return false;
}
isConstant() {
return false;
}
transformInternalExpressions(transform, flags) {
this.receiver = transformExpressionsInExpression(this.receiver, transform, flags);
for (let i = 0; i < this.args.length; i++) {
this.args[i] = transformExpressionsInExpression(this.args[i], transform, flags);
}
}
clone() {
return new SafeInvokeFunctionExpr(this.receiver.clone(), this.args.map(a => a.clone()));
}
}
class SafeTernaryExpr extends ExpressionBase {
guard;
expr;
kind = ExpressionKind.SafeTernaryExpr;
constructor(guard, expr) {
super();
this.guard = guard;
this.expr = expr;
}
visitExpression(visitor, context) {
this.guard.visitExpression(visitor, context);
this.expr.visitExpression(visitor, context);
}
isEquivalent() {
return false;
}
isConstant() {
return false;
}
transformInternalExpressions(transform, flags) {
this.guard = transformExpressionsInExpression(this.guard, transform, flags);
this.expr = transformExpressionsInExpression(this.expr, transform, flags);
}
clone() {
return new SafeTernaryExpr(this.guard.clone(), this.expr.clone());
}
}
class EmptyExpr extends ExpressionBase {
kind = ExpressionKind.EmptyExpr;
visitExpression(visitor, context) {}
isEquivalent(e) {
return e instanceof EmptyExpr;
}
isConstant() {
return true;
}
clone() {
return new EmptyExpr();
}
transformInternalExpressions() {}
}
class AssignTemporaryExpr extends ExpressionBase {
expr;
xref;
kind = ExpressionKind.AssignTemporaryExpr;
name = null;
constructor(expr, xref) {
super();
this.expr = expr;
this.xref = xref;
}
visitExpression(visitor, context) {
this.expr.visitExpression(visitor, context);
}
isEquivalent() {
return false;
}
isConstant() {
return false;
}
transformInternalExpressions(transform, flags) {
this.expr = transformExpressionsInExpression(this.expr, transform, flags);
}
clone() {
const a = new AssignTemporaryExpr(this.expr.clone(), this.xref);
a.name = this.name;
return a;
}
}
class ReadTemporaryExpr extends ExpressionBase {
xref;
kind = ExpressionKind.ReadTemporaryExpr;
name = null;
constructor(xref) {
super();
this.xref = xref;
}
visitExpression(visitor, context) {}
isEquivalent() {
return this.xref === this.xref;
}
isConstant() {
return false;
}
transformInternalExpressions(transform, flags) {}
clone() {
const r = new ReadTemporaryExpr(this.xref);
r.name = this.name;
return r;
}
}
class SlotLiteralExpr extends ExpressionBase {
slot;
kind = ExpressionKind.SlotLiteralExpr;
constructor(slot) {
super();
this.slot = slot;
}
visitExpression(visitor, context) {}
isEquivalent(e) {
return e instanceof SlotLiteralExpr && e.slot === this.slot;
}
isConstant() {
return true;
}
clone() {
return new SlotLiteralExpr(this.slot);
}
transformInternalExpressions() {}
}
class ConditionalCaseExpr extends ExpressionBase {
expr;
target;
targetSlot;
alias;
kind = ExpressionKind.ConditionalCase;
constructor(expr, target, targetSlot, alias = null) {
super();
this.expr = expr;
this.target = target;
this.targetSlot = targetSlot;
this.alias = alias;
}
visitExpression(visitor, context) {
if (this.expr !== null) {
this.expr.visitExpression(visitor, context);
}
}
isEquivalent(e) {
return e instanceof ConditionalCaseExpr && e.expr === this.expr;
}
isConstant() {
return true;
}
clone() {
return new ConditionalCaseExpr(this.expr, this.target, this.targetSlot);
}
transformInternalExpressions(transform, flags) {
if (this.expr !== null) {
this.expr = transformExpressionsInExpression(this.expr, transform, flags);
}
}
}
class ConstCollectedExpr extends ExpressionBase {
expr;
kind = ExpressionKind.ConstCollected;
constructor(expr) {
super();
this.expr = expr;
}
transformInternalExpressions(transform, flags) {
this.expr = transform(this.expr, flags);
}
visitExpression(visitor, context) {
this.expr.visitExpression(visitor, context);
}
isEquivalent(e) {
if (!(e instanceof ConstCollectedExpr)) {
return false;
}
return this.expr.isEquivalent(e.expr);
}
isConstant() {
return this.expr.isConstant();
}
clone() {
return new ConstCollectedExpr(this.expr);
}
}
function visitExpressionsInOp(op, visitor) {
transformExpressionsInOp(op, (expr, flags) => {
visitor(expr, flags);
return expr;
}, VisitorContextFlag.None);
}
var VisitorContextFlag;
(function (VisitorContextFlag) {
VisitorContextFlag[VisitorContextFlag["None"] = 0] = "None";
VisitorContextFlag[VisitorContextFlag["InChildOperation"] = 1] = "InChildOperation";
})(VisitorContextFlag || (VisitorContextFlag = {}));
function transformExpressionsInInterpolation(interpolation, transform, flags) {
for (let i = 0; i < interpolation.expressions.length; i++) {
interpolation.expressions[i] = transformExpressionsInExpression(interpolation.expressions[i], transform, flags);
}
}
function transformExpressionsInOp(op, transform, flags) {
switch (op.kind) {
case OpKind.StyleProp:
case OpKind.StyleMap:
case OpKind.ClassProp:
case OpKind.ClassMap:
case OpKind.AnimationString:
case OpKind.AnimationBinding:
case OpKind.Binding:
if (op.expression instanceof Interpolation) {
transformExpressionsInInterpolation(op.expression, transform, flags);
} else {
op.expression = transformExpressionsInExpression(op.expression, transform, flags);
}
break;
case OpKind.Property:
case OpKind.DomProperty:
case OpKind.Attribute:
case OpKind.Control:
if (op.expression instanceof Interpolation) {
transformExpressionsInInterpolation(op.expression, transform, flags);
} else {
op.expression = transformExpressionsInExpression(op.expression, transform, flags);
}
op.sanitizer = op.sanitizer && transformExpressionsInExpression(op.sanitizer, transform, flags);
break;
case OpKind.TwoWayProperty:
op.expression = transformExpressionsInExpression(op.expression, transform, flags);
op.sanitizer = op.sanitizer && transformExpressionsInExpression(op.sanitizer, transform, flags);
break;
case OpKind.I18nExpression:
op.expression = transformExpressionsInExpression(op.expression, transform, flags);
break;
case OpKind.InterpolateText:
transformExpressionsInInterpolation(op.interpolation, transform, flags);
break;
case OpKind.Statement:
transformExpressionsInStatement(op.statement, transform, flags);
break;
case OpKind.Variable:
op.initializer = transformExpressionsInExpression(op.initializer, transform, flags);
break;
case OpKind.Conditional:
for (const condition of op.conditions) {
if (condition.expr === null) {
continue;
}
condition.expr = transformExpressionsInExpression(condition.expr, transform, flags);
}
if (op.processed !== null) {
op.processed = transformExpressionsInExpression(op.processed, transform, flags);
}
if (op.contextValue !== null) {
op.contextValue = transformExpressionsInExpression(op.contextValue, transform, flags);
}
break;
case OpKind.Animation:
case OpKind.AnimationListener:
case OpKind.Listener:
case OpKind.TwoWayListener:
for (const innerOp of op.handlerOps) {
transformExpressionsInOp(innerOp, transform, flags | VisitorContextFlag.InChildOperation);
}
break;
case OpKind.ExtractedAttribute:
op.expression = op.expression && transformExpressionsInExpression(op.expression, transform, flags);
op.trustedValueFn = op.trustedValueFn && transformExpressionsInExpression(op.trustedValueFn, transform, flags);
break;
case OpKind.RepeaterCreate:
if (op.trackByOps === null) {
op.track = transformExpressionsInExpression(op.track, transform, flags);
} else {
for (const innerOp of op.trackByOps) {
transformExpressionsInOp(innerOp, transform, flags | VisitorContextFlag.InChildOperation);
}
}
if (op.trackByFn !== null) {
op.trackByFn = transformExpressionsInExpression(op.trackByFn, transform, flags);
}
break;
case OpKind.Repeater:
op.collection = transformExpressionsInExpression(op.collection, transform, flags);
break;
case OpKind.Defer:
if (op.loadingConfig !== null) {
op.loadingConfig = transformExpressionsInExpression(op.loadingConfig, transform, flags);
}
if (op.placeholderConfig !== null) {
op.placeholderConfig = transformExpressionsInExpression(op.placeholderConfig, transform, flags);
}
if (op.resolverFn !== null) {
op.resolverFn = transformExpressionsInExpression(op.resolverFn, transform, flags);
}
break;
case OpKind.I18nMessage:
for (const [placeholder, expr] of op.params) {
op.params.set(placeholder, transformExpressionsInExpression(expr, transform, flags));
}
for (const [placeholder, expr] of op.postprocessingParams) {
op.postprocessingParams.set(placeholder, transformExpressionsInExpression(expr, transform, flags));
}
break;
case OpKind.DeferWhen:
op.expr = transformExpressionsInExpression(op.expr, transform, flags);
break;
case OpKind.StoreLet:
op.value = transformExpressionsInExpression(op.value, transform, flags);
break;
case OpKind.Advance:
case OpKind.Container:
case OpKind.ContainerEnd:
case OpKind.ContainerStart:
case OpKind.DeferOn:
case OpKind.DisableBindings:
case OpKind.Element:
case OpKind.ElementEnd:
case OpKind.ElementStart:
case OpKind.EnableBindings:
case OpKind.I18n:
case OpKind.I18nApply:
case OpKind.I18nContext:
case OpKind.I18nEnd:
case OpKind.I18nStart:
case OpKind.IcuEnd:
case OpKind.IcuStart:
case OpKind.Namespace:
case OpKind.Pipe:
case OpKind.Projection:
case OpKind.ProjectionDef:
case OpKind.Template:
case OpKind.Text:
case OpKind.I18nAttributes:
case OpKind.IcuPlaceholder:
case OpKind.DeclareLet:
case OpKind.SourceLocation:
case OpKind.ConditionalCreate:
case OpKind.ConditionalBranchCreate:
case OpKind.ControlCreate:
break;
default:
throw new Error(`AssertionError: transformExpressionsInOp doesn't handle ${OpKind[op.kind]}`);
}
}
function transformExpressionsInExpression(expr, transform, flags) {
if (expr instanceof ExpressionBase) {
expr.transformInternalExpressions(transform, flags);
} else if (expr instanceof BinaryOperatorExpr) {
expr.lhs = transformExpressionsInExpression(expr.lhs, transform, flags);
expr.rhs = transformExpressionsInExpression(expr.rhs, transform, flags);
} else if (expr instanceof UnaryOperatorExpr) {
expr.expr = transformExpressionsInExpression(expr.expr, transform, flags);
} else if (expr instanceof ReadPropExpr) {
expr.receiver = transformExpressionsInExpression(expr.receiver, transform, flags);
} else if (expr instanceof ReadKeyExpr) {
expr.receiver = transformExpressionsInExpression(expr.receiver, transform, flags);
expr.index = transformExpressionsInExpression(expr.index, transform, flags);
} else if (expr instanceof InvokeFunctionExpr) {
expr.fn = transformExpressionsInExpression(expr.fn, transform, flags);
for (let i = 0; i < expr.args.length; i++) {
expr.args[i] = transformExpressionsInExpression(expr.args[i], transform, flags);
}
} else if (expr instanceof LiteralArrayExpr) {
for (let i = 0; i < expr.entries.length; i++) {
expr.entries[i] = transformExpressionsInExpression(expr.entries[i], transform, flags);
}
} else if (expr instanceof LiteralMapExpr) {
for (const entry of expr.entries) {
if (entry instanceof LiteralMapSpreadAssignment) {
entry.expression = transformExpressionsInExpression(entry.expression, transform, flags);
} else {
entry.value = transformExpressionsInExpression(entry.value, transform, flags);
}
}
} else if (expr instanceof ConditionalExpr) {
expr.condition = transformExpressionsInExpression(expr.condition, transform, flags);
expr.trueCase = transformExpressionsInExpression(expr.trueCase, transform, flags);
if (expr.falseCase !== null) {
expr.falseCase = transformExpressionsInExpression(expr.falseCase, transform, flags);
}
} else if (expr instanceof TypeofExpr) {
expr.expr = transformExpressionsInExpression(expr.expr, transform, flags);
} else if (expr instanceof VoidExpr) {
expr.expr = transformExpressionsInExpression(expr.expr, transform, flags);
} else if (expr instanceof LocalizedString) {
for (let i = 0; i < expr.expressions.length; i++) {
expr.expressions[i] = transformExpressionsInExpression(expr.expressions[i], transform, flags);
}
} else if (expr instanceof NotExpr) {
expr.condition = transformExpressionsInExpression(expr.condition, transform, flags);
} else if (expr instanceof TaggedTemplateLiteralExpr) {
expr.tag = transformExpressionsInExpression(expr.tag, transform, flags);
expr.template.expressions = expr.template.expressions.map(e => transformExpressionsInExpression(e, transform, flags));
} else if (expr instanceof ArrowFunctionExpr) {
if (Array.isArray(expr.body)) {
for (let i = 0; i < expr.body.length; i++) {
transformExpressionsInStatement(expr.body[i], transform, flags);
}
} else {
expr.body = transformExpressionsInExpression(expr.body, transform, flags);
}
} else if (expr instanceof WrappedNodeExpr) ; else if (expr instanceof TemplateLiteralExpr) {
for (let i = 0; i < expr.expressions.length; i++) {
expr.expressions[i] = transformExpressionsInExpression(expr.expressions[i], transform, flags);
}
} else if (expr instanceof ParenthesizedExpr) {
expr.expr = transformExpressionsInExpression(expr.expr, transform, flags);
} else if (expr instanceof SpreadElementExpr) {
expr.expression = transformExpressionsInExpression(expr.expression, transform, flags);
} else if (expr instanceof ReadVarExpr || expr instanceof ExternalExpr || expr instanceof LiteralExpr || expr instanceof RegularExpressionLiteralExpr) ; else {
throw new Error(`Unhandled expression kind: ${expr.constructor.name}`);
}
return transform(expr, flags);
}
function transformExpressionsInStatement(stmt, transform, flags) {
if (stmt instanceof ExpressionStatement) {
stmt.expr = transformExpressionsInExpression(stmt.expr, transform, flags);
} else if (stmt instanceof ReturnStatement) {
stmt.value = transformExpressionsInExpression(stmt.value, transform, flags);
} else if (stmt instanceof DeclareVarStmt) {
if (stmt.value !== undefined) {
stmt.value = transformExpressionsInExpression(stmt.value, transform, flags);
}
} else if (stmt instanceof IfStmt) {
stmt.condition = transformExpressionsInExpression(stmt.condition, transform, flags);
for (const caseStatement of stmt.trueCase) {
transformExpressionsInStatement(caseStatement, transform, flags);
}
for (const caseStatement of stmt.falseCase) {
transformExpressionsInStatement(caseStatement, transform, flags);
}
} else {
throw new Error(`Unhandled statement kind: ${stmt.constructor.name}`);
}
}
function isStringLiteral(expr) {
return expr instanceof LiteralExpr && typeof expr.value === 'string';
}
class OpList {
static nextListId = 0;
debugListId = OpList.nextListId++;
head = {
kind: OpKind.ListEnd,
next: null,
prev: null,
debugListId: this.debugListId
};
tail = {
kind: OpKind.ListEnd,
next: null,
prev: null,
debugListId: this.debugListId
};
constructor() {
this.head.next = this.tail;
this.tail.prev = this.head;
}
push(op) {
if (Array.isArray(op)) {
for (const o of op) {
this.push(o);
}
return;
}
OpList.assertIsNotEnd(op);
OpList.assertIsUnowned(op);
op.debugListId = this.debugListId;
const oldLast = this.tail.prev;
op.prev = oldLast;
oldLast.next = op;
op.next = this.tail;
this.tail.prev = op;
}
prepend(ops) {
if (ops.length === 0) {
return;
}
for (const op of ops) {
OpList.assertIsNotEnd(op);
OpList.assertIsUnowned(op);
op.debugListId = this.debugListId;
}
const first = this.head.next;
let prev = this.head;
for (const op of ops) {
prev.next = op;
op.prev = prev;
prev = op;
}
prev.next = first;
first.prev = prev;
}
*[Symbol.iterator]() {
let current = this.head.next;
while (current !== this.tail) {
OpList.assertIsOwned(current, this.debugListId);
const next = current.next;
yield current;
current = next;
}
}
*reversed() {
let current = this.tail.prev;
while (current !== this.head) {
OpList.assertIsOwned(current, this.debugListId);
const prev = current.prev;
yield current;
current = prev;
}
}
static replace(oldOp, newOp) {
OpList.assertIsNotEnd(oldOp);
OpList.assertIsNotEnd(newOp);
OpList.assertIsOwned(oldOp);
OpList.assertIsUnowned(newOp);
newOp.debugListId = oldOp.debugListId;
if (oldOp.prev !== null) {
oldOp.prev.next = newOp;
newOp.prev = oldOp.prev;
}
if (oldOp.next !== null) {
oldOp.next.prev = newOp;
newOp.next = oldOp.next;
}
oldOp.debugListId = null;
oldOp.prev = null;
oldOp.next = null;
}
static replaceWithMany(oldOp, newOps) {
if (newOps.length === 0) {
OpList.remove(oldOp);
return;
}
OpList.assertIsNotEnd(oldOp);
OpList.assertIsOwned(oldOp);
const listId = oldOp.debugListId;
oldOp.debugListId = null;
for (const newOp of newOps) {
OpList.assertIsNotEnd(newOp);
OpList.assertIsUnowned(newOp);
}
const {
prev: oldPrev,
next: oldNext
} = oldOp;
oldOp.prev = null;
oldOp.next = null;
let prev = oldPrev;
for (const newOp of newOps) {
OpList.assertIsUnowned(newOp);
newOp.debugListId = listId;
prev.next = newOp;
newOp.prev = prev;
newOp.next = null;
prev = newOp;
}
const first = newOps[0];
const last = prev;
if (oldPrev !== null) {
oldPrev.next = first;
first.prev = oldPrev;
}
if (oldNext !== null) {
oldNext.prev = last;
last.next = oldNext;
}
}
static remove(op) {
OpList.assertIsNotEnd(op);
OpList.assertIsOwned(op);
op.prev.next = op.next;
op.next.prev = op.prev;
op.debugListId = null;
op.prev = null;
op.next = null;
}
static insertBefore(op, target) {
if (Array.isArray(op)) {
for (const o of op) {
OpList.insertBefore(o, target);
}
return;
}
OpList.assertIsOwned(target);
if (target.prev === null) {
throw new Error(`AssertionError: illegal operation on list start`);
}
OpList.assertIsNotEnd(op);
OpList.assertIsUnowned(op);
op.debugListId = target.debugListId;
op.prev = null;
target.prev.next = op;
op.prev = target.prev;
op.next = target;
target.prev = op;
}
static insertAfter(op, target) {
OpList.assertIsOwned(target);
if (target.next === null) {
throw new Error(`AssertionError: illegal operation on list end`);
}
OpList.assertIsNotEnd(op);
OpList.assertIsUnowned(op);
op.debugListId = target.debugListId;
target.next.prev = op;
op.next = target.next;
op.prev = target;
target.next = op;
}
static assertIsUnowned(op) {
if (op.debugListId !== null) {
throw new Error(`AssertionError: illegal operation on owned node: ${OpKind[op.kind]}`);
}
}
static assertIsOwned(op, byList) {
if (op.debugListId === null) {
throw new Error(`AssertionError: illegal operation on unowned node: ${OpKind[op.kind]}`);
} else if (byList !== undefined && op.debugListId !== byList) {
throw new Error(`AssertionError: node belongs to the wrong list (expected ${byList}, actual ${op.debugListId})`);
}
}
static assertIsNotEnd(op) {
if (op.kind === OpKind.ListEnd) {
throw new Error(`AssertionError: illegal operation on list head or tail`);
}
}
}
class SlotHandle {
slot = null;
}
const elementContainerOpKinds = new Set([OpKind.Element, OpKind.ElementStart, OpKind.Container, OpKind.ContainerStart, OpKind.Template, OpKind.RepeaterCreate, OpKind.ConditionalCreate, OpKind.ConditionalBranchCreate]);
function isElementOrContainerOp(op) {
return elementContainerOpKinds.has(op.kind);
}
function createElementStartOp(tag, xref, namespace, i18nPlaceholder, startSourceSpan, wholeSourceSpan) {
return {
kind: OpKind.ElementStart,
xref,
tag,
handle: new SlotHandle(),
attributes: null,
localRefs: [],
nonBindable: false,
namespace,
i18nPlaceholder,
startSourceSpan,
wholeSourceSpan,
...TRAIT_CONSUMES_SLOT,
...NEW_OP
};
}
function createTemplateOp(xref, templateKind, tag, functionNameSuffix, namespace, i18nPlaceholder, startSourceSpan, wholeSourceSpan) {
return {
kind: OpKind.Template,
xref,
templateKind,
attributes: null,
tag,
handle: new SlotHandle(),
functionNameSuffix,
decls: null,
vars: null,
localRefs: [],
nonBindable: false,
namespace,
i18nPlaceholder,
startSourceSpan,
wholeSourceSpan,
...TRAIT_CONSUMES_SLOT,
...NEW_OP
};
}
function createConditionalCreateOp(xref, templateKind, tag, functionNameSuffix, namespace, i18nPlaceholder, startSourceSpan, wholeSourceSpan) {
return {
kind: OpKind.ConditionalCreate,
xref,
templateKind,
attributes: null,
tag,
handle: new SlotHandle(),
functionNameSuffix,
decls: null,
vars: null,
localRefs: [],
nonBindable: false,
namespace,
i18nPlaceholder,
startSourceSpan,
wholeSourceSpan,
...TRAIT_CONSUMES_SLOT,
...NEW_OP
};
}
function createConditionalBranchCreateOp(xref, templateKind, tag, functionNameSuffix, namespace, i18nPlaceholder, startSourceSpan, wholeSourceSpan) {
return {
kind: OpKind.ConditionalBranchCreate,
xref,
templateKind,
attributes: null,
tag,
handle: new SlotHandle(),
functionNameSuffix,
decls: null,
vars: null,
localRefs: [],
nonBindable: false,
namespace,
i18nPlaceholder,
startSourceSpan,
wholeSourceSpan,
...TRAIT_CONSUMES_SLOT,
...NEW_OP
};
}
function createRepeaterCreateOp(primaryView, emptyView, tag, track, varNames, emptyTag, i18nPlaceholder, emptyI18nPlaceholder, startSourceSpan, wholeSourceSpan) {
return {
kind: OpKind.RepeaterCreate,
attributes: null,
xref: primaryView,
handle: new SlotHandle(),
emptyView,
track,
trackByFn: null,
trackByOps: null,
tag,
emptyTag,
emptyAttributes: null,
functionNameSuffix: 'For',
namespace: Namespace.HTML,
nonBindable: false,
localRefs: [],
decls: null,
vars: null,
varNames,
usesComponentInstance: false,
i18nPlaceholder,
emptyI18nPlaceholder,
startSourceSpan,
wholeSourceSpan,
...TRAIT_CONSUMES_SLOT,
...NEW_OP,
...TRAIT_CONSUMES_VARS,
numSlotsUsed: emptyView === null ? 2 : 3
};
}
function createElementEndOp(xref, sourceSpan) {
return {
kind: OpKind.ElementEnd,
xref,
sourceSpan,
...NEW_OP
};
}
function createDisableBindingsOp(xref) {
return {
kind: OpKind.DisableBindings,
xref,
...NEW_OP
};
}
function createEnableBindingsOp(xref) {
return {
kind: OpKind.EnableBindings,
xref,
...NEW_OP
};
}
function createTextOp(xref, initialValue, icuPlaceholder, sourceSpan) {
return {
kind: OpKind.Text,
xref,
handle: new SlotHandle(),
initialValue,
icuPlaceholder,
sourceSpan,
...TRAIT_CONSUMES_SLOT,
...NEW_OP
};
}
function createAnimationStringOp(name, target, animationKind, expression, securityContext, sourceSpan) {
return {
kind: OpKind.AnimationString,
name,
target,
animationKind,
expression,
i18nMessage: null,
securityContext,
sanitizer: null,
sourceSpan,
...NEW_OP
};
}
function createAnimationOp(name, target, animationKind, callbackOps, securityContext, sourceSpan) {
const handlerOps = new OpList();
handlerOps.push(callbackOps);
return {
kind: OpKind.Animation,
name,
target,
animationKind,
handlerOps,
handlerFnName: null,
i18nMessage: null,
securityContext,
sanitizer: null,
sourceSpan,
...NEW_OP
};
}
function createListenerOp(target, targetSlot, name, tag, handlerOps, legacyAnimationPhase, eventTarget, hostListener, sourceSpan) {
const handlerList = new OpList();
handlerList.push(handlerOps);
return {
kind: OpKind.Listener,
target,
targetSlot,
tag,
hostListener,
name,
handlerOps: handlerList,
handlerFnName: null,
consumesDollarEvent: false,
isLegacyAnimationListener: legacyAnimationPhase !== null,
legacyAnimationPhase: legacyAnimationPhase,
eventTarget,
sourceSpan,
...NEW_OP
};
}
function createAnimationListenerOp(target, targetSlot, name, tag, handlerOps, animationKind, eventTarget, hostListener, sourceSpan) {
const handlerList = new OpList();
handlerList.push(handlerOps);
return {
kind: OpKind.AnimationListener,
target,
targetSlot,
tag,
hostListener,
name,
animationKind,
handlerOps: handlerList,
handlerFnName: null,
consumesDollarEvent: false,
eventTarget,
sourceSpan,
...NEW_OP
};
}
function createTwoWayListenerOp(target, targetSlot, name, tag, handlerOps, sourceSpan) {
const handlerList = new OpList();
handlerList.push(handlerOps);
return {
kind: OpKind.TwoWayListener,
target,
targetSlot,
tag,
name,
handlerOps: handlerList,
handlerFnName: null,
sourceSpan,
...NEW_OP
};
}
function createPipeOp(xref, slot, name) {
return {
kind: OpKind.Pipe,
xref,
handle: slot,
name,
...NEW_OP,
...TRAIT_CONSUMES_SLOT
};
}
function createNamespaceOp(namespace) {
return {
kind: OpKind.Namespace,
active: namespace,
...NEW_OP
};
}
function createProjectionDefOp(def) {
return {
kind: OpKind.ProjectionDef,
def,
...NEW_OP
};
}
function createProjectionOp(xref, selector, i18nPlaceholder, fallbackView, sourceSpan) {
return {
kind: OpKind.Projection,
xref,
handle: new SlotHandle(),
selector,
i18nPlaceholder,
fallbackView,
projectionSlotIndex: 0,
attributes: null,
localRefs: [],
sourceSpan,
...NEW_OP,
...TRAIT_CONSUMES_SLOT,
numSlotsUsed: fallbackView === null ? 1 : 2
};
}
function createExtractedAttributeOp(target, bindingKind, namespace, name, expression, i18nContext, i18nMessage, securityContext) {
return {
kind: OpKind.ExtractedAttribute,
target,
bindingKind,
namespace,
name,
expression,
i18nContext,
i18nMessage,
securityContext,
trustedValueFn: null,
...NEW_OP
};
}
function createDeferOp(xref, main, mainSlot, ownResolverFn, resolverFn, sourceSpan) {
return {
kind: OpKind.Defer,
xref,
handle: new SlotHandle(),
mainView: main,
mainSlot,
loadingView: null,
loadingSlot: null,
loadingConfig: null,
loadingMinimumTime: null,
loadingAfterTime: null,
placeholderView: null,
placeholderSlot: null,
placeholderConfig: null,
placeholderMinimumTime: null,
errorView: null,
errorSlot: null,
ownResolverFn,
resolverFn,
flags: null,
sourceSpan,
...NEW_OP,
...TRAIT_CONSUMES_SLOT,
numSlotsUsed: 2
};
}
function createDeferOnOp(defer, trigger, modifier, sourceSpan) {
return {
kind: OpKind.DeferOn,
defer,
trigger,
modifier,
sourceSpan,
...NEW_OP
};
}
function createDeclareLetOp(xref, declaredName, sourceSpan) {
return {
kind: OpKind.DeclareLet,
xref,
declaredName,
sourceSpan,
handle: new SlotHandle(),
...TRAIT_CONSUMES_SLOT,
...NEW_OP
};
}
function createI18nMessageOp(xref, i18nContext, i18nBlock, message, messagePlaceholder, params, postprocessingParams, needsPostprocessing) {
return {
kind: OpKind.I18nMessage,
xref,
i18nContext,
i18nBlock,
message,
messagePlaceholder,
params,
postprocessingParams,
needsPostprocessing,
subMessages: [],
...NEW_OP
};
}
function createI18nStartOp(xref, message, root, sourceSpan) {
return {
kind: OpKind.I18nStart,
xref,
handle: new SlotHandle(),
root: root ?? xref,
message,
messageIndex: null,
subTemplateIndex: null,
context: null,
sourceSpan,
...NEW_OP,
...TRAIT_CONSUMES_SLOT
};
}
function createI18nEndOp(xref, sourceSpan) {
return {
kind: OpKind.I18nEnd,
xref,
sourceSpan,
...NEW_OP
};
}
function createIcuStartOp(xref, message, messagePlaceholder, sourceSpan) {
return {
kind: OpKind.IcuStart,
xref,
message,
messagePlaceholder,
context: null,
sourceSpan,
...NEW_OP
};
}
function createIcuEndOp(xref) {
return {
kind: OpKind.IcuEnd,
xref,
...NEW_OP
};
}
function createIcuPlaceholderOp(xref, name, strings) {
return {
kind: OpKind.IcuPlaceholder,
xref,
name,
strings,
expressionPlaceholders: [],
...NEW_OP
};
}
function createI18nContextOp(contextKind, xref, i18nBlock, message, sourceSpan) {
if (i18nBlock === null && contextKind !== I18nContextKind.Attr) {
throw new Error('AssertionError: i18nBlock must be provided for non-attribute contexts.');
}
return {
kind: OpKind.I18nContext,
contextKind,
xref,
i18nBlock,
message,
sourceSpan,
params: new Map(),
postprocessingParams: new Map(),
...NEW_OP
};
}
function createI18nAttributesOp(xref, handle, target) {
return {
kind: OpKind.I18nAttributes,
xref,
handle,
target,
i18nAttributesConfig: null,
...NEW_OP,
...TRAIT_CONSUMES_SLOT
};
}
function createSourceLocationOp(templatePath, locations) {
return {
kind: OpKind.SourceLocation,
templatePath,
locations,
...NEW_OP
};
}
function createControlCreateOp(sourceSpan) {
return {
kind: OpKind.ControlCreate,
sourceSpan,
...NEW_OP
};
}
function createDomPropertyOp(name, expression, bindingKind, i18nContext, securityContext, sourceSpan) {
return {
kind: OpKind.DomProperty,
name,
expression,
bindingKind,
i18nContext,
securityContext,
sanitizer: null,
sourceSpan,
...TRAIT_CONSUMES_VARS,
...NEW_OP
};
}
const CTX_REF = 'CTX_REF_MARKER';
var CompilationJobKind;
(function (CompilationJobKind) {
CompilationJobKind[CompilationJobKind["Tmpl"] = 0] = "Tmpl";
CompilationJobKind[CompilationJobKind["Host"] = 1] = "Host";
CompilationJobKind[CompilationJobKind["Both"] = 2] = "Both";
})(CompilationJobKind || (CompilationJobKind = {}));
var TemplateCompilationMode;
(function (TemplateCompilationMode) {
TemplateCompilationMode[TemplateCompilationMode["Full"] = 0] = "Full";
TemplateCompilationMode[TemplateCompilationMode["DomOnly"] = 1] = "DomOnly";
})(TemplateCompilationMode || (TemplateCompilationMode = {}));
class CompilationJob {
componentName;
pool;
compatibility;
mode;
constructor(componentName, pool, compatibility, mode) {
this.componentName = componentName;
this.pool = pool;
this.compatibility = compatibility;
this.mode = mode;
}
kind = CompilationJobKind.Both;
allocateXrefId() {
return this.nextXrefId++;
}
nextXrefId = 0;
}
class ComponentCompilationJob extends CompilationJob {
relativeContextFilePath;
i18nUseExternalIds;
deferMeta;
allDeferrableDepsFn;
relativeTemplatePath;
enableDebugLocations;
constructor(componentName, pool, compatibility, mode, relativeContextFilePath, i18nUseExternalIds, deferMeta, allDeferrableDepsFn, relativeTemplatePath, enableDebugLocations) {
super(componentName, pool, compatibility, mode);
this.relativeContextFilePath = relativeContextFilePath;
this.i18nUseExternalIds = i18nUseExternalIds;
this.deferMeta = deferMeta;
this.allDeferrableDepsFn = allDeferrableDepsFn;
this.relativeTemplatePath = relativeTemplatePath;
this.enableDebugLocations = enableDebugLocations;
this.root = new ViewCompilationUnit(this, this.allocateXrefId(), null);
this.views.set(this.root.xref, this.root);
}
kind = CompilationJobKind.Tmpl;
fnSuffix = 'Template';
root;
views = new Map();
contentSelectors = null;
allocateView(parent) {
const view = new ViewCompilationUnit(this, this.allocateXrefId(), parent);
this.views.set(view.xref, view);
return view;
}
get units() {
return this.views.values();
}
addConst(newConst, initializers) {
for (let idx = 0; idx < this.consts.length; idx++) {
if (this.consts[idx].isEquivalent(newConst)) {
return idx;
}
}
const idx = this.consts.length;
this.consts.push(newConst);
if (initializers) {
this.constsInitializers.push(...initializers);
}
return idx;
}
consts = [];
constsInitializers = [];
}
class CompilationUnit {
xref;
constructor(xref) {
this.xref = xref;
}
create = new OpList();
update = new OpList();
fnName = null;
vars = null;
*ops() {
for (const op of this.create) {
yield op;
if (op.kind === OpKind.Listener || op.kind === OpKind.Animation || op.kind === OpKind.AnimationListener || op.kind === OpKind.TwoWayListener) {
for (const listenerOp of op.handlerOps) {
yield listenerOp;
}
} else if (op.kind === OpKind.RepeaterCreate && op.trackByOps !== null) {
for (const trackOp of op.trackByOps) {
yield trackOp;
}
}
}
for (const op of this.update) {
yield op;
}
}
}
class ViewCompilationUnit extends CompilationUnit {
job;
parent;
constructor(job, xref, parent) {
super(xref);
this.job = job;
this.parent = parent;
}
contextVariables = new Map();
aliases = new Set();
decls = null;
}
class HostBindingCompilationJob extends CompilationJob {
constructor(componentName, pool, compatibility, mode) {
super(componentName, pool, compatibility, mode);
this.root = new HostBindingCompilationUnit(this);
}
kind = CompilationJobKind.Host;
fnSuffix = 'HostBindings';
root;
get units() {
return [this.root];
}
}
class HostBindingCompilationUnit extends CompilationUnit {
job;
constructor(job) {
super(0);
this.job = job;
}
attributes = null;
}
function deleteAnyCasts(job) {
for (const unit of job.units) {
for (const op of unit.ops()) {
transformExpressionsInOp(op, removeAnys, VisitorContextFlag.None);
}
}
}
function removeAnys(e) {
if (e instanceof InvokeFunctionExpr && e.fn instanceof LexicalReadExpr && e.fn.name === '$any') {
if (e.args.length !== 1) {
throw new Error('The $any builtin function expects exactly one argument.');
}
return e.args[0];
}
return e;
}
function applyI18nExpressions(job) {
const i18nContexts = new Map();
for (const unit of job.units) {
for (const op of unit.create) {
if (op.kind === OpKind.I18nContext) {
i18nContexts.set(op.xref, op);
}
}
}
for (const unit of job.units) {
for (const op of unit.update) {
if (op.kind === OpKind.I18nExpression && needsApplication(i18nContexts, op)) {
OpList.insertAfter(createI18nApplyOp(op.i18nOwner, op.handle, null), op);
}
}
}
}
function needsApplication(i18nContexts, op) {
if (op.next?.kind !== OpKind.I18nExpression) {
return true;
}
const context = i18nContexts.get(op.context);
const nextContext = i18nContexts.get(op.next.context);
if (context === undefined) {
throw new Error("AssertionError: expected an I18nContextOp to exist for the I18nExpressionOp's context");
}
if (nextContext === undefined) {
throw new Error("AssertionError: expected an I18nContextOp to exist for the next I18nExpressionOp's context");
}
if (context.i18nBlock !== null) {
if (context.i18nBlock !== nextContext.i18nBlock) {
return true;
}
return false;
}
if (op.i18nOwner !== op.next.i18nOwner) {
return true;
}
return false;
}
function assignI18nSlotDependencies(job) {
for (const unit of job.units) {
let updateOp = unit.update.head;
let i18nExpressionsInProgress = [];
let state = null;
for (const createOp of unit.create) {
if (createOp.kind === OpKind.I18nStart) {
state = {
blockXref: createOp.xref,
lastSlotConsumer: createOp.xref
};
} else if (createOp.kind === OpKind.I18nEnd) {
for (const op of i18nExpressionsInProgress) {
op.target = state.lastSlotConsumer;
OpList.insertBefore(op, updateOp);
}
i18nExpressionsInProgress.length = 0;
state = null;
}
if (hasConsumesSlotTrait(createOp)) {
if (state !== null) {
state.lastSlotConsumer = createOp.xref;
}
while (true) {
if (updateOp.next === null) {
break;
}
if (state !== null && updateOp.kind === OpKind.I18nExpression && updateOp.usage === I18nExpressionFor.I18nText && updateOp.i18nOwner === state.blockXref) {
const opToRemove = updateOp;
updateOp = updateOp.next;
OpList.remove(opToRemove);
i18nExpressionsInProgress.push(opToRemove);
continue;
}
let hasDifferentTarget = false;
if (hasDependsOnSlotContextTrait(updateOp) && updateOp.target !== createOp.xref) {
hasDifferentTarget = true;
} else if (updateOp.kind === OpKind.Statement || updateOp.kind === OpKind.Variable) {
visitExpressionsInOp(updateOp, expr => {
if (!hasDifferentTarget && hasDependsOnSlotContextTrait(expr) && expr.target !== createOp.xref) {
hasDifferentTarget = true;
}
});
}
if (hasDifferentTarget) {
break;
}
updateOp = updateOp.next;
}
}
}
}
}
function attachSourceLocations(job) {
if (!job.enableDebugLocations || job.relativeTemplatePath === null) {
return;
}
for (const unit of job.units) {
const locations = [];
for (const op of unit.create) {
if (op.kind === OpKind.ElementStart || op.kind === OpKind.Element) {
const start = op.startSourceSpan.start;
locations.push({
targetSlot: op.handle,
offset: start.offset,
line: start.line,
column: start.col
});
}
}
if (locations.length > 0) {
unit.create.push(createSourceLocationOp(job.relativeTemplatePath, locations));
}
}
}
function createOpXrefMap(unit) {
const map = new Map();
for (const op of unit.create) {
if (!hasConsumesSlotTrait(op)) {
continue;
}
map.set(op.xref, op);
if (op.kind === OpKind.RepeaterCreate && op.emptyView !== null) {
map.set(op.emptyView, op);
}
}
return map;
}
function extractAttributes(job) {
for (const unit of job.units) {
const elements = createOpXrefMap(unit);
for (const op of unit.ops()) {
switch (op.kind) {
case OpKind.Attribute:
extractAttributeOp(unit, op, elements);
break;
case OpKind.Property:
if (op.bindingKind !== BindingKind.LegacyAnimation && op.bindingKind !== BindingKind.Animation) {
let bindingKind;
if (op.i18nMessage !== null && op.templateKind === null) {
bindingKind = BindingKind.I18n;
} else if (op.isStructuralTemplateAttribute) {
bindingKind = BindingKind.Template;
} else {
bindingKind = BindingKind.Property;
}
OpList.insertBefore(createExtractedAttributeOp(op.target, bindingKind, null, op.name, null, null, null, op.securityContext), lookupElement$3(elements, op.target));
}
break;
case OpKind.Control:
OpList.insertBefore(createExtractedAttributeOp(op.target, BindingKind.Property, null, op.name, null, null, null, op.securityContext), lookupElement$3(elements, op.target));
break;
case OpKind.TwoWayProperty:
OpList.insertBefore(createExtractedAttributeOp(op.target, BindingKind.TwoWayProperty, null, op.name, null, null, null, op.securityContext), lookupElement$3(elements, op.target));
break;
case OpKind.StyleProp:
case OpKind.ClassProp:
if (unit.job.compatibility === CompatibilityMode.TemplateDefinitionBuilder && op.expression instanceof EmptyExpr) {
OpList.insertBefore(createExtractedAttributeOp(op.target, BindingKind.Property, null, op.name, null, null, null, SecurityContext.STYLE), lookupElement$3(elements, op.target));
}
break;
case OpKind.Listener:
if (!op.isLegacyAnimationListener) {
const extractedAttributeOp = createExtractedAttributeOp(op.target, BindingKind.Property, null, op.name, null, null, null, SecurityContext.NONE);
if (job.kind === CompilationJobKind.Host) {
if (job.compatibility) {
break;
}
unit.create.push(extractedAttributeOp);
} else {
OpList.insertBefore(extractedAttributeOp, lookupElement$3(elements, op.target));
}
}
break;
case OpKind.TwoWayListener:
if (job.kind !== CompilationJobKind.Host) {
const extractedAttributeOp = createExtractedAttributeOp(op.target, BindingKind.Property, null, op.name, null, null, null, SecurityContext.NONE);
OpList.insertBefore(extractedAttributeOp, lookupElement$3(elements, op.target));
}
break;
}
}
}
}
function lookupElement$3(elements, xref) {
const el = elements.get(xref);
if (el === undefined) {
throw new Error('All attributes should have an element-like target.');
}
return el;
}
function extractAttributeOp(unit, op, elements) {
if (op.expression instanceof Interpolation) {
return;
}
let extractable = op.isTextAttribute || op.expression.isConstant();
if (unit.job.compatibility === CompatibilityMode.TemplateDefinitionBuilder) {
extractable &&= op.isTextAttribute;
}
if (extractable) {
const extractedAttributeOp = createExtractedAttributeOp(op.target, op.isStructuralTemplateAttribute ? BindingKind.Template : BindingKind.Attribute, op.namespace, op.name, op.expression, op.i18nContext, op.i18nMessage, op.securityContext);
if (unit.job.kind === CompilationJobKind.Host) {
unit.create.push(extractedAttributeOp);
} else {
const ownerOp = lookupElement$3(elements, op.target);
OpList.insertBefore(extractedAttributeOp, ownerOp);
}
OpList.remove(op);
}
}
const ARIA_PREFIX = 'aria-';
function isAriaAttribute(name) {
return name.startsWith(ARIA_PREFIX) && name.length > ARIA_PREFIX.length;
}
function lookupElement$2(elements, xref) {
const el = elements.get(xref);
if (el === undefined) {
throw new Error('All attributes should have an element-like target.');
}
return el;
}
function specializeBindings(job) {
const elements = new Map();
for (const unit of job.units) {
for (const op of unit.create) {
if (!isElementOrContainerOp(op)) {
continue;
}
elements.set(op.xref, op);
}
}
for (const unit of job.units) {
for (const op of unit.ops()) {
if (op.kind !== OpKind.Binding) {
continue;
}
switch (op.bindingKind) {
case BindingKind.Attribute:
if (op.name === 'ngNonBindable') {
OpList.remove(op);
const target = lookupElement$2(elements, op.target);
target.nonBindable = true;
} else if (op.name.startsWith('animate.')) {
OpList.replace(op, createAnimationBindingOp(op.name, op.target, op.name === 'animate.enter' ? "enter" : "leave", op.expression, op.securityContext, op.sourceSpan, 0));
} else {
const [namespace, name] = splitNsName(op.name);
OpList.replace(op, createAttributeOp(op.target, namespace, name, op.expression, op.securityContext, op.isTextAttribute, op.isStructuralTemplateAttribute, op.templateKind, op.i18nMessage, op.sourceSpan));
}
break;
case BindingKind.Animation:
OpList.replace(op, createAnimationBindingOp(op.name, op.target, op.name === 'animate.enter' ? "enter" : "leave", op.expression, op.securityContext, op.sourceSpan, 1));
break;
case BindingKind.Property:
case BindingKind.LegacyAnimation:
if (job.mode === TemplateCompilationMode.DomOnly && isAriaAttribute(op.name)) {
OpList.replace(op, createAttributeOp(op.target, null, op.name, op.expression, op.securityContext, false, op.isStructuralTemplateAttribute, op.templateKind, op.i18nMessage, op.sourceSpan));
} else if (job.kind === CompilationJobKind.Host) {
OpList.replace(op, createDomPropertyOp(op.name, op.expression, op.bindingKind, op.i18nContext, op.securityContext, op.sourceSpan));
} else if (op.name === 'formField') {
OpList.replace(op, createControlOp(op));
} else {
OpList.replace(op, createPropertyOp(op.target, op.name, op.expression, op.bindingKind, op.securityContext, op.isStructuralTemplateAttribute, op.templateKind, op.i18nContext, op.i18nMessage, op.sourceSpan));
}
break;
case BindingKind.TwoWayProperty:
if (!(op.expression instanceof Expression)) {
throw new Error(`Expected value of two-way property binding "${op.name}" to be an expression`);
}
OpList.replace(op, createTwoWayPropertyOp(op.target, op.name, op.expression, op.securityContext, op.isStructuralTemplateAttribute, op.templateKind, op.i18nContext, op.i18nMessage, op.sourceSpan));
break;
case BindingKind.I18n:
case BindingKind.ClassName:
case BindingKind.StyleProperty:
throw new Error(`Unhandled binding of kind ${BindingKind[op.bindingKind]}`);
}
}
}
}
const CHAIN_COMPATIBILITY = new Map([[Identifiers.ariaProperty, Identifiers.ariaProperty], [Identifiers.attribute, Identifiers.attribute], [Identifiers.classProp, Identifiers.classProp], [Identifiers.element, Identifiers.element], [Identifiers.elementContainer, Identifiers.elementContainer], [Identifiers.elementContainerEnd, Identifiers.elementContainerEnd], [Identifiers.elementContainerStart, Identifiers.elementContainerStart], [Identifiers.elementEnd, Identifiers.elementEnd], [Identifiers.elementStart, Identifiers.elementStart], [Identifiers.domProperty, Identifiers.domProperty], [Identifiers.i18nExp, Identifiers.i18nExp], [Identifiers.listener, Identifiers.listener], [Identifiers.listener, Identifiers.listener], [Identifiers.property, Identifiers.property], [Identifiers.styleProp, Identifiers.styleProp], [Identifiers.syntheticHostListener, Identifiers.syntheticHostListener], [Identifiers.syntheticHostProperty, Identifiers.syntheticHostProperty], [Identifiers.templateCreate, Identifiers.templateCreate], [Identifiers.twoWayProperty, Identifiers.twoWayProperty], [Identifiers.twoWayListener, Identifiers.twoWayListener], [Identifiers.declareLet, Identifiers.declareLet], [Identifiers.conditionalCreate, Identifiers.conditionalBranchCreate], [Identifiers.conditionalBranchCreate, Identifiers.conditionalBranchCreate], [Identifiers.domElement, Identifiers.domElement], [Identifiers.domElementStart, Identifiers.domElementStart], [Identifiers.domElementEnd, Identifiers.domElementEnd], [Identifiers.domElementContainer, Identifiers.domElementContainer], [Identifiers.domElementContainerStart, Identifiers.domElementContainerStart], [Identifiers.domElementContainerEnd, Identifiers.domElementContainerEnd], [Identifiers.domListener, Identifiers.domListener], [Identifiers.domTemplate, Identifiers.domTemplate], [Identifiers.animationEnter, Identifiers.animationEnter], [Identifiers.animationLeave, Identifiers.animationLeave], [Identifiers.animationEnterListener, Identifiers.animationEnterListener], [Identifiers.animationLeaveListener, Identifiers.animationLeaveListener]]);
const MAX_CHAIN_LENGTH = 256;
function chain(job) {
for (const unit of job.units) {
chainOperationsInList(unit.create);
chainOperationsInList(unit.update);
}
}
function chainOperationsInList(opList) {
let chain = null;
for (const op of opList) {
if (op.kind !== OpKind.Statement || !(op.statement instanceof ExpressionStatement)) {
chain = null;
continue;
}
if (!(op.statement.expr instanceof InvokeFunctionExpr) || !(op.statement.expr.fn instanceof ExternalExpr)) {
chain = null;
continue;
}
const instruction = op.statement.expr.fn.value;
if (!CHAIN_COMPATIBILITY.has(instruction)) {
chain = null;
continue;
}
if (chain !== null && CHAIN_COMPATIBILITY.get(chain.instruction) === instruction && chain.length < MAX_CHAIN_LENGTH) {
const expression = chain.expression.callFn(op.statement.expr.args, op.statement.expr.sourceSpan, op.statement.expr.pure);
chain.expression = expression;
chain.op.statement = expression.toStmt();
chain.length++;
OpList.remove(op);
} else {
chain = {
op,
instruction,
expression: op.statement.expr,
length: 1
};
}
}
}
function collapseSingletonInterpolations(job) {
for (const unit of job.units) {
for (const op of unit.update) {
const eligibleOpKind = op.kind === OpKind.Attribute || op.kind === OpKind.StyleProp || op.kind == OpKind.StyleMap || op.kind === OpKind.ClassMap;
if (eligibleOpKind && op.expression instanceof Interpolation && op.expression.strings.length === 2 && op.expression.strings.every(s => s === '')) {
op.expression = op.expression.expressions[0];
}
}
}
}
function generateConditionalExpressions(job) {
for (const unit of job.units) {
for (const op of unit.ops()) {
if (op.kind !== OpKind.Conditional) {
continue;
}
let test;
const defaultCase = op.conditions.findIndex(cond => cond.expr === null);
if (defaultCase >= 0) {
const slot = op.conditions.splice(defaultCase, 1)[0].targetSlot;
test = new SlotLiteralExpr(slot);
} else {
test = literal(-1);
}
let tmp = op.test == null ? null : new AssignTemporaryExpr(op.test, job.allocateXrefId());
let caseExpressionTemporaryXref = null;
for (let i = op.conditions.length - 1; i >= 0; i--) {
let conditionalCase = op.conditions[i];
if (conditionalCase.expr === null) {
continue;
}
if (tmp !== null) {
const useTmp = i === 0 ? tmp : new ReadTemporaryExpr(tmp.xref);
conditionalCase.expr = new BinaryOperatorExpr(BinaryOperator.Identical, useTmp, conditionalCase.expr);
} else if (conditionalCase.alias !== null) {
caseExpressionTemporaryXref ??= job.allocateXrefId();
conditionalCase.expr = new AssignTemporaryExpr(conditionalCase.expr, caseExpressionTemporaryXref);
op.contextValue = new ReadTemporaryExpr(caseExpressionTemporaryXref);
}
test = new ConditionalExpr(conditionalCase.expr, new SlotLiteralExpr(conditionalCase.targetSlot), test);
}
op.processed = test;
op.conditions = [];
}
}
}
const BINARY_OPERATORS = new Map([['&&', BinaryOperator.And], ['>', BinaryOperator.Bigger], ['>=', BinaryOperator.BiggerEquals], ['|', BinaryOperator.BitwiseOr], ['&', BinaryOperator.BitwiseAnd], ['/', BinaryOperator.Divide], ['=', BinaryOperator.Assign], ['==', BinaryOperator.Equals], ['===', BinaryOperator.Identical], ['<', BinaryOperator.Lower], ['<=', BinaryOperator.LowerEquals], ['-', BinaryOperator.Minus], ['%', BinaryOperator.Modulo], ['**', BinaryOperator.Exponentiation], ['*', BinaryOperator.Multiply], ['!=', BinaryOperator.NotEquals], ['!==', BinaryOperator.NotIdentical], ['??', BinaryOperator.NullishCoalesce], ['||', BinaryOperator.Or], ['+', BinaryOperator.Plus], ['in', BinaryOperator.In], ['+=', BinaryOperator.AdditionAssignment], ['-=', BinaryOperator.SubtractionAssignment], ['*=', BinaryOperator.MultiplicationAssignment], ['/=', BinaryOperator.DivisionAssignment], ['%=', BinaryOperator.RemainderAssignment], ['**=', BinaryOperator.ExponentiationAssignment], ['&&=', BinaryOperator.AndAssignment], ['||=', BinaryOperator.OrAssignment], ['??=', BinaryOperator.NullishCoalesceAssignment]]);
function namespaceForKey(namespacePrefixKey) {
const NAMESPACES = new Map([['svg', Namespace.SVG], ['math', Namespace.Math]]);
if (namespacePrefixKey === null) {
return Namespace.HTML;
}
return NAMESPACES.get(namespacePrefixKey) ?? Namespace.HTML;
}
function keyForNamespace(namespace) {
const NAMESPACES = new Map([['svg', Namespace.SVG], ['math', Namespace.Math]]);
for (const [k, n] of NAMESPACES.entries()) {
if (n === namespace) {
return k;
}
}
return null;
}
function prefixWithNamespace(strippedTag, namespace) {
if (namespace === Namespace.HTML) {
return strippedTag;
}
return `:${keyForNamespace(namespace)}:${strippedTag}`;
}
function literalOrArrayLiteral(value) {
if (Array.isArray(value)) {
return literalArr(value.map(literalOrArrayLiteral));
}
return literal(value);
}
function collectElementConsts(job) {
const allElementAttributes = new Map();
for (const unit of job.units) {
for (const op of unit.create) {
if (op.kind === OpKind.ExtractedAttribute) {
const attributes = allElementAttributes.get(op.target) || new ElementAttributes(job.compatibility);
allElementAttributes.set(op.target, attributes);
attributes.add(op.bindingKind, op.name, op.expression, op.namespace, op.trustedValueFn);
OpList.remove(op);
}
}
}
if (job instanceof ComponentCompilationJob) {
for (const unit of job.units) {
for (const op of unit.create) {
if (op.kind == OpKind.Projection) {
const attributes = allElementAttributes.get(op.xref);
if (attributes !== undefined) {
const attrArray = serializeAttributes(attributes);
if (attrArray.entries.length > 0) {
op.attributes = attrArray;
}
}
} else if (isElementOrContainerOp(op)) {
op.attributes = getConstIndex(job, allElementAttributes, op.xref);
if (op.kind === OpKind.RepeaterCreate && op.emptyView !== null) {
op.emptyAttributes = getConstIndex(job, allElementAttributes, op.emptyView);
}
}
}
}
} else if (job instanceof HostBindingCompilationJob) {
for (const [xref, attributes] of allElementAttributes.entries()) {
if (xref !== job.root.xref) {
throw new Error(`An attribute would be const collected into the host binding's template function, but is not associated with the root xref.`);
}
const attrArray = serializeAttributes(attributes);
if (attrArray.entries.length > 0) {
job.root.attributes = attrArray;
}
}
}
}
function getConstIndex(job, allElementAttributes, xref) {
const attributes = allElementAttributes.get(xref);
if (attributes !== undefined) {
const attrArray = serializeAttributes(attributes);
if (attrArray.entries.length > 0) {
return job.addConst(attrArray);
}
}
return null;
}
const FLYWEIGHT_ARRAY = Object.freeze([]);
class ElementAttributes {
compatibility;
known = new Map();
byKind = new Map();
propertyBindings = null;
projectAs = null;
get attributes() {
return this.byKind.get(BindingKind.Attribute) ?? FLYWEIGHT_ARRAY;
}
get classes() {
return this.byKind.get(BindingKind.ClassName) ?? FLYWEIGHT_ARRAY;
}
get styles() {
return this.byKind.get(BindingKind.StyleProperty) ?? FLYWEIGHT_ARRAY;
}
get bindings() {
return this.propertyBindings ?? FLYWEIGHT_ARRAY;
}
get template() {
return this.byKind.get(BindingKind.Template) ?? FLYWEIGHT_ARRAY;
}
get i18n() {
return this.byKind.get(BindingKind.I18n) ?? FLYWEIGHT_ARRAY;
}
constructor(compatibility) {
this.compatibility = compatibility;
}
isKnown(kind, name) {
const nameToValue = this.known.get(kind) ?? new Set();
this.known.set(kind, nameToValue);
if (nameToValue.has(name)) {
return true;
}
nameToValue.add(name);
return false;
}
add(kind, name, value, namespace, trustedValueFn) {
const allowDuplicates = this.compatibility === CompatibilityMode.TemplateDefinitionBuilder && (kind === BindingKind.Attribute || kind === BindingKind.ClassName || kind === BindingKind.StyleProperty);
if (!allowDuplicates && this.isKnown(kind, name)) {
return;
}
if (name === 'ngProjectAs') {
if (value === null || !(value instanceof LiteralExpr) || value.value == null || typeof value.value?.toString() !== 'string') {
throw Error('ngProjectAs must have a string literal value');
}
this.projectAs = value.value.toString();
}
const array = this.arrayFor(kind);
array.push(...getAttributeNameLiterals(namespace, name));
if (kind === BindingKind.Attribute || kind === BindingKind.StyleProperty) {
if (value === null) {
throw Error('Attribute, i18n attribute, & style element attributes must have a value');
}
if (trustedValueFn !== null) {
if (!isStringLiteral(value)) {
throw Error('AssertionError: extracted attribute value should be string literal');
}
array.push(taggedTemplate(trustedValueFn, new TemplateLiteralExpr([new TemplateLiteralElementExpr(value.value)], []), undefined, value.sourceSpan));
} else {
array.push(value);
}
}
}
arrayFor(kind) {
if (kind === BindingKind.Property || kind === BindingKind.TwoWayProperty) {
this.propertyBindings ??= [];
return this.propertyBindings;
} else {
if (!this.byKind.has(kind)) {
this.byKind.set(kind, []);
}
return this.byKind.get(kind);
}
}
}
function getAttributeNameLiterals(namespace, name) {
const nameLiteral = literal(name);
if (namespace) {
return [literal(0), literal(namespace), nameLiteral];
}
return [nameLiteral];
}
function serializeAttributes({
attributes,
bindings,
classes,
i18n,
projectAs,
styles,
template
}) {
const attrArray = [...attributes];
if (projectAs !== null) {
const parsedR3Selector = parseSelectorToR3Selector(projectAs)[0];
attrArray.push(literal(5), literalOrArrayLiteral(parsedR3Selector));
}
if (classes.length > 0) {
attrArray.push(literal(1), ...classes);
}
if (styles.length > 0) {
attrArray.push(literal(2), ...styles);
}
if (bindings.length > 0) {
attrArray.push(literal(3), ...bindings);
}
if (template.length > 0) {
attrArray.push(literal(4), ...template);
}
if (i18n.length > 0) {
attrArray.push(literal(6), ...i18n);
}
return literalArr(attrArray);
}
function lookupElement$1(elements, xref) {
const el = elements.get(xref);
if (el === undefined) {
throw new Error('All attributes should have an element-like target.');
}
return el;
}
function convertAnimations(job) {
const elements = new Map();
for (const unit of job.units) {
for (const op of unit.create) {
if (!isElementOrContainerOp(op)) {
continue;
}
elements.set(op.xref, op);
}
}
for (const unit of job.units) {
for (const op of unit.ops()) {
if (op.kind === OpKind.AnimationBinding) {
const createAnimationOp = getAnimationOp(op);
if (job.kind === CompilationJobKind.Host) {
unit.create.push(createAnimationOp);
} else {
OpList.insertAfter(createAnimationOp, lookupElement$1(elements, op.target));
}
OpList.remove(op);
}
}
}
}
function getAnimationOp(op) {
if (op.animationBindingKind === 0) {
return createAnimationStringOp(op.name, op.target, op.name === 'animate.enter' ? "enter" : "leave", op.expression, op.securityContext, op.sourceSpan);
} else {
const expression = op.expression;
return createAnimationOp(op.name, op.target, op.name === 'animate.enter' ? "enter" : "leave", [createStatementOp(new ReturnStatement(expression, expression.sourceSpan))], op.securityContext, op.sourceSpan);
}
}
function convertI18nBindings(job) {
const i18nAttributesByElem = new Map();
for (const unit of job.units) {
for (const op of unit.create) {
if (op.kind === OpKind.I18nAttributes) {
i18nAttributesByElem.set(op.target, op);
}
}
for (const op of unit.update) {
switch (op.kind) {
case OpKind.Property:
case OpKind.Attribute:
if (op.i18nContext === null) {
continue;
}
if (!(op.expression instanceof Interpolation)) {
continue;
}
const i18nAttributesForElem = i18nAttributesByElem.get(op.target);
if (i18nAttributesForElem === undefined) {
throw new Error('AssertionError: An i18n attribute binding instruction requires the owning element to have an I18nAttributes create instruction');
}
if (i18nAttributesForElem.target !== op.target) {
throw new Error('AssertionError: Expected i18nAttributes target element to match binding target element');
}
const ops = [];
for (let i = 0; i < op.expression.expressions.length; i++) {
const expr = op.expression.expressions[i];
if (op.expression.i18nPlaceholders.length !== op.expression.expressions.length) {
throw new Error(`AssertionError: An i18n attribute binding instruction requires the same number of expressions and placeholders, but found ${op.expression.i18nPlaceholders.length} placeholders and ${op.expression.expressions.length} expressions`);
}
ops.push(createI18nExpressionOp(op.i18nContext, i18nAttributesForElem.target, i18nAttributesForElem.xref, i18nAttributesForElem.handle, expr, null, op.expression.i18nPlaceholders[i], I18nParamResolutionTime.Creation, I18nExpressionFor.I18nAttribute, op.name, op.sourceSpan));
}
OpList.replaceWithMany(op, ops);
break;
}
}
}
}
function createI18nContexts(job) {
const attrContextByMessage = new Map();
for (const unit of job.units) {
for (const op of unit.ops()) {
switch (op.kind) {
case OpKind.Binding:
case OpKind.Property:
case OpKind.Attribute:
case OpKind.ExtractedAttribute:
if (op.i18nMessage === null) {
continue;
}
if (!attrContextByMessage.has(op.i18nMessage)) {
const i18nContext = createI18nContextOp(I18nContextKind.Attr, job.allocateXrefId(), null, op.i18nMessage, null);
unit.create.push(i18nContext);
attrContextByMessage.set(op.i18nMessage, i18nContext.xref);
}
op.i18nContext = attrContextByMessage.get(op.i18nMessage);
break;
}
}
}
const blockContextByI18nBlock = new Map();
for (const unit of job.units) {
for (const op of unit.create) {
switch (op.kind) {
case OpKind.I18nStart:
if (op.xref === op.root) {
const contextOp = createI18nContextOp(I18nContextKind.RootI18n, job.allocateXrefId(), op.xref, op.message, null);
unit.create.push(contextOp);
op.context = contextOp.xref;
blockContextByI18nBlock.set(op.xref, contextOp);
}
break;
}
}
}
for (const unit of job.units) {
for (const op of unit.create) {
if (op.kind === OpKind.I18nStart && op.xref !== op.root) {
const rootContext = blockContextByI18nBlock.get(op.root);
if (rootContext === undefined) {
throw Error('AssertionError: Root i18n block i18n context should have been created.');
}
op.context = rootContext.xref;
blockContextByI18nBlock.set(op.xref, rootContext);
}
}
}
let currentI18nOp = null;
for (const unit of job.units) {
for (const op of unit.create) {
switch (op.kind) {
case OpKind.I18nStart:
currentI18nOp = op;
break;
case OpKind.I18nEnd:
currentI18nOp = null;
break;
case OpKind.IcuStart:
if (currentI18nOp === null) {
throw Error('AssertionError: Unexpected ICU outside of an i18n block.');
}
if (op.message.id !== currentI18nOp.message.id) {
const contextOp = createI18nContextOp(I18nContextKind.Icu, job.allocateXrefId(), currentI18nOp.root, op.message, null);
unit.create.push(contextOp);
op.context = contextOp.xref;
} else {
op.context = currentI18nOp.context;
blockContextByI18nBlock.get(currentI18nOp.xref).contextKind = I18nContextKind.Icu;
}
break;
}
}
}
}
function deduplicateTextBindings(job) {
const seen = new Map();
for (const unit of job.units) {
for (const op of unit.update.reversed()) {
if (op.kind === OpKind.Binding && op.isTextAttribute) {
const seenForElement = seen.get(op.target) || new Set();
if (seenForElement.has(op.name)) {
if (job.compatibility === CompatibilityMode.TemplateDefinitionBuilder) {
if (op.name === 'style' || op.name === 'class') {
OpList.remove(op);
}
}
}
seenForElement.add(op.name);
seen.set(op.target, seenForElement);
}
}
}
}
function configureDeferInstructions(job) {
for (const unit of job.units) {
for (const op of unit.create) {
if (op.kind !== OpKind.Defer) {
continue;
}
if (op.placeholderMinimumTime !== null) {
op.placeholderConfig = new ConstCollectedExpr(literalOrArrayLiteral([op.placeholderMinimumTime]));
}
if (op.loadingMinimumTime !== null || op.loadingAfterTime !== null) {
op.loadingConfig = new ConstCollectedExpr(literalOrArrayLiteral([op.loadingMinimumTime, op.loadingAfterTime]));
}
}
}
}
function resolveDeferTargetNames(job) {
const scopes = new Map();
function getScopeForView(view) {
if (scopes.has(view.xref)) {
return scopes.get(view.xref);
}
const scope = new Scope$1();
for (const op of view.create) {
if (!isElementOrContainerOp(op) || op.localRefs === null) {
continue;
}
if (!Array.isArray(op.localRefs)) {
throw new Error('LocalRefs were already processed, but were needed to resolve defer targets.');
}
for (const ref of op.localRefs) {
if (ref.target !== '') {
continue;
}
scope.targets.set(ref.name, {
xref: op.xref,
slot: op.handle
});
}
}
scopes.set(view.xref, scope);
return scope;
}
function resolveTrigger(deferOwnerView, op, placeholderView) {
switch (op.trigger.kind) {
case DeferTriggerKind.Idle:
case DeferTriggerKind.Never:
case DeferTriggerKind.Immediate:
case DeferTriggerKind.Timer:
return;
case DeferTriggerKind.Hover:
case DeferTriggerKind.Interaction:
case DeferTriggerKind.Viewport:
if (op.trigger.targetName === null) {
if (placeholderView === null) {
throw new Error('defer on trigger with no target name must have a placeholder block');
}
const placeholder = job.views.get(placeholderView);
if (placeholder == undefined) {
throw new Error('AssertionError: could not find placeholder view for defer on trigger');
}
for (const placeholderOp of placeholder.create) {
if (hasConsumesSlotTrait(placeholderOp) && (isElementOrContainerOp(placeholderOp) || placeholderOp.kind === OpKind.Projection)) {
op.trigger.targetXref = placeholderOp.xref;
op.trigger.targetView = placeholderView;
op.trigger.targetSlotViewSteps = -1;
op.trigger.targetSlot = placeholderOp.handle;
return;
}
}
return;
}
let view = placeholderView !== null ? job.views.get(placeholderView) : deferOwnerView;
let step = placeholderView !== null ? -1 : 0;
while (view !== null) {
const scope = getScopeForView(view);
if (scope.targets.has(op.trigger.targetName)) {
const {
xref,
slot
} = scope.targets.get(op.trigger.targetName);
op.trigger.targetXref = xref;
op.trigger.targetView = view.xref;
op.trigger.targetSlotViewSteps = step;
op.trigger.targetSlot = slot;
return;
}
view = view.parent !== null ? job.views.get(view.parent) : null;
step++;
}
break;
default:
throw new Error(`Trigger kind ${op.trigger.kind} not handled`);
}
}
for (const unit of job.units) {
const defers = new Map();
for (const op of unit.create) {
switch (op.kind) {
case OpKind.Defer:
defers.set(op.xref, op);
break;
case OpKind.DeferOn:
const deferOp = defers.get(op.defer);
resolveTrigger(unit, op, op.modifier === "hydrate" ? deferOp.mainView : deferOp.placeholderView);
break;
}
}
}
}
let Scope$1 = class Scope {
targets = new Map();
};
const REPLACEMENTS = new Map([[OpKind.ElementEnd, [OpKind.ElementStart, OpKind.Element]], [OpKind.ContainerEnd, [OpKind.ContainerStart, OpKind.Container]], [OpKind.I18nEnd, [OpKind.I18nStart, OpKind.I18n]]]);
const IGNORED_OP_KINDS = new Set([OpKind.Pipe]);
function collapseEmptyInstructions(job) {
for (const unit of job.units) {
for (const op of unit.create) {
const opReplacements = REPLACEMENTS.get(op.kind);
if (opReplacements === undefined) {
continue;
}
const [startKind, mergedKind] = opReplacements;
let prevOp = op.prev;
while (prevOp !== null && IGNORED_OP_KINDS.has(prevOp.kind)) {
prevOp = prevOp.prev;
}
if (prevOp !== null && prevOp.kind === startKind) {
prevOp.kind = mergedKind;
OpList.remove(op);
}
}
}
}
function expandSafeReads(job) {
for (const unit of job.units) {
for (const op of unit.ops()) {
transformExpressionsInOp(op, e => safeTransform(e, {
job
}), VisitorContextFlag.None);
transformExpressionsInOp(op, ternaryTransform, VisitorContextFlag.None);
}
}
}
function needsTemporaryInSafeAccess(e) {
if (e instanceof UnaryOperatorExpr) {
return needsTemporaryInSafeAccess(e.expr);
} else if (e instanceof BinaryOperatorExpr) {
return needsTemporaryInSafeAccess(e.lhs) || needsTemporaryInSafeAccess(e.rhs);
} else if (e instanceof ConditionalExpr) {
if (e.falseCase && needsTemporaryInSafeAccess(e.falseCase)) return true;
return needsTemporaryInSafeAccess(e.condition) || needsTemporaryInSafeAccess(e.trueCase);
} else if (e instanceof NotExpr) {
return needsTemporaryInSafeAccess(e.condition);
} else if (e instanceof AssignTemporaryExpr) {
return needsTemporaryInSafeAccess(e.expr);
} else if (e instanceof ReadPropExpr) {
return needsTemporaryInSafeAccess(e.receiver);
} else if (e instanceof ReadKeyExpr) {
return needsTemporaryInSafeAccess(e.receiver) || needsTemporaryInSafeAccess(e.index);
} else if (e instanceof ParenthesizedExpr) {
return needsTemporaryInSafeAccess(e.expr);
}
return e instanceof InvokeFunctionExpr || e instanceof LiteralArrayExpr || e instanceof LiteralMapExpr || e instanceof SafeInvokeFunctionExpr || e instanceof PipeBindingExpr;
}
function temporariesIn(e) {
const temporaries = new Set();
transformExpressionsInExpression(e, e => {
if (e instanceof AssignTemporaryExpr) {
temporaries.add(e.xref);
}
return e;
}, VisitorContextFlag.None);
return temporaries;
}
function eliminateTemporaryAssignments(e, tmps, ctx) {
transformExpressionsInExpression(e, e => {
if (e instanceof AssignTemporaryExpr && tmps.has(e.xref)) {
const read = new ReadTemporaryExpr(e.xref);
return ctx.job.compatibility === CompatibilityMode.TemplateDefinitionBuilder ? new AssignTemporaryExpr(read, read.xref) : read;
}
return e;
}, VisitorContextFlag.None);
return e;
}
function safeTernaryWithTemporary(guard, body, ctx) {
let result;
if (needsTemporaryInSafeAccess(guard)) {
const xref = ctx.job.allocateXrefId();
result = [new AssignTemporaryExpr(guard, xref), new ReadTemporaryExpr(xref)];
} else {
result = [guard, guard.clone()];
eliminateTemporaryAssignments(result[1], temporariesIn(result[0]), ctx);
}
return new SafeTernaryExpr(result[0], body(result[1]));
}
function isSafeAccessExpression(e) {
return e instanceof SafePropertyReadExpr || e instanceof SafeKeyedReadExpr || e instanceof SafeInvokeFunctionExpr;
}
function isUnsafeAccessExpression(e) {
return e instanceof ReadPropExpr || e instanceof ReadKeyExpr || e instanceof InvokeFunctionExpr;
}
function isAccessExpression(e) {
return isSafeAccessExpression(e) || isUnsafeAccessExpression(e);
}
function deepestSafeTernary(e) {
if (isAccessExpression(e) && e.receiver instanceof SafeTernaryExpr) {
let st = e.receiver;
while (st.expr instanceof SafeTernaryExpr) {
st = st.expr;
}
return st;
}
return null;
}
function safeTransform(e, ctx) {
if (!isAccessExpression(e)) {
return e;
}
const dst = deepestSafeTernary(e);
if (dst) {
if (e instanceof InvokeFunctionExpr) {
dst.expr = dst.expr.callFn(e.args);
return e.receiver;
}
if (e instanceof ReadPropExpr) {
dst.expr = dst.expr.prop(e.name);
return e.receiver;
}
if (e instanceof ReadKeyExpr) {
dst.expr = dst.expr.key(e.index);
return e.receiver;
}
if (e instanceof SafeInvokeFunctionExpr) {
dst.expr = safeTernaryWithTemporary(dst.expr, r => r.callFn(e.args), ctx);
return e.receiver;
}
if (e instanceof SafePropertyReadExpr) {
dst.expr = safeTernaryWithTemporary(dst.expr, r => r.prop(e.name), ctx);
return e.receiver;
}
if (e instanceof SafeKeyedReadExpr) {
dst.expr = safeTernaryWithTemporary(dst.expr, r => r.key(e.index), ctx);
return e.receiver;
}
} else {
if (e instanceof SafeInvokeFunctionExpr) {
return safeTernaryWithTemporary(e.receiver, r => r.callFn(e.args), ctx);
}
if (e instanceof SafePropertyReadExpr) {
return safeTernaryWithTemporary(e.receiver, r => r.prop(e.name), ctx);
}
if (e instanceof SafeKeyedReadExpr) {
return safeTernaryWithTemporary(e.receiver, r => r.key(e.index), ctx);
}
}
return e;
}
function ternaryTransform(e) {
if (!(e instanceof SafeTernaryExpr)) {
return e;
}
return new ParenthesizedExpr(new ConditionalExpr(new BinaryOperatorExpr(BinaryOperator.Equals, e.guard, NULL_EXPR), NULL_EXPR, e.expr));
}
const ESCAPE$1 = '\uFFFD';
const ELEMENT_MARKER = '#';
const TEMPLATE_MARKER = '*';
const TAG_CLOSE_MARKER = '/';
const CONTEXT_MARKER = ':';
const LIST_START_MARKER = '[';
const LIST_END_MARKER = ']';
const LIST_DELIMITER = '|';
function extractI18nMessages(job) {
const i18nMessagesByContext = new Map();
const i18nBlocks = new Map();
const i18nContexts = new Map();
for (const unit of job.units) {
for (const op of unit.create) {
switch (op.kind) {
case OpKind.I18nContext:
const i18nMessageOp = createI18nMessage(job, op);
unit.create.push(i18nMessageOp);
i18nMessagesByContext.set(op.xref, i18nMessageOp);
i18nContexts.set(op.xref, op);
break;
case OpKind.I18nStart:
i18nBlocks.set(op.xref, op);
break;
}
}
}
let currentIcu = null;
for (const unit of job.units) {
for (const op of unit.create) {
switch (op.kind) {
case OpKind.IcuStart:
currentIcu = op;
OpList.remove(op);
const icuContext = i18nContexts.get(op.context);
if (icuContext.contextKind !== I18nContextKind.Icu) {
continue;
}
const i18nBlock = i18nBlocks.get(icuContext.i18nBlock);
if (i18nBlock.context === icuContext.xref) {
continue;
}
const rootI18nBlock = i18nBlocks.get(i18nBlock.root);
const rootMessage = i18nMessagesByContext.get(rootI18nBlock.context);
if (rootMessage === undefined) {
throw Error('AssertionError: ICU sub-message should belong to a root message.');
}
const subMessage = i18nMessagesByContext.get(icuContext.xref);
subMessage.messagePlaceholder = op.messagePlaceholder;
rootMessage.subMessages.push(subMessage.xref);
break;
case OpKind.IcuEnd:
currentIcu = null;
OpList.remove(op);
break;
case OpKind.IcuPlaceholder:
if (currentIcu === null || currentIcu.context == null) {
throw Error('AssertionError: Unexpected ICU placeholder outside of i18n context');
}
const msg = i18nMessagesByContext.get(currentIcu.context);
msg.postprocessingParams.set(op.name, literal(formatIcuPlaceholder(op)));
OpList.remove(op);
break;
}
}
}
}
function createI18nMessage(job, context, messagePlaceholder) {
let formattedParams = formatParams(context.params);
const formattedPostprocessingParams = formatParams(context.postprocessingParams);
let needsPostprocessing = [...context.params.values()].some(v => v.length > 1);
return createI18nMessageOp(job.allocateXrefId(), context.xref, context.i18nBlock, context.message, null, formattedParams, formattedPostprocessingParams, needsPostprocessing);
}
function formatIcuPlaceholder(op) {
if (op.strings.length !== op.expressionPlaceholders.length + 1) {
throw Error(`AssertionError: Invalid ICU placeholder with ${op.strings.length} strings and ${op.expressionPlaceholders.length} expressions`);
}
const values = op.expressionPlaceholders.map(formatValue);
return op.strings.flatMap((str, i) => [str, values[i] || '']).join('');
}
function formatParams(params) {
const formattedParams = new Map();
for (const [placeholder, placeholderValues] of params) {
const serializedValues = formatParamValues(placeholderValues);
if (serializedValues !== null) {
formattedParams.set(placeholder, literal(serializedValues));
}
}
return formattedParams;
}
function formatParamValues(values) {
if (values.length === 0) {
return null;
}
const serializedValues = values.map(value => formatValue(value));
return serializedValues.length === 1 ? serializedValues[0] : `${LIST_START_MARKER}${serializedValues.join(LIST_DELIMITER)}${LIST_END_MARKER}`;
}
function formatValue(value) {
if (value.flags & I18nParamValueFlags.ElementTag && value.flags & I18nParamValueFlags.TemplateTag) {
if (typeof value.value !== 'object') {
throw Error('AssertionError: Expected i18n param value to have an element and template slot');
}
const elementValue = formatValue({
...value,
value: value.value.element,
flags: value.flags & ~I18nParamValueFlags.TemplateTag
});
const templateValue = formatValue({
...value,
value: value.value.template,
flags: value.flags & ~I18nParamValueFlags.ElementTag
});
if (value.flags & I18nParamValueFlags.OpenTag && value.flags & I18nParamValueFlags.CloseTag) {
return `${templateValue}${elementValue}${templateValue}`;
}
return value.flags & I18nParamValueFlags.CloseTag ? `${elementValue}${templateValue}` : `${templateValue}${elementValue}`;
}
if (value.flags & I18nParamValueFlags.OpenTag && value.flags & I18nParamValueFlags.CloseTag) {
return `${formatValue({
...value,
flags: value.flags & ~I18nParamValueFlags.CloseTag
})}${formatValue({
...value,
flags: value.flags & ~I18nParamValueFlags.OpenTag
})}`;
}
if (value.flags === I18nParamValueFlags.None) {
return `${value.value}`;
}
let tagMarker = '';
let closeMarker = '';
if (value.flags & I18nParamValueFlags.ElementTag) {
tagMarker = ELEMENT_MARKER;
} else if (value.flags & I18nParamValueFlags.TemplateTag) {
tagMarker = TEMPLATE_MARKER;
}
if (tagMarker !== '') {
closeMarker = value.flags & I18nParamValueFlags.CloseTag ? TAG_CLOSE_MARKER : '';
}
const context = value.subTemplateIndex === null ? '' : `${CONTEXT_MARKER}${value.subTemplateIndex}`;
return `${ESCAPE$1}${closeMarker}${tagMarker}${value.value}${context}${ESCAPE$1}`;
}
function generateAdvance(job) {
for (const unit of job.units) {
const slotMap = new Map();
for (const op of unit.create) {
if (!hasConsumesSlotTrait(op)) {
continue;
} else if (op.handle.slot === null) {
throw new Error(`AssertionError: expected slots to have been allocated before generating advance() calls`);
}
slotMap.set(op.xref, op.handle.slot);
}
let slotContext = 0;
for (const op of unit.update) {
let consumer = null;
if (hasDependsOnSlotContextTrait(op)) {
consumer = op;
} else {
visitExpressionsInOp(op, expr => {
if (consumer === null && hasDependsOnSlotContextTrait(expr)) {
consumer = expr;
}
});
}
if (consumer === null) {
continue;
}
if (!slotMap.has(consumer.target)) {
throw new Error(`AssertionError: reference to unknown slot for target ${consumer.target}`);
}
const slot = slotMap.get(consumer.target);
if (slotContext !== slot) {
const delta = slot - slotContext;
if (delta < 0) {
throw new Error(`AssertionError: slot counter should never need to move backwards`);
}
OpList.insertBefore(createAdvanceOp(delta, consumer.sourceSpan), op);
slotContext = slot;
}
}
}
}
function generateLocalLetReferences(job) {
for (const unit of job.units) {
for (const op of unit.update) {
if (op.kind !== OpKind.StoreLet) {
continue;
}
const variable = {
kind: SemanticVariableKind.Identifier,
name: null,
identifier: op.declaredName,
local: true
};
OpList.replace(op, createVariableOp(job.allocateXrefId(), variable, new StoreLetExpr(op.target, op.value, op.sourceSpan), VariableFlags.None));
}
}
}
function generateProjectionDefs(job) {
const share = job.compatibility === CompatibilityMode.TemplateDefinitionBuilder;
const selectors = [];
let projectionSlotIndex = 0;
for (const unit of job.units) {
for (const op of unit.create) {
if (op.kind === OpKind.Projection) {
selectors.push(op.selector);
op.projectionSlotIndex = projectionSlotIndex++;
}
}
}
if (selectors.length > 0) {
let defExpr = null;
if (selectors.length > 1 || selectors[0] !== '*') {
const def = selectors.map(s => s === '*' ? s : parseSelectorToR3Selector(s));
defExpr = job.pool.getConstLiteral(literalOrArrayLiteral(def), share);
}
job.contentSelectors = job.pool.getConstLiteral(literalOrArrayLiteral(selectors), share);
job.root.create.prepend([createProjectionDefOp(defExpr)]);
}
}
function generateVariables(job) {
recursivelyProcessView(job.root, null);
}
function recursivelyProcessView(view, parentScope) {
const scope = getScopeForView(view, parentScope);
for (const op of view.create) {
switch (op.kind) {
case OpKind.ConditionalCreate:
case OpKind.ConditionalBranchCreate:
case OpKind.Template:
recursivelyProcessView(view.job.views.get(op.xref), scope);
break;
case OpKind.Projection:
if (op.fallbackView !== null) {
recursivelyProcessView(view.job.views.get(op.fallbackView), scope);
}
break;
case OpKind.RepeaterCreate:
recursivelyProcessView(view.job.views.get(op.xref), scope);
if (op.emptyView) {
recursivelyProcessView(view.job.views.get(op.emptyView), scope);
}
if (op.trackByOps !== null) {
op.trackByOps.prepend(generateVariablesInScopeForView(view, scope, false));
}
break;
case OpKind.Animation:
case OpKind.AnimationListener:
case OpKind.Listener:
case OpKind.TwoWayListener:
op.handlerOps.prepend(generateVariablesInScopeForView(view, scope, true));
break;
}
}
view.update.prepend(generateVariablesInScopeForView(view, scope, false));
}
function getScopeForView(view, parent) {
const scope = {
view: view.xref,
viewContextVariable: {
kind: SemanticVariableKind.Context,
name: null,
view: view.xref
},
contextVariables: new Map(),
aliases: view.aliases,
references: [],
letDeclarations: [],
parent
};
for (const identifier of view.contextVariables.keys()) {
scope.contextVariables.set(identifier, {
kind: SemanticVariableKind.Identifier,
name: null,
identifier,
local: false
});
}
for (const op of view.create) {
switch (op.kind) {
case OpKind.ElementStart:
case OpKind.ConditionalCreate:
case OpKind.ConditionalBranchCreate:
case OpKind.Template:
if (!Array.isArray(op.localRefs)) {
throw new Error(`AssertionError: expected localRefs to be an array`);
}
for (let offset = 0; offset < op.localRefs.length; offset++) {
scope.references.push({
name: op.localRefs[offset].name,
targetId: op.xref,
targetSlot: op.handle,
offset,
variable: {
kind: SemanticVariableKind.Identifier,
name: null,
identifier: op.localRefs[offset].name,
local: false
}
});
}
break;
case OpKind.DeclareLet:
scope.letDeclarations.push({
targetId: op.xref,
targetSlot: op.handle,
variable: {
kind: SemanticVariableKind.Identifier,
name: null,
identifier: op.declaredName,
local: false
}
});
break;
}
}
return scope;
}
function generateVariablesInScopeForView(view, scope, isCallback) {
const newOps = [];
if (scope.view !== view.xref) {
newOps.push(createVariableOp(view.job.allocateXrefId(), scope.viewContextVariable, new NextContextExpr(), VariableFlags.None));
}
const scopeView = view.job.views.get(scope.view);
for (const [name, value] of scopeView.contextVariables) {
const context = new ContextExpr(scope.view);
const variable = value === CTX_REF ? context : new ReadPropExpr(context, value);
newOps.push(createVariableOp(view.job.allocateXrefId(), scope.contextVariables.get(name), variable, VariableFlags.None));
}
for (const alias of scopeView.aliases) {
newOps.push(createVariableOp(view.job.allocateXrefId(), alias, alias.expression.clone(), VariableFlags.AlwaysInline));
}
for (const ref of scope.references) {
newOps.push(createVariableOp(view.job.allocateXrefId(), ref.variable, new ReferenceExpr(ref.targetId, ref.targetSlot, ref.offset), VariableFlags.None));
}
if (scope.view !== view.xref || isCallback) {
for (const decl of scope.letDeclarations) {
newOps.push(createVariableOp(view.job.allocateXrefId(), decl.variable, new ContextLetReferenceExpr(decl.targetId, decl.targetSlot), VariableFlags.None));
}
}
if (scope.parent !== null) {
newOps.push(...generateVariablesInScopeForView(view, scope.parent, false));
}
return newOps;
}
function collectConstExpressions(job) {
for (const unit of job.units) {
for (const op of unit.ops()) {
transformExpressionsInOp(op, expr => {
if (!(expr instanceof ConstCollectedExpr)) {
return expr;
}
return literal(job.addConst(expr.expr));
}, VisitorContextFlag.None);
}
}
}
const STYLE_DOT = 'style.';
const CLASS_DOT = 'class.';
const STYLE_BANG = 'style!';
const CLASS_BANG = 'class!';
const BANG_IMPORTANT = '!important';
function parseHostStyleProperties(job) {
for (const op of job.root.update) {
if (!(op.kind === OpKind.Binding && op.bindingKind === BindingKind.Property)) {
continue;
}
if (op.name.endsWith(BANG_IMPORTANT)) {
op.name = op.name.substring(0, op.name.length - BANG_IMPORTANT.length);
}
if (op.name.startsWith(STYLE_DOT)) {
op.bindingKind = BindingKind.StyleProperty;
op.name = op.name.substring(STYLE_DOT.length);
if (!isCssCustomProperty(op.name)) {
op.name = hyphenate$1(op.name);
}
const {
property,
suffix
} = parseProperty(op.name);
op.name = property;
op.unit = suffix;
} else if (op.name.startsWith(STYLE_BANG)) {
op.bindingKind = BindingKind.StyleProperty;
op.name = 'style';
} else if (op.name.startsWith(CLASS_DOT)) {
op.bindingKind = BindingKind.ClassName;
op.name = parseProperty(op.name.substring(CLASS_DOT.length)).property;
} else if (op.name.startsWith(CLASS_BANG)) {
op.bindingKind = BindingKind.ClassName;
op.name = parseProperty(op.name.substring(CLASS_BANG.length)).property;
}
}
}
function isCssCustomProperty(name) {
return name.startsWith('--');
}
function hyphenate$1(value) {
return value.replace(/[a-z][A-Z]/g, v => {
return v.charAt(0) + '-' + v.charAt(1);
}).toLowerCase();
}
function parseProperty(name) {
const overrideIndex = name.indexOf('!important');
if (overrideIndex !== -1) {
name = overrideIndex > 0 ? name.substring(0, overrideIndex) : '';
}
let suffix = null;
let property = name;
const unitIndex = name.lastIndexOf('.');
if (unitIndex > 0) {
suffix = name.slice(unitIndex + 1);
property = name.substring(0, unitIndex);
}
return {
property,
suffix
};
}
function mapLiteral(obj, quoted = false) {
return literalMap(Object.keys(obj).map(key => ({
key,
quoted,
value: obj[key]
})));
}
class IcuSerializerVisitor {
visitText(text) {
return text.value;
}
visitContainer(container) {
return container.children.map(child => child.visit(this)).join('');
}
visitIcu(icu) {
const strCases = Object.keys(icu.cases).map(k => `${k} {${icu.cases[k].visit(this)}}`);
const result = `{${icu.expressionPlaceholder}, ${icu.type}, ${strCases.join(' ')}}`;
return result;
}
visitTagPlaceholder(ph) {
return ph.isVoid ? this.formatPh(ph.startName) : `${this.formatPh(ph.startName)}${ph.children.map(child => child.visit(this)).join('')}${this.formatPh(ph.closeName)}`;
}
visitPlaceholder(ph) {
return this.formatPh(ph.name);
}
visitBlockPlaceholder(ph) {
return `${this.formatPh(ph.startName)}${ph.children.map(child => child.visit(this)).join('')}${this.formatPh(ph.closeName)}`;
}
visitIcuPlaceholder(ph, context) {
return this.formatPh(ph.name);
}
formatPh(value) {
return `{${formatI18nPlaceholderName(value, false)}}`;
}
}
const serializer = new IcuSerializerVisitor();
function serializeIcuNode(icu) {
return icu.visit(serializer);
}
class NodeWithI18n {
sourceSpan;
i18n;
constructor(sourceSpan, i18n) {
this.sourceSpan = sourceSpan;
this.i18n = i18n;
}
}
class Text extends NodeWithI18n {
value;
tokens;
constructor(value, sourceSpan, tokens, i18n) {
super(sourceSpan, i18n);
this.value = value;
this.tokens = tokens;
}
visit(visitor, context) {
return visitor.visitText(this, context);
}
}
class Expansion extends NodeWithI18n {
switchValue;
type;
cases;
switchValueSourceSpan;
constructor(switchValue, type, cases, sourceSpan, switchValueSourceSpan, i18n) {
super(sourceSpan, i18n);
this.switchValue = switchValue;
this.type = type;
this.cases = cases;
this.switchValueSourceSpan = switchValueSourceSpan;
}
visit(visitor, context) {
return visitor.visitExpansion(this, context);
}
}
class ExpansionCase {
value;
expression;
sourceSpan;
valueSourceSpan;
expSourceSpan;
constructor(value, expression, sourceSpan, valueSourceSpan, expSourceSpan) {
this.value = value;
this.expression = expression;
this.sourceSpan = sourceSpan;
this.valueSourceSpan = valueSourceSpan;
this.expSourceSpan = expSourceSpan;
}
visit(visitor, context) {
return visitor.visitExpansionCase(this, context);
}
}
class Attribute extends NodeWithI18n {
name;
value;
keySpan;
valueSpan;
valueTokens;
constructor(name, value, sourceSpan, keySpan, valueSpan, valueTokens, i18n) {
super(sourceSpan, i18n);
this.name = name;
this.value = value;
this.keySpan = keySpan;
this.valueSpan = valueSpan;
this.valueTokens = valueTokens;
}
visit(visitor, context) {
return visitor.visitAttribute(this, context);
}
}
class Element extends NodeWithI18n {
name;
attrs;
directives;
children;
isSelfClosing;
startSourceSpan;
endSourceSpan;
isVoid;
constructor(name, attrs, directives, children, isSelfClosing, sourceSpan, startSourceSpan, endSourceSpan = null, isVoid, i18n) {
super(sourceSpan, i18n);
this.name = name;
this.attrs = attrs;
this.directives = directives;
this.children = children;
this.isSelfClosing = isSelfClosing;
this.startSourceSpan = startSourceSpan;
this.endSourceSpan = endSourceSpan;
this.isVoid = isVoid;
}
visit(visitor, context) {
return visitor.visitElement(this, context);
}
}
class Comment {
value;
sourceSpan;
constructor(value, sourceSpan) {
this.value = value;
this.sourceSpan = sourceSpan;
}
visit(visitor, context) {
return visitor.visitComment(this, context);
}
}
class Block extends NodeWithI18n {
name;
parameters;
children;
nameSpan;
startSourceSpan;
endSourceSpan;
constructor(name, parameters, children, sourceSpan, nameSpan, startSourceSpan, endSourceSpan = null, i18n) {
super(sourceSpan, i18n);
this.name = name;
this.parameters = parameters;
this.children = children;
this.nameSpan = nameSpan;
this.startSourceSpan = startSourceSpan;
this.endSourceSpan = endSourceSpan;
}
visit(visitor, context) {
return visitor.visitBlock(this, context);
}
}
class Component extends NodeWithI18n {
componentName;
tagName;
fullName;
attrs;
directives;
children;
isSelfClosing;
startSourceSpan;
endSourceSpan;
constructor(componentName, tagName, fullName, attrs, directives, children, isSelfClosing, sourceSpan, startSourceSpan, endSourceSpan = null, i18n) {
super(sourceSpan, i18n);
this.componentName = componentName;
this.tagName = tagName;
this.fullName = fullName;
this.attrs = attrs;
this.directives = directives;
this.children = children;
this.isSelfClosing = isSelfClosing;
this.startSourceSpan = startSourceSpan;
this.endSourceSpan = endSourceSpan;
}
visit(visitor, context) {
return visitor.visitComponent(this, context);
}
}
class Directive {
name;
attrs;
sourceSpan;
startSourceSpan;
endSourceSpan;
constructor(name, attrs, sourceSpan, startSourceSpan, endSourceSpan = null) {
this.name = name;
this.attrs = attrs;
this.sourceSpan = sourceSpan;
this.startSourceSpan = startSourceSpan;
this.endSourceSpan = endSourceSpan;
}
visit(visitor, context) {
return visitor.visitDirective(this, context);
}
}
class BlockParameter {
expression;
sourceSpan;
constructor(expression, sourceSpan) {
this.expression = expression;
this.sourceSpan = sourceSpan;
}
visit(visitor, context) {
return visitor.visitBlockParameter(this, context);
}
}
class LetDeclaration {
name;
value;
sourceSpan;
nameSpan;
valueSpan;
constructor(name, value, sourceSpan, nameSpan, valueSpan) {
this.name = name;
this.value = value;
this.sourceSpan = sourceSpan;
this.nameSpan = nameSpan;
this.valueSpan = valueSpan;
}
visit(visitor, context) {
return visitor.visitLetDeclaration(this, context);
}
}
function visitAll(visitor, nodes, context = null) {
const result = [];
const visit = visitor.visit ? ast => visitor.visit(ast, context) || ast.visit(visitor, context) : ast => ast.visit(visitor, context);
nodes.forEach(ast => {
const astResult = visit(ast);
if (astResult) {
result.push(astResult);
}
});
return result;
}
class RecursiveVisitor {
constructor() {}
visitElement(ast, context) {
this.visitChildren(context, visit => {
visit(ast.attrs);
visit(ast.directives);
visit(ast.children);
});
}
visitAttribute(ast, context) {}
visitText(ast, context) {}
visitComment(ast, context) {}
visitExpansion(ast, context) {
return this.visitChildren(context, visit => {
visit(ast.cases);
});
}
visitExpansionCase(ast, context) {}
visitBlock(block, context) {
this.visitChildren(context, visit => {
visit(block.parameters);
visit(block.children);
});
}
visitBlockParameter(ast, context) {}
visitLetDeclaration(decl, context) {}
visitComponent(component, context) {
this.visitChildren(context, visit => {
visit(component.attrs);
visit(component.children);
});
}
visitDirective(directive, context) {
this.visitChildren(context, visit => {
visit(directive.attrs);
});
}
visitChildren(context, cb) {
let results = [];
let t = this;
function visit(children) {
if (children) results.push(visitAll(t, children, context));
}
cb(visit);
return Array.prototype.concat.apply([], results);
}
}
const NAMED_ENTITIES = {
'AElig': '\u00C6',
'AMP': '\u0026',
'amp': '\u0026',
'Aacute': '\u00C1',
'Abreve': '\u0102',
'Acirc': '\u00C2',
'Acy': '\u0410',
'Afr': '\uD835\uDD04',
'Agrave': '\u00C0',
'Alpha': '\u0391',
'Amacr': '\u0100',
'And': '\u2A53',
'Aogon': '\u0104',
'Aopf': '\uD835\uDD38',
'ApplyFunction': '\u2061',
'af': '\u2061',
'Aring': '\u00C5',
'angst': '\u00C5',
'Ascr': '\uD835\uDC9C',
'Assign': '\u2254',
'colone': '\u2254',
'coloneq': '\u2254',
'Atilde': '\u00C3',
'Auml': '\u00C4',
'Backslash': '\u2216',
'setminus': '\u2216',
'setmn': '\u2216',
'smallsetminus': '\u2216',
'ssetmn': '\u2216',
'Barv': '\u2AE7',
'Barwed': '\u2306',
'doublebarwedge': '\u2306',
'Bcy': '\u0411',
'Because': '\u2235',
'becaus': '\u2235',
'because': '\u2235',
'Bernoullis': '\u212C',
'Bscr': '\u212C',
'bernou': '\u212C',
'Beta': '\u0392',
'Bfr': '\uD835\uDD05',
'Bopf': '\uD835\uDD39',
'Breve': '\u02D8',
'breve': '\u02D8',
'Bumpeq': '\u224E',
'HumpDownHump': '\u224E',
'bump': '\u224E',
'CHcy': '\u0427',
'COPY': '\u00A9',
'copy': '\u00A9',
'Cacute': '\u0106',
'Cap': '\u22D2',
'CapitalDifferentialD': '\u2145',
'DD': '\u2145',
'Cayleys': '\u212D',
'Cfr': '\u212D',
'Ccaron': '\u010C',
'Ccedil': '\u00C7',
'Ccirc': '\u0108',
'Cconint': '\u2230',
'Cdot': '\u010A',
'Cedilla': '\u00B8',
'cedil': '\u00B8',
'CenterDot': '\u00B7',
'centerdot': '\u00B7',
'middot': '\u00B7',
'Chi': '\u03A7',
'CircleDot': '\u2299',
'odot': '\u2299',
'CircleMinus': '\u2296',
'ominus': '\u2296',
'CirclePlus': '\u2295',
'oplus': '\u2295',
'CircleTimes': '\u2297',
'otimes': '\u2297',
'ClockwiseContourIntegral': '\u2232',
'cwconint': '\u2232',
'CloseCurlyDoubleQuote': '\u201D',
'rdquo': '\u201D',
'rdquor': '\u201D',
'CloseCurlyQuote': '\u2019',
'rsquo': '\u2019',
'rsquor': '\u2019',
'Colon': '\u2237',
'Proportion': '\u2237',
'Colone': '\u2A74',
'Congruent': '\u2261',
'equiv': '\u2261',
'Conint': '\u222F',
'DoubleContourIntegral': '\u222F',
'ContourIntegral': '\u222E',
'conint': '\u222E',
'oint': '\u222E',
'Copf': '\u2102',
'complexes': '\u2102',
'Coproduct': '\u2210',
'coprod': '\u2210',
'CounterClockwiseContourIntegral': '\u2233',
'awconint': '\u2233',
'Cross': '\u2A2F',
'Cscr': '\uD835\uDC9E',
'Cup': '\u22D3',
'CupCap': '\u224D',
'asympeq': '\u224D',
'DDotrahd': '\u2911',
'DJcy': '\u0402',
'DScy': '\u0405',
'DZcy': '\u040F',
'Dagger': '\u2021',
'ddagger': '\u2021',
'Darr': '\u21A1',
'Dashv': '\u2AE4',
'DoubleLeftTee': '\u2AE4',
'Dcaron': '\u010E',
'Dcy': '\u0414',
'Del': '\u2207',
'nabla': '\u2207',
'Delta': '\u0394',
'Dfr': '\uD835\uDD07',
'DiacriticalAcute': '\u00B4',
'acute': '\u00B4',
'DiacriticalDot': '\u02D9',
'dot': '\u02D9',
'DiacriticalDoubleAcute': '\u02DD',
'dblac': '\u02DD',
'DiacriticalGrave': '\u0060',
'grave': '\u0060',
'DiacriticalTilde': '\u02DC',
'tilde': '\u02DC',
'Diamond': '\u22C4',
'diam': '\u22C4',
'diamond': '\u22C4',
'DifferentialD': '\u2146',
'dd': '\u2146',
'Dopf': '\uD835\uDD3B',
'Dot': '\u00A8',
'DoubleDot': '\u00A8',
'die': '\u00A8',
'uml': '\u00A8',
'DotDot': '\u20DC',
'DotEqual': '\u2250',
'doteq': '\u2250',
'esdot': '\u2250',
'DoubleDownArrow': '\u21D3',
'Downarrow': '\u21D3',
'dArr': '\u21D3',
'DoubleLeftArrow': '\u21D0',
'Leftarrow': '\u21D0',
'lArr': '\u21D0',
'DoubleLeftRightArrow': '\u21D4',
'Leftrightarrow': '\u21D4',
'hArr': '\u21D4',
'iff': '\u21D4',
'DoubleLongLeftArrow': '\u27F8',
'Longleftarrow': '\u27F8',
'xlArr': '\u27F8',
'DoubleLongLeftRightArrow': '\u27FA',
'Longleftrightarrow': '\u27FA',
'xhArr': '\u27FA',
'DoubleLongRightArrow': '\u27F9',
'Longrightarrow': '\u27F9',
'xrArr': '\u27F9',
'DoubleRightArrow': '\u21D2',
'Implies': '\u21D2',
'Rightarrow': '\u21D2',
'rArr': '\u21D2',
'DoubleRightTee': '\u22A8',
'vDash': '\u22A8',
'DoubleUpArrow': '\u21D1',
'Uparrow': '\u21D1',
'uArr': '\u21D1',
'DoubleUpDownArrow': '\u21D5',
'Updownarrow': '\u21D5',
'vArr': '\u21D5',
'DoubleVerticalBar': '\u2225',
'par': '\u2225',
'parallel': '\u2225',
'shortparallel': '\u2225',
'spar': '\u2225',
'DownArrow': '\u2193',
'ShortDownArrow': '\u2193',
'darr': '\u2193',
'downarrow': '\u2193',
'DownArrowBar': '\u2913',
'DownArrowUpArrow': '\u21F5',
'duarr': '\u21F5',
'DownBreve': '\u0311',
'DownLeftRightVector': '\u2950',
'DownLeftTeeVector': '\u295E',
'DownLeftVector': '\u21BD',
'leftharpoondown': '\u21BD',
'lhard': '\u21BD',
'DownLeftVectorBar': '\u2956',
'DownRightTeeVector': '\u295F',
'DownRightVector': '\u21C1',
'rhard': '\u21C1',
'rightharpoondown': '\u21C1',
'DownRightVectorBar': '\u2957',
'DownTee': '\u22A4',
'top': '\u22A4',
'DownTeeArrow': '\u21A7',
'mapstodown': '\u21A7',
'Dscr': '\uD835\uDC9F',
'Dstrok': '\u0110',
'ENG': '\u014A',
'ETH': '\u00D0',
'Eacute': '\u00C9',
'Ecaron': '\u011A',
'Ecirc': '\u00CA',
'Ecy': '\u042D',
'Edot': '\u0116',
'Efr': '\uD835\uDD08',
'Egrave': '\u00C8',
'Element': '\u2208',
'in': '\u2208',
'isin': '\u2208',
'isinv': '\u2208',
'Emacr': '\u0112',
'EmptySmallSquare': '\u25FB',
'EmptyVerySmallSquare': '\u25AB',
'Eogon': '\u0118',
'Eopf': '\uD835\uDD3C',
'Epsilon': '\u0395',
'Equal': '\u2A75',
'EqualTilde': '\u2242',
'eqsim': '\u2242',
'esim': '\u2242',
'Equilibrium': '\u21CC',
'rightleftharpoons': '\u21CC',
'rlhar': '\u21CC',
'Escr': '\u2130',
'expectation': '\u2130',
'Esim': '\u2A73',
'Eta': '\u0397',
'Euml': '\u00CB',
'Exists': '\u2203',
'exist': '\u2203',
'ExponentialE': '\u2147',
'ee': '\u2147',
'exponentiale': '\u2147',
'Fcy': '\u0424',
'Ffr': '\uD835\uDD09',
'FilledSmallSquare': '\u25FC',
'FilledVerySmallSquare': '\u25AA',
'blacksquare': '\u25AA',
'squarf': '\u25AA',
'squf': '\u25AA',
'Fopf': '\uD835\uDD3D',
'ForAll': '\u2200',
'forall': '\u2200',
'Fouriertrf': '\u2131',
'Fscr': '\u2131',
'GJcy': '\u0403',
'GT': '\u003E',
'gt': '\u003E',
'Gamma': '\u0393',
'Gammad': '\u03DC',
'Gbreve': '\u011E',
'Gcedil': '\u0122',
'Gcirc': '\u011C',
'Gcy': '\u0413',
'Gdot': '\u0120',
'Gfr': '\uD835\uDD0A',
'Gg': '\u22D9',
'ggg': '\u22D9',
'Gopf': '\uD835\uDD3E',
'GreaterEqual': '\u2265',
'ge': '\u2265',
'geq': '\u2265',
'GreaterEqualLess': '\u22DB',
'gel': '\u22DB',
'gtreqless': '\u22DB',
'GreaterFullEqual': '\u2267',
'gE': '\u2267',
'geqq': '\u2267',
'GreaterGreater': '\u2AA2',
'GreaterLess': '\u2277',
'gl': '\u2277',
'gtrless': '\u2277',
'GreaterSlantEqual': '\u2A7E',
'geqslant': '\u2A7E',
'ges': '\u2A7E',
'GreaterTilde': '\u2273',
'gsim': '\u2273',
'gtrsim': '\u2273',
'Gscr': '\uD835\uDCA2',
'Gt': '\u226B',
'NestedGreaterGreater': '\u226B',
'gg': '\u226B',
'HARDcy': '\u042A',
'Hacek': '\u02C7',
'caron': '\u02C7',
'Hat': '\u005E',
'Hcirc': '\u0124',
'Hfr': '\u210C',
'Poincareplane': '\u210C',
'HilbertSpace': '\u210B',
'Hscr': '\u210B',
'hamilt': '\u210B',
'Hopf': '\u210D',
'quaternions': '\u210D',
'HorizontalLine': '\u2500',
'boxh': '\u2500',
'Hstrok': '\u0126',
'HumpEqual': '\u224F',
'bumpe': '\u224F',
'bumpeq': '\u224F',
'IEcy': '\u0415',
'IJlig': '\u0132',
'IOcy': '\u0401',
'Iacute': '\u00CD',
'Icirc': '\u00CE',
'Icy': '\u0418',
'Idot': '\u0130',
'Ifr': '\u2111',
'Im': '\u2111',
'image': '\u2111',
'imagpart': '\u2111',
'Igrave': '\u00CC',
'Imacr': '\u012A',
'ImaginaryI': '\u2148',
'ii': '\u2148',
'Int': '\u222C',
'Integral': '\u222B',
'int': '\u222B',
'Intersection': '\u22C2',
'bigcap': '\u22C2',
'xcap': '\u22C2',
'InvisibleComma': '\u2063',
'ic': '\u2063',
'InvisibleTimes': '\u2062',
'it': '\u2062',
'Iogon': '\u012E',
'Iopf': '\uD835\uDD40',
'Iota': '\u0399',
'Iscr': '\u2110',
'imagline': '\u2110',
'Itilde': '\u0128',
'Iukcy': '\u0406',
'Iuml': '\u00CF',
'Jcirc': '\u0134',
'Jcy': '\u0419',
'Jfr': '\uD835\uDD0D',
'Jopf': '\uD835\uDD41',
'Jscr': '\uD835\uDCA5',
'Jsercy': '\u0408',
'Jukcy': '\u0404',
'KHcy': '\u0425',
'KJcy': '\u040C',
'Kappa': '\u039A',
'Kcedil': '\u0136',
'Kcy': '\u041A',
'Kfr': '\uD835\uDD0E',
'Kopf': '\uD835\uDD42',
'Kscr': '\uD835\uDCA6',
'LJcy': '\u0409',
'LT': '\u003C',
'lt': '\u003C',
'Lacute': '\u0139',
'Lambda': '\u039B',
'Lang': '\u27EA',
'Laplacetrf': '\u2112',
'Lscr': '\u2112',
'lagran': '\u2112',
'Larr': '\u219E',
'twoheadleftarrow': '\u219E',
'Lcaron': '\u013D',
'Lcedil': '\u013B',
'Lcy': '\u041B',
'LeftAngleBracket': '\u27E8',
'lang': '\u27E8',
'langle': '\u27E8',
'LeftArrow': '\u2190',
'ShortLeftArrow': '\u2190',
'larr': '\u2190',
'leftarrow': '\u2190',
'slarr': '\u2190',
'LeftArrowBar': '\u21E4',
'larrb': '\u21E4',
'LeftArrowRightArrow': '\u21C6',
'leftrightarrows': '\u21C6',
'lrarr': '\u21C6',
'LeftCeiling': '\u2308',
'lceil': '\u2308',
'LeftDoubleBracket': '\u27E6',
'lobrk': '\u27E6',
'LeftDownTeeVector': '\u2961',
'LeftDownVector': '\u21C3',
'dharl': '\u21C3',
'downharpoonleft': '\u21C3',
'LeftDownVectorBar': '\u2959',
'LeftFloor': '\u230A',
'lfloor': '\u230A',
'LeftRightArrow': '\u2194',
'harr': '\u2194',
'leftrightarrow': '\u2194',
'LeftRightVector': '\u294E',
'LeftTee': '\u22A3',
'dashv': '\u22A3',
'LeftTeeArrow': '\u21A4',
'mapstoleft': '\u21A4',
'LeftTeeVector': '\u295A',
'LeftTriangle': '\u22B2',
'vartriangleleft': '\u22B2',
'vltri': '\u22B2',
'LeftTriangleBar': '\u29CF',
'LeftTriangleEqual': '\u22B4',
'ltrie': '\u22B4',
'trianglelefteq': '\u22B4',
'LeftUpDownVector': '\u2951',
'LeftUpTeeVector': '\u2960',
'LeftUpVector': '\u21BF',
'uharl': '\u21BF',
'upharpoonleft': '\u21BF',
'LeftUpVectorBar': '\u2958',
'LeftVector': '\u21BC',
'leftharpoonup': '\u21BC',
'lharu': '\u21BC',
'LeftVectorBar': '\u2952',
'LessEqualGreater': '\u22DA',
'leg': '\u22DA',
'lesseqgtr': '\u22DA',
'LessFullEqual': '\u2266',
'lE': '\u2266',
'leqq': '\u2266',
'LessGreater': '\u2276',
'lessgtr': '\u2276',
'lg': '\u2276',
'LessLess': '\u2AA1',
'LessSlantEqual': '\u2A7D',
'leqslant': '\u2A7D',
'les': '\u2A7D',
'LessTilde': '\u2272',
'lesssim': '\u2272',
'lsim': '\u2272',
'Lfr': '\uD835\uDD0F',
'Ll': '\u22D8',
'Lleftarrow': '\u21DA',
'lAarr': '\u21DA',
'Lmidot': '\u013F',
'LongLeftArrow': '\u27F5',
'longleftarrow': '\u27F5',
'xlarr': '\u27F5',
'LongLeftRightArrow': '\u27F7',
'longleftrightarrow': '\u27F7',
'xharr': '\u27F7',
'LongRightArrow': '\u27F6',
'longrightarrow': '\u27F6',
'xrarr': '\u27F6',
'Lopf': '\uD835\uDD43',
'LowerLeftArrow': '\u2199',
'swarr': '\u2199',
'swarrow': '\u2199',
'LowerRightArrow': '\u2198',
'searr': '\u2198',
'searrow': '\u2198',
'Lsh': '\u21B0',
'lsh': '\u21B0',
'Lstrok': '\u0141',
'Lt': '\u226A',
'NestedLessLess': '\u226A',
'll': '\u226A',
'Map': '\u2905',
'Mcy': '\u041C',
'MediumSpace': '\u205F',
'Mellintrf': '\u2133',
'Mscr': '\u2133',
'phmmat': '\u2133',
'Mfr': '\uD835\uDD10',
'MinusPlus': '\u2213',
'mnplus': '\u2213',
'mp': '\u2213',
'Mopf': '\uD835\uDD44',
'Mu': '\u039C',
'NJcy': '\u040A',
'Nacute': '\u0143',
'Ncaron': '\u0147',
'Ncedil': '\u0145',
'Ncy': '\u041D',
'NegativeMediumSpace': '\u200B',
'NegativeThickSpace': '\u200B',
'NegativeThinSpace': '\u200B',
'NegativeVeryThinSpace': '\u200B',
'ZeroWidthSpace': '\u200B',
'NewLine': '\u000A',
'Nfr': '\uD835\uDD11',
'NoBreak': '\u2060',
'NonBreakingSpace': '\u00A0',
'nbsp': '\u00A0',
'Nopf': '\u2115',
'naturals': '\u2115',
'Not': '\u2AEC',
'NotCongruent': '\u2262',
'nequiv': '\u2262',
'NotCupCap': '\u226D',
'NotDoubleVerticalBar': '\u2226',
'npar': '\u2226',
'nparallel': '\u2226',
'nshortparallel': '\u2226',
'nspar': '\u2226',
'NotElement': '\u2209',
'notin': '\u2209',
'notinva': '\u2209',
'NotEqual': '\u2260',
'ne': '\u2260',
'NotEqualTilde': '\u2242\u0338',
'nesim': '\u2242\u0338',
'NotExists': '\u2204',
'nexist': '\u2204',
'nexists': '\u2204',
'NotGreater': '\u226F',
'ngt': '\u226F',
'ngtr': '\u226F',
'NotGreaterEqual': '\u2271',
'nge': '\u2271',
'ngeq': '\u2271',
'NotGreaterFullEqual': '\u2267\u0338',
'ngE': '\u2267\u0338',
'ngeqq': '\u2267\u0338',
'NotGreaterGreater': '\u226B\u0338',
'nGtv': '\u226B\u0338',
'NotGreaterLess': '\u2279',
'ntgl': '\u2279',
'NotGreaterSlantEqual': '\u2A7E\u0338',
'ngeqslant': '\u2A7E\u0338',
'nges': '\u2A7E\u0338',
'NotGreaterTilde': '\u2275',
'ngsim': '\u2275',
'NotHumpDownHump': '\u224E\u0338',
'nbump': '\u224E\u0338',
'NotHumpEqual': '\u224F\u0338',
'nbumpe': '\u224F\u0338',
'NotLeftTriangle': '\u22EA',
'nltri': '\u22EA',
'ntriangleleft': '\u22EA',
'NotLeftTriangleBar': '\u29CF\u0338',
'NotLeftTriangleEqual': '\u22EC',
'nltrie': '\u22EC',
'ntrianglelefteq': '\u22EC',
'NotLess': '\u226E',
'nless': '\u226E',
'nlt': '\u226E',
'NotLessEqual': '\u2270',
'nle': '\u2270',
'nleq': '\u2270',
'NotLessGreater': '\u2278',
'ntlg': '\u2278',
'NotLessLess': '\u226A\u0338',
'nLtv': '\u226A\u0338',
'NotLessSlantEqual': '\u2A7D\u0338',
'nleqslant': '\u2A7D\u0338',
'nles': '\u2A7D\u0338',
'NotLessTilde': '\u2274',
'nlsim': '\u2274',
'NotNestedGreaterGreater': '\u2AA2\u0338',
'NotNestedLessLess': '\u2AA1\u0338',
'NotPrecedes': '\u2280',
'npr': '\u2280',
'nprec': '\u2280',
'NotPrecedesEqual': '\u2AAF\u0338',
'npre': '\u2AAF\u0338',
'npreceq': '\u2AAF\u0338',
'NotPrecedesSlantEqual': '\u22E0',
'nprcue': '\u22E0',
'NotReverseElement': '\u220C',
'notni': '\u220C',
'notniva': '\u220C',
'NotRightTriangle': '\u22EB',
'nrtri': '\u22EB',
'ntriangleright': '\u22EB',
'NotRightTriangleBar': '\u29D0\u0338',
'NotRightTriangleEqual': '\u22ED',
'nrtrie': '\u22ED',
'ntrianglerighteq': '\u22ED',
'NotSquareSubset': '\u228F\u0338',
'NotSquareSubsetEqual': '\u22E2',
'nsqsube': '\u22E2',
'NotSquareSuperset': '\u2290\u0338',
'NotSquareSupersetEqual': '\u22E3',
'nsqsupe': '\u22E3',
'NotSubset': '\u2282\u20D2',
'nsubset': '\u2282\u20D2',
'vnsub': '\u2282\u20D2',
'NotSubsetEqual': '\u2288',
'nsube': '\u2288',
'nsubseteq': '\u2288',
'NotSucceeds': '\u2281',
'nsc': '\u2281',
'nsucc': '\u2281',
'NotSucceedsEqual': '\u2AB0\u0338',
'nsce': '\u2AB0\u0338',
'nsucceq': '\u2AB0\u0338',
'NotSucceedsSlantEqual': '\u22E1',
'nsccue': '\u22E1',
'NotSucceedsTilde': '\u227F\u0338',
'NotSuperset': '\u2283\u20D2',
'nsupset': '\u2283\u20D2',
'vnsup': '\u2283\u20D2',
'NotSupersetEqual': '\u2289',
'nsupe': '\u2289',
'nsupseteq': '\u2289',
'NotTilde': '\u2241',
'nsim': '\u2241',
'NotTildeEqual': '\u2244',
'nsime': '\u2244',
'nsimeq': '\u2244',
'NotTildeFullEqual': '\u2247',
'ncong': '\u2247',
'NotTildeTilde': '\u2249',
'nap': '\u2249',
'napprox': '\u2249',
'NotVerticalBar': '\u2224',
'nmid': '\u2224',
'nshortmid': '\u2224',
'nsmid': '\u2224',
'Nscr': '\uD835\uDCA9',
'Ntilde': '\u00D1',
'Nu': '\u039D',
'OElig': '\u0152',
'Oacute': '\u00D3',
'Ocirc': '\u00D4',
'Ocy': '\u041E',
'Odblac': '\u0150',
'Ofr': '\uD835\uDD12',
'Ograve': '\u00D2',
'Omacr': '\u014C',
'Omega': '\u03A9',
'ohm': '\u03A9',
'Omicron': '\u039F',
'Oopf': '\uD835\uDD46',
'OpenCurlyDoubleQuote': '\u201C',
'ldquo': '\u201C',
'OpenCurlyQuote': '\u2018',
'lsquo': '\u2018',
'Or': '\u2A54',
'Oscr': '\uD835\uDCAA',
'Oslash': '\u00D8',
'Otilde': '\u00D5',
'Otimes': '\u2A37',
'Ouml': '\u00D6',
'OverBar': '\u203E',
'oline': '\u203E',
'OverBrace': '\u23DE',
'OverBracket': '\u23B4',
'tbrk': '\u23B4',
'OverParenthesis': '\u23DC',
'PartialD': '\u2202',
'part': '\u2202',
'Pcy': '\u041F',
'Pfr': '\uD835\uDD13',
'Phi': '\u03A6',
'Pi': '\u03A0',
'PlusMinus': '\u00B1',
'plusmn': '\u00B1',
'pm': '\u00B1',
'Popf': '\u2119',
'primes': '\u2119',
'Pr': '\u2ABB',
'Precedes': '\u227A',
'pr': '\u227A',
'prec': '\u227A',
'PrecedesEqual': '\u2AAF',
'pre': '\u2AAF',
'preceq': '\u2AAF',
'PrecedesSlantEqual': '\u227C',
'prcue': '\u227C',
'preccurlyeq': '\u227C',
'PrecedesTilde': '\u227E',
'precsim': '\u227E',
'prsim': '\u227E',
'Prime': '\u2033',
'Product': '\u220F',
'prod': '\u220F',
'Proportional': '\u221D',
'prop': '\u221D',
'propto': '\u221D',
'varpropto': '\u221D',
'vprop': '\u221D',
'Pscr': '\uD835\uDCAB',
'Psi': '\u03A8',
'QUOT': '\u0022',
'quot': '\u0022',
'Qfr': '\uD835\uDD14',
'Qopf': '\u211A',
'rationals': '\u211A',
'Qscr': '\uD835\uDCAC',
'RBarr': '\u2910',
'drbkarow': '\u2910',
'REG': '\u00AE',
'circledR': '\u00AE',
'reg': '\u00AE',
'Racute': '\u0154',
'Rang': '\u27EB',
'Rarr': '\u21A0',
'twoheadrightarrow': '\u21A0',
'Rarrtl': '\u2916',
'Rcaron': '\u0158',
'Rcedil': '\u0156',
'Rcy': '\u0420',
'Re': '\u211C',
'Rfr': '\u211C',
'real': '\u211C',
'realpart': '\u211C',
'ReverseElement': '\u220B',
'SuchThat': '\u220B',
'ni': '\u220B',
'niv': '\u220B',
'ReverseEquilibrium': '\u21CB',
'leftrightharpoons': '\u21CB',
'lrhar': '\u21CB',
'ReverseUpEquilibrium': '\u296F',
'duhar': '\u296F',
'Rho': '\u03A1',
'RightAngleBracket': '\u27E9',
'rang': '\u27E9',
'rangle': '\u27E9',
'RightArrow': '\u2192',
'ShortRightArrow': '\u2192',
'rarr': '\u2192',
'rightarrow': '\u2192',
'srarr': '\u2192',
'RightArrowBar': '\u21E5',
'rarrb': '\u21E5',
'RightArrowLeftArrow': '\u21C4',
'rightleftarrows': '\u21C4',
'rlarr': '\u21C4',
'RightCeiling': '\u2309',
'rceil': '\u2309',
'RightDoubleBracket': '\u27E7',
'robrk': '\u27E7',
'RightDownTeeVector': '\u295D',
'RightDownVector': '\u21C2',
'dharr': '\u21C2',
'downharpoonright': '\u21C2',
'RightDownVectorBar': '\u2955',
'RightFloor': '\u230B',
'rfloor': '\u230B',
'RightTee': '\u22A2',
'vdash': '\u22A2',
'RightTeeArrow': '\u21A6',
'map': '\u21A6',
'mapsto': '\u21A6',
'RightTeeVector': '\u295B',
'RightTriangle': '\u22B3',
'vartriangleright': '\u22B3',
'vrtri': '\u22B3',
'RightTriangleBar': '\u29D0',
'RightTriangleEqual': '\u22B5',
'rtrie': '\u22B5',
'trianglerighteq': '\u22B5',
'RightUpDownVector': '\u294F',
'RightUpTeeVector': '\u295C',
'RightUpVector': '\u21BE',
'uharr': '\u21BE',
'upharpoonright': '\u21BE',
'RightUpVectorBar': '\u2954',
'RightVector': '\u21C0',
'rharu': '\u21C0',
'rightharpoonup': '\u21C0',
'RightVectorBar': '\u2953',
'Ropf': '\u211D',
'reals': '\u211D',
'RoundImplies': '\u2970',
'Rrightarrow': '\u21DB',
'rAarr': '\u21DB',
'Rscr': '\u211B',
'realine': '\u211B',
'Rsh': '\u21B1',
'rsh': '\u21B1',
'RuleDelayed': '\u29F4',
'SHCHcy': '\u0429',
'SHcy': '\u0428',
'SOFTcy': '\u042C',
'Sacute': '\u015A',
'Sc': '\u2ABC',
'Scaron': '\u0160',
'Scedil': '\u015E',
'Scirc': '\u015C',
'Scy': '\u0421',
'Sfr': '\uD835\uDD16',
'ShortUpArrow': '\u2191',
'UpArrow': '\u2191',
'uarr': '\u2191',
'uparrow': '\u2191',
'Sigma': '\u03A3',
'SmallCircle': '\u2218',
'compfn': '\u2218',
'Sopf': '\uD835\uDD4A',
'Sqrt': '\u221A',
'radic': '\u221A',
'Square': '\u25A1',
'squ': '\u25A1',
'square': '\u25A1',
'SquareIntersection': '\u2293',
'sqcap': '\u2293',
'SquareSubset': '\u228F',
'sqsub': '\u228F',
'sqsubset': '\u228F',
'SquareSubsetEqual': '\u2291',
'sqsube': '\u2291',
'sqsubseteq': '\u2291',
'SquareSuperset': '\u2290',
'sqsup': '\u2290',
'sqsupset': '\u2290',
'SquareSupersetEqual': '\u2292',
'sqsupe': '\u2292',
'sqsupseteq': '\u2292',
'SquareUnion': '\u2294',
'sqcup': '\u2294',
'Sscr': '\uD835\uDCAE',
'Star': '\u22C6',
'sstarf': '\u22C6',
'Sub': '\u22D0',
'Subset': '\u22D0',
'SubsetEqual': '\u2286',
'sube': '\u2286',
'subseteq': '\u2286',
'Succeeds': '\u227B',
'sc': '\u227B',
'succ': '\u227B',
'SucceedsEqual': '\u2AB0',
'sce': '\u2AB0',
'succeq': '\u2AB0',
'SucceedsSlantEqual': '\u227D',
'sccue': '\u227D',
'succcurlyeq': '\u227D',
'SucceedsTilde': '\u227F',
'scsim': '\u227F',
'succsim': '\u227F',
'Sum': '\u2211',
'sum': '\u2211',
'Sup': '\u22D1',
'Supset': '\u22D1',
'Superset': '\u2283',
'sup': '\u2283',
'supset': '\u2283',
'SupersetEqual': '\u2287',
'supe': '\u2287',
'supseteq': '\u2287',
'THORN': '\u00DE',
'TRADE': '\u2122',
'trade': '\u2122',
'TSHcy': '\u040B',
'TScy': '\u0426',
'Tab': '\u0009',
'Tau': '\u03A4',
'Tcaron': '\u0164',
'Tcedil': '\u0162',
'Tcy': '\u0422',
'Tfr': '\uD835\uDD17',
'Therefore': '\u2234',
'there4': '\u2234',
'therefore': '\u2234',
'Theta': '\u0398',
'ThickSpace': '\u205F\u200A',
'ThinSpace': '\u2009',
'thinsp': '\u2009',
'Tilde': '\u223C',
'sim': '\u223C',
'thicksim': '\u223C',
'thksim': '\u223C',
'TildeEqual': '\u2243',
'sime': '\u2243',
'simeq': '\u2243',
'TildeFullEqual': '\u2245',
'cong': '\u2245',
'TildeTilde': '\u2248',
'ap': '\u2248',
'approx': '\u2248',
'asymp': '\u2248',
'thickapprox': '\u2248',
'thkap': '\u2248',
'Topf': '\uD835\uDD4B',
'TripleDot': '\u20DB',
'tdot': '\u20DB',
'Tscr': '\uD835\uDCAF',
'Tstrok': '\u0166',
'Uacute': '\u00DA',
'Uarr': '\u219F',
'Uarrocir': '\u2949',
'Ubrcy': '\u040E',
'Ubreve': '\u016C',
'Ucirc': '\u00DB',
'Ucy': '\u0423',
'Udblac': '\u0170',
'Ufr': '\uD835\uDD18',
'Ugrave': '\u00D9',
'Umacr': '\u016A',
'UnderBar': '\u005F',
'lowbar': '\u005F',
'UnderBrace': '\u23DF',
'UnderBracket': '\u23B5',
'bbrk': '\u23B5',
'UnderParenthesis': '\u23DD',
'Union': '\u22C3',
'bigcup': '\u22C3',
'xcup': '\u22C3',
'UnionPlus': '\u228E',
'uplus': '\u228E',
'Uogon': '\u0172',
'Uopf': '\uD835\uDD4C',
'UpArrowBar': '\u2912',
'UpArrowDownArrow': '\u21C5',
'udarr': '\u21C5',
'UpDownArrow': '\u2195',
'updownarrow': '\u2195',
'varr': '\u2195',
'UpEquilibrium': '\u296E',
'udhar': '\u296E',
'UpTee': '\u22A5',
'bot': '\u22A5',
'bottom': '\u22A5',
'perp': '\u22A5',
'UpTeeArrow': '\u21A5',
'mapstoup': '\u21A5',
'UpperLeftArrow': '\u2196',
'nwarr': '\u2196',
'nwarrow': '\u2196',
'UpperRightArrow': '\u2197',
'nearr': '\u2197',
'nearrow': '\u2197',
'Upsi': '\u03D2',
'upsih': '\u03D2',
'Upsilon': '\u03A5',
'Uring': '\u016E',
'Uscr': '\uD835\uDCB0',
'Utilde': '\u0168',
'Uuml': '\u00DC',
'VDash': '\u22AB',
'Vbar': '\u2AEB',
'Vcy': '\u0412',
'Vdash': '\u22A9',
'Vdashl': '\u2AE6',
'Vee': '\u22C1',
'bigvee': '\u22C1',
'xvee': '\u22C1',
'Verbar': '\u2016',
'Vert': '\u2016',
'VerticalBar': '\u2223',
'mid': '\u2223',
'shortmid': '\u2223',
'smid': '\u2223',
'VerticalLine': '\u007C',
'verbar': '\u007C',
'vert': '\u007C',
'VerticalSeparator': '\u2758',
'VerticalTilde': '\u2240',
'wr': '\u2240',
'wreath': '\u2240',
'VeryThinSpace': '\u200A',
'hairsp': '\u200A',
'Vfr': '\uD835\uDD19',
'Vopf': '\uD835\uDD4D',
'Vscr': '\uD835\uDCB1',
'Vvdash': '\u22AA',
'Wcirc': '\u0174',
'Wedge': '\u22C0',
'bigwedge': '\u22C0',
'xwedge': '\u22C0',
'Wfr': '\uD835\uDD1A',
'Wopf': '\uD835\uDD4E',
'Wscr': '\uD835\uDCB2',
'Xfr': '\uD835\uDD1B',
'Xi': '\u039E',
'Xopf': '\uD835\uDD4F',
'Xscr': '\uD835\uDCB3',
'YAcy': '\u042F',
'YIcy': '\u0407',
'YUcy': '\u042E',
'Yacute': '\u00DD',
'Ycirc': '\u0176',
'Ycy': '\u042B',
'Yfr': '\uD835\uDD1C',
'Yopf': '\uD835\uDD50',
'Yscr': '\uD835\uDCB4',
'Yuml': '\u0178',
'ZHcy': '\u0416',
'Zacute': '\u0179',
'Zcaron': '\u017D',
'Zcy': '\u0417',
'Zdot': '\u017B',
'Zeta': '\u0396',
'Zfr': '\u2128',
'zeetrf': '\u2128',
'Zopf': '\u2124',
'integers': '\u2124',
'Zscr': '\uD835\uDCB5',
'aacute': '\u00E1',
'abreve': '\u0103',
'ac': '\u223E',
'mstpos': '\u223E',
'acE': '\u223E\u0333',
'acd': '\u223F',
'acirc': '\u00E2',
'acy': '\u0430',
'aelig': '\u00E6',
'afr': '\uD835\uDD1E',
'agrave': '\u00E0',
'alefsym': '\u2135',
'aleph': '\u2135',
'alpha': '\u03B1',
'amacr': '\u0101',
'amalg': '\u2A3F',
'and': '\u2227',
'wedge': '\u2227',
'andand': '\u2A55',
'andd': '\u2A5C',
'andslope': '\u2A58',
'andv': '\u2A5A',
'ang': '\u2220',
'angle': '\u2220',
'ange': '\u29A4',
'angmsd': '\u2221',
'measuredangle': '\u2221',
'angmsdaa': '\u29A8',
'angmsdab': '\u29A9',
'angmsdac': '\u29AA',
'angmsdad': '\u29AB',
'angmsdae': '\u29AC',
'angmsdaf': '\u29AD',
'angmsdag': '\u29AE',
'angmsdah': '\u29AF',
'angrt': '\u221F',
'angrtvb': '\u22BE',
'angrtvbd': '\u299D',
'angsph': '\u2222',
'angzarr': '\u237C',
'aogon': '\u0105',
'aopf': '\uD835\uDD52',
'apE': '\u2A70',
'apacir': '\u2A6F',
'ape': '\u224A',
'approxeq': '\u224A',
'apid': '\u224B',
'apos': '\u0027',
'aring': '\u00E5',
'ascr': '\uD835\uDCB6',
'ast': '\u002A',
'midast': '\u002A',
'atilde': '\u00E3',
'auml': '\u00E4',
'awint': '\u2A11',
'bNot': '\u2AED',
'backcong': '\u224C',
'bcong': '\u224C',
'backepsilon': '\u03F6',
'bepsi': '\u03F6',
'backprime': '\u2035',
'bprime': '\u2035',
'backsim': '\u223D',
'bsim': '\u223D',
'backsimeq': '\u22CD',
'bsime': '\u22CD',
'barvee': '\u22BD',
'barwed': '\u2305',
'barwedge': '\u2305',
'bbrktbrk': '\u23B6',
'bcy': '\u0431',
'bdquo': '\u201E',
'ldquor': '\u201E',
'bemptyv': '\u29B0',
'beta': '\u03B2',
'beth': '\u2136',
'between': '\u226C',
'twixt': '\u226C',
'bfr': '\uD835\uDD1F',
'bigcirc': '\u25EF',
'xcirc': '\u25EF',
'bigodot': '\u2A00',
'xodot': '\u2A00',
'bigoplus': '\u2A01',
'xoplus': '\u2A01',
'bigotimes': '\u2A02',
'xotime': '\u2A02',
'bigsqcup': '\u2A06',
'xsqcup': '\u2A06',
'bigstar': '\u2605',
'starf': '\u2605',
'bigtriangledown': '\u25BD',
'xdtri': '\u25BD',
'bigtriangleup': '\u25B3',
'xutri': '\u25B3',
'biguplus': '\u2A04',
'xuplus': '\u2A04',
'bkarow': '\u290D',
'rbarr': '\u290D',
'blacklozenge': '\u29EB',
'lozf': '\u29EB',
'blacktriangle': '\u25B4',
'utrif': '\u25B4',
'blacktriangledown': '\u25BE',
'dtrif': '\u25BE',
'blacktriangleleft': '\u25C2',
'ltrif': '\u25C2',
'blacktriangleright': '\u25B8',
'rtrif': '\u25B8',
'blank': '\u2423',
'blk12': '\u2592',
'blk14': '\u2591',
'blk34': '\u2593',
'block': '\u2588',
'bne': '\u003D\u20E5',
'bnequiv': '\u2261\u20E5',
'bnot': '\u2310',
'bopf': '\uD835\uDD53',
'bowtie': '\u22C8',
'boxDL': '\u2557',
'boxDR': '\u2554',
'boxDl': '\u2556',
'boxDr': '\u2553',
'boxH': '\u2550',
'boxHD': '\u2566',
'boxHU': '\u2569',
'boxHd': '\u2564',
'boxHu': '\u2567',
'boxUL': '\u255D',
'boxUR': '\u255A',
'boxUl': '\u255C',
'boxUr': '\u2559',
'boxV': '\u2551',
'boxVH': '\u256C',
'boxVL': '\u2563',
'boxVR': '\u2560',
'boxVh': '\u256B',
'boxVl': '\u2562',
'boxVr': '\u255F',
'boxbox': '\u29C9',
'boxdL': '\u2555',
'boxdR': '\u2552',
'boxdl': '\u2510',
'boxdr': '\u250C',
'boxhD': '\u2565',
'boxhU': '\u2568',
'boxhd': '\u252C',
'boxhu': '\u2534',
'boxminus': '\u229F',
'minusb': '\u229F',
'boxplus': '\u229E',
'plusb': '\u229E',
'boxtimes': '\u22A0',
'timesb': '\u22A0',
'boxuL': '\u255B',
'boxuR': '\u2558',
'boxul': '\u2518',
'boxur': '\u2514',
'boxv': '\u2502',
'boxvH': '\u256A',
'boxvL': '\u2561',
'boxvR': '\u255E',
'boxvh': '\u253C',
'boxvl': '\u2524',
'boxvr': '\u251C',
'brvbar': '\u00A6',
'bscr': '\uD835\uDCB7',
'bsemi': '\u204F',
'bsol': '\u005C',
'bsolb': '\u29C5',
'bsolhsub': '\u27C8',
'bull': '\u2022',
'bullet': '\u2022',
'bumpE': '\u2AAE',
'cacute': '\u0107',
'cap': '\u2229',
'capand': '\u2A44',
'capbrcup': '\u2A49',
'capcap': '\u2A4B',
'capcup': '\u2A47',
'capdot': '\u2A40',
'caps': '\u2229\uFE00',
'caret': '\u2041',
'ccaps': '\u2A4D',
'ccaron': '\u010D',
'ccedil': '\u00E7',
'ccirc': '\u0109',
'ccups': '\u2A4C',
'ccupssm': '\u2A50',
'cdot': '\u010B',
'cemptyv': '\u29B2',
'cent': '\u00A2',
'cfr': '\uD835\uDD20',
'chcy': '\u0447',
'check': '\u2713',
'checkmark': '\u2713',
'chi': '\u03C7',
'cir': '\u25CB',
'cirE': '\u29C3',
'circ': '\u02C6',
'circeq': '\u2257',
'cire': '\u2257',
'circlearrowleft': '\u21BA',
'olarr': '\u21BA',
'circlearrowright': '\u21BB',
'orarr': '\u21BB',
'circledS': '\u24C8',
'oS': '\u24C8',
'circledast': '\u229B',
'oast': '\u229B',
'circledcirc': '\u229A',
'ocir': '\u229A',
'circleddash': '\u229D',
'odash': '\u229D',
'cirfnint': '\u2A10',
'cirmid': '\u2AEF',
'cirscir': '\u29C2',
'clubs': '\u2663',
'clubsuit': '\u2663',
'colon': '\u003A',
'comma': '\u002C',
'commat': '\u0040',
'comp': '\u2201',
'complement': '\u2201',
'congdot': '\u2A6D',
'copf': '\uD835\uDD54',
'copysr': '\u2117',
'crarr': '\u21B5',
'cross': '\u2717',
'cscr': '\uD835\uDCB8',
'csub': '\u2ACF',
'csube': '\u2AD1',
'csup': '\u2AD0',
'csupe': '\u2AD2',
'ctdot': '\u22EF',
'cudarrl': '\u2938',
'cudarrr': '\u2935',
'cuepr': '\u22DE',
'curlyeqprec': '\u22DE',
'cuesc': '\u22DF',
'curlyeqsucc': '\u22DF',
'cularr': '\u21B6',
'curvearrowleft': '\u21B6',
'cularrp': '\u293D',
'cup': '\u222A',
'cupbrcap': '\u2A48',
'cupcap': '\u2A46',
'cupcup': '\u2A4A',
'cupdot': '\u228D',
'cupor': '\u2A45',
'cups': '\u222A\uFE00',
'curarr': '\u21B7',
'curvearrowright': '\u21B7',
'curarrm': '\u293C',
'curlyvee': '\u22CE',
'cuvee': '\u22CE',
'curlywedge': '\u22CF',
'cuwed': '\u22CF',
'curren': '\u00A4',
'cwint': '\u2231',
'cylcty': '\u232D',
'dHar': '\u2965',
'dagger': '\u2020',
'daleth': '\u2138',
'dash': '\u2010',
'hyphen': '\u2010',
'dbkarow': '\u290F',
'rBarr': '\u290F',
'dcaron': '\u010F',
'dcy': '\u0434',
'ddarr': '\u21CA',
'downdownarrows': '\u21CA',
'ddotseq': '\u2A77',
'eDDot': '\u2A77',
'deg': '\u00B0',
'delta': '\u03B4',
'demptyv': '\u29B1',
'dfisht': '\u297F',
'dfr': '\uD835\uDD21',
'diamondsuit': '\u2666',
'diams': '\u2666',
'digamma': '\u03DD',
'gammad': '\u03DD',
'disin': '\u22F2',
'div': '\u00F7',
'divide': '\u00F7',
'divideontimes': '\u22C7',
'divonx': '\u22C7',
'djcy': '\u0452',
'dlcorn': '\u231E',
'llcorner': '\u231E',
'dlcrop': '\u230D',
'dollar': '\u0024',
'dopf': '\uD835\uDD55',
'doteqdot': '\u2251',
'eDot': '\u2251',
'dotminus': '\u2238',
'minusd': '\u2238',
'dotplus': '\u2214',
'plusdo': '\u2214',
'dotsquare': '\u22A1',
'sdotb': '\u22A1',
'drcorn': '\u231F',
'lrcorner': '\u231F',
'drcrop': '\u230C',
'dscr': '\uD835\uDCB9',
'dscy': '\u0455',
'dsol': '\u29F6',
'dstrok': '\u0111',
'dtdot': '\u22F1',
'dtri': '\u25BF',
'triangledown': '\u25BF',
'dwangle': '\u29A6',
'dzcy': '\u045F',
'dzigrarr': '\u27FF',
'eacute': '\u00E9',
'easter': '\u2A6E',
'ecaron': '\u011B',
'ecir': '\u2256',
'eqcirc': '\u2256',
'ecirc': '\u00EA',
'ecolon': '\u2255',
'eqcolon': '\u2255',
'ecy': '\u044D',
'edot': '\u0117',
'efDot': '\u2252',
'fallingdotseq': '\u2252',
'efr': '\uD835\uDD22',
'eg': '\u2A9A',
'egrave': '\u00E8',
'egs': '\u2A96',
'eqslantgtr': '\u2A96',
'egsdot': '\u2A98',
'el': '\u2A99',
'elinters': '\u23E7',
'ell': '\u2113',
'els': '\u2A95',
'eqslantless': '\u2A95',
'elsdot': '\u2A97',
'emacr': '\u0113',
'empty': '\u2205',
'emptyset': '\u2205',
'emptyv': '\u2205',
'varnothing': '\u2205',
'emsp13': '\u2004',
'emsp14': '\u2005',
'emsp': '\u2003',
'eng': '\u014B',
'ensp': '\u2002',
'eogon': '\u0119',
'eopf': '\uD835\uDD56',
'epar': '\u22D5',
'eparsl': '\u29E3',
'eplus': '\u2A71',
'epsi': '\u03B5',
'epsilon': '\u03B5',
'epsiv': '\u03F5',
'straightepsilon': '\u03F5',
'varepsilon': '\u03F5',
'equals': '\u003D',
'equest': '\u225F',
'questeq': '\u225F',
'equivDD': '\u2A78',
'eqvparsl': '\u29E5',
'erDot': '\u2253',
'risingdotseq': '\u2253',
'erarr': '\u2971',
'escr': '\u212F',
'eta': '\u03B7',
'eth': '\u00F0',
'euml': '\u00EB',
'euro': '\u20AC',
'excl': '\u0021',
'fcy': '\u0444',
'female': '\u2640',
'ffilig': '\uFB03',
'fflig': '\uFB00',
'ffllig': '\uFB04',
'ffr': '\uD835\uDD23',
'filig': '\uFB01',
'fjlig': '\u0066\u006A',
'flat': '\u266D',
'fllig': '\uFB02',
'fltns': '\u25B1',
'fnof': '\u0192',
'fopf': '\uD835\uDD57',
'fork': '\u22D4',
'pitchfork': '\u22D4',
'forkv': '\u2AD9',
'fpartint': '\u2A0D',
'frac12': '\u00BD',
'half': '\u00BD',
'frac13': '\u2153',
'frac14': '\u00BC',
'frac15': '\u2155',
'frac16': '\u2159',
'frac18': '\u215B',
'frac23': '\u2154',
'frac25': '\u2156',
'frac34': '\u00BE',
'frac35': '\u2157',
'frac38': '\u215C',
'frac45': '\u2158',
'frac56': '\u215A',
'frac58': '\u215D',
'frac78': '\u215E',
'frasl': '\u2044',
'frown': '\u2322',
'sfrown': '\u2322',
'fscr': '\uD835\uDCBB',
'gEl': '\u2A8C',
'gtreqqless': '\u2A8C',
'gacute': '\u01F5',
'gamma': '\u03B3',
'gap': '\u2A86',
'gtrapprox': '\u2A86',
'gbreve': '\u011F',
'gcirc': '\u011D',
'gcy': '\u0433',
'gdot': '\u0121',
'gescc': '\u2AA9',
'gesdot': '\u2A80',
'gesdoto': '\u2A82',
'gesdotol': '\u2A84',
'gesl': '\u22DB\uFE00',
'gesles': '\u2A94',
'gfr': '\uD835\uDD24',
'gimel': '\u2137',
'gjcy': '\u0453',
'glE': '\u2A92',
'gla': '\u2AA5',
'glj': '\u2AA4',
'gnE': '\u2269',
'gneqq': '\u2269',
'gnap': '\u2A8A',
'gnapprox': '\u2A8A',
'gne': '\u2A88',
'gneq': '\u2A88',
'gnsim': '\u22E7',
'gopf': '\uD835\uDD58',
'gscr': '\u210A',
'gsime': '\u2A8E',
'gsiml': '\u2A90',
'gtcc': '\u2AA7',
'gtcir': '\u2A7A',
'gtdot': '\u22D7',
'gtrdot': '\u22D7',
'gtlPar': '\u2995',
'gtquest': '\u2A7C',
'gtrarr': '\u2978',
'gvertneqq': '\u2269\uFE00',
'gvnE': '\u2269\uFE00',
'hardcy': '\u044A',
'harrcir': '\u2948',
'harrw': '\u21AD',
'leftrightsquigarrow': '\u21AD',
'hbar': '\u210F',
'hslash': '\u210F',
'planck': '\u210F',
'plankv': '\u210F',
'hcirc': '\u0125',
'hearts': '\u2665',
'heartsuit': '\u2665',
'hellip': '\u2026',
'mldr': '\u2026',
'hercon': '\u22B9',
'hfr': '\uD835\uDD25',
'hksearow': '\u2925',
'searhk': '\u2925',
'hkswarow': '\u2926',
'swarhk': '\u2926',
'hoarr': '\u21FF',
'homtht': '\u223B',
'hookleftarrow': '\u21A9',
'larrhk': '\u21A9',
'hookrightarrow': '\u21AA',
'rarrhk': '\u21AA',
'hopf': '\uD835\uDD59',
'horbar': '\u2015',
'hscr': '\uD835\uDCBD',
'hstrok': '\u0127',
'hybull': '\u2043',
'iacute': '\u00ED',
'icirc': '\u00EE',
'icy': '\u0438',
'iecy': '\u0435',
'iexcl': '\u00A1',
'ifr': '\uD835\uDD26',
'igrave': '\u00EC',
'iiiint': '\u2A0C',
'qint': '\u2A0C',
'iiint': '\u222D',
'tint': '\u222D',
'iinfin': '\u29DC',
'iiota': '\u2129',
'ijlig': '\u0133',
'imacr': '\u012B',
'imath': '\u0131',
'inodot': '\u0131',
'imof': '\u22B7',
'imped': '\u01B5',
'incare': '\u2105',
'infin': '\u221E',
'infintie': '\u29DD',
'intcal': '\u22BA',
'intercal': '\u22BA',
'intlarhk': '\u2A17',
'intprod': '\u2A3C',
'iprod': '\u2A3C',
'iocy': '\u0451',
'iogon': '\u012F',
'iopf': '\uD835\uDD5A',
'iota': '\u03B9',
'iquest': '\u00BF',
'iscr': '\uD835\uDCBE',
'isinE': '\u22F9',
'isindot': '\u22F5',
'isins': '\u22F4',
'isinsv': '\u22F3',
'itilde': '\u0129',
'iukcy': '\u0456',
'iuml': '\u00EF',
'jcirc': '\u0135',
'jcy': '\u0439',
'jfr': '\uD835\uDD27',
'jmath': '\u0237',
'jopf': '\uD835\uDD5B',
'jscr': '\uD835\uDCBF',
'jsercy': '\u0458',
'jukcy': '\u0454',
'kappa': '\u03BA',
'kappav': '\u03F0',
'varkappa': '\u03F0',
'kcedil': '\u0137',
'kcy': '\u043A',
'kfr': '\uD835\uDD28',
'kgreen': '\u0138',
'khcy': '\u0445',
'kjcy': '\u045C',
'kopf': '\uD835\uDD5C',
'kscr': '\uD835\uDCC0',
'lAtail': '\u291B',
'lBarr': '\u290E',
'lEg': '\u2A8B',
'lesseqqgtr': '\u2A8B',
'lHar': '\u2962',
'lacute': '\u013A',
'laemptyv': '\u29B4',
'lambda': '\u03BB',
'langd': '\u2991',
'lap': '\u2A85',
'lessapprox': '\u2A85',
'laquo': '\u00AB',
'larrbfs': '\u291F',
'larrfs': '\u291D',
'larrlp': '\u21AB',
'looparrowleft': '\u21AB',
'larrpl': '\u2939',
'larrsim': '\u2973',
'larrtl': '\u21A2',
'leftarrowtail': '\u21A2',
'lat': '\u2AAB',
'latail': '\u2919',
'late': '\u2AAD',
'lates': '\u2AAD\uFE00',
'lbarr': '\u290C',
'lbbrk': '\u2772',
'lbrace': '\u007B',
'lcub': '\u007B',
'lbrack': '\u005B',
'lsqb': '\u005B',
'lbrke': '\u298B',
'lbrksld': '\u298F',
'lbrkslu': '\u298D',
'lcaron': '\u013E',
'lcedil': '\u013C',
'lcy': '\u043B',
'ldca': '\u2936',
'ldrdhar': '\u2967',
'ldrushar': '\u294B',
'ldsh': '\u21B2',
'le': '\u2264',
'leq': '\u2264',
'leftleftarrows': '\u21C7',
'llarr': '\u21C7',
'leftthreetimes': '\u22CB',
'lthree': '\u22CB',
'lescc': '\u2AA8',
'lesdot': '\u2A7F',
'lesdoto': '\u2A81',
'lesdotor': '\u2A83',
'lesg': '\u22DA\uFE00',
'lesges': '\u2A93',
'lessdot': '\u22D6',
'ltdot': '\u22D6',
'lfisht': '\u297C',
'lfr': '\uD835\uDD29',
'lgE': '\u2A91',
'lharul': '\u296A',
'lhblk': '\u2584',
'ljcy': '\u0459',
'llhard': '\u296B',
'lltri': '\u25FA',
'lmidot': '\u0140',
'lmoust': '\u23B0',
'lmoustache': '\u23B0',
'lnE': '\u2268',
'lneqq': '\u2268',
'lnap': '\u2A89',
'lnapprox': '\u2A89',
'lne': '\u2A87',
'lneq': '\u2A87',
'lnsim': '\u22E6',
'loang': '\u27EC',
'loarr': '\u21FD',
'longmapsto': '\u27FC',
'xmap': '\u27FC',
'looparrowright': '\u21AC',
'rarrlp': '\u21AC',
'lopar': '\u2985',
'lopf': '\uD835\uDD5D',
'loplus': '\u2A2D',
'lotimes': '\u2A34',
'lowast': '\u2217',
'loz': '\u25CA',
'lozenge': '\u25CA',
'lpar': '\u0028',
'lparlt': '\u2993',
'lrhard': '\u296D',
'lrm': '\u200E',
'lrtri': '\u22BF',
'lsaquo': '\u2039',
'lscr': '\uD835\uDCC1',
'lsime': '\u2A8D',
'lsimg': '\u2A8F',
'lsquor': '\u201A',
'sbquo': '\u201A',
'lstrok': '\u0142',
'ltcc': '\u2AA6',
'ltcir': '\u2A79',
'ltimes': '\u22C9',
'ltlarr': '\u2976',
'ltquest': '\u2A7B',
'ltrPar': '\u2996',
'ltri': '\u25C3',
'triangleleft': '\u25C3',
'lurdshar': '\u294A',
'luruhar': '\u2966',
'lvertneqq': '\u2268\uFE00',
'lvnE': '\u2268\uFE00',
'mDDot': '\u223A',
'macr': '\u00AF',
'strns': '\u00AF',
'male': '\u2642',
'malt': '\u2720',
'maltese': '\u2720',
'marker': '\u25AE',
'mcomma': '\u2A29',
'mcy': '\u043C',
'mdash': '\u2014',
'mfr': '\uD835\uDD2A',
'mho': '\u2127',
'micro': '\u00B5',
'midcir': '\u2AF0',
'minus': '\u2212',
'minusdu': '\u2A2A',
'mlcp': '\u2ADB',
'models': '\u22A7',
'mopf': '\uD835\uDD5E',
'mscr': '\uD835\uDCC2',
'mu': '\u03BC',
'multimap': '\u22B8',
'mumap': '\u22B8',
'nGg': '\u22D9\u0338',
'nGt': '\u226B\u20D2',
'nLeftarrow': '\u21CD',
'nlArr': '\u21CD',
'nLeftrightarrow': '\u21CE',
'nhArr': '\u21CE',
'nLl': '\u22D8\u0338',
'nLt': '\u226A\u20D2',
'nRightarrow': '\u21CF',
'nrArr': '\u21CF',
'nVDash': '\u22AF',
'nVdash': '\u22AE',
'nacute': '\u0144',
'nang': '\u2220\u20D2',
'napE': '\u2A70\u0338',
'napid': '\u224B\u0338',
'napos': '\u0149',
'natur': '\u266E',
'natural': '\u266E',
'ncap': '\u2A43',
'ncaron': '\u0148',
'ncedil': '\u0146',
'ncongdot': '\u2A6D\u0338',
'ncup': '\u2A42',
'ncy': '\u043D',
'ndash': '\u2013',
'neArr': '\u21D7',
'nearhk': '\u2924',
'nedot': '\u2250\u0338',
'nesear': '\u2928',
'toea': '\u2928',
'nfr': '\uD835\uDD2B',
'nharr': '\u21AE',
'nleftrightarrow': '\u21AE',
'nhpar': '\u2AF2',
'nis': '\u22FC',
'nisd': '\u22FA',
'njcy': '\u045A',
'nlE': '\u2266\u0338',
'nleqq': '\u2266\u0338',
'nlarr': '\u219A',
'nleftarrow': '\u219A',
'nldr': '\u2025',
'nopf': '\uD835\uDD5F',
'not': '\u00AC',
'notinE': '\u22F9\u0338',
'notindot': '\u22F5\u0338',
'notinvb': '\u22F7',
'notinvc': '\u22F6',
'notnivb': '\u22FE',
'notnivc': '\u22FD',
'nparsl': '\u2AFD\u20E5',
'npart': '\u2202\u0338',
'npolint': '\u2A14',
'nrarr': '\u219B',
'nrightarrow': '\u219B',
'nrarrc': '\u2933\u0338',
'nrarrw': '\u219D\u0338',
'nscr': '\uD835\uDCC3',
'nsub': '\u2284',
'nsubE': '\u2AC5\u0338',
'nsubseteqq': '\u2AC5\u0338',
'nsup': '\u2285',
'nsupE': '\u2AC6\u0338',
'nsupseteqq': '\u2AC6\u0338',
'ntilde': '\u00F1',
'nu': '\u03BD',
'num': '\u0023',
'numero': '\u2116',
'numsp': '\u2007',
'nvDash': '\u22AD',
'nvHarr': '\u2904',
'nvap': '\u224D\u20D2',
'nvdash': '\u22AC',
'nvge': '\u2265\u20D2',
'nvgt': '\u003E\u20D2',
'nvinfin': '\u29DE',
'nvlArr': '\u2902',
'nvle': '\u2264\u20D2',
'nvlt': '\u003C\u20D2',
'nvltrie': '\u22B4\u20D2',
'nvrArr': '\u2903',
'nvrtrie': '\u22B5\u20D2',
'nvsim': '\u223C\u20D2',
'nwArr': '\u21D6',
'nwarhk': '\u2923',
'nwnear': '\u2927',
'oacute': '\u00F3',
'ocirc': '\u00F4',
'ocy': '\u043E',
'odblac': '\u0151',
'odiv': '\u2A38',
'odsold': '\u29BC',
'oelig': '\u0153',
'ofcir': '\u29BF',
'ofr': '\uD835\uDD2C',
'ogon': '\u02DB',
'ograve': '\u00F2',
'ogt': '\u29C1',
'ohbar': '\u29B5',
'olcir': '\u29BE',
'olcross': '\u29BB',
'olt': '\u29C0',
'omacr': '\u014D',
'omega': '\u03C9',
'omicron': '\u03BF',
'omid': '\u29B6',
'oopf': '\uD835\uDD60',
'opar': '\u29B7',
'operp': '\u29B9',
'or': '\u2228',
'vee': '\u2228',
'ord': '\u2A5D',
'order': '\u2134',
'orderof': '\u2134',
'oscr': '\u2134',
'ordf': '\u00AA',
'ordm': '\u00BA',
'origof': '\u22B6',
'oror': '\u2A56',
'orslope': '\u2A57',
'orv': '\u2A5B',
'oslash': '\u00F8',
'osol': '\u2298',
'otilde': '\u00F5',
'otimesas': '\u2A36',
'ouml': '\u00F6',
'ovbar': '\u233D',
'para': '\u00B6',
'parsim': '\u2AF3',
'parsl': '\u2AFD',
'pcy': '\u043F',
'percnt': '\u0025',
'period': '\u002E',
'permil': '\u2030',
'pertenk': '\u2031',
'pfr': '\uD835\uDD2D',
'phi': '\u03C6',
'phiv': '\u03D5',
'straightphi': '\u03D5',
'varphi': '\u03D5',
'phone': '\u260E',
'pi': '\u03C0',
'piv': '\u03D6',
'varpi': '\u03D6',
'planckh': '\u210E',
'plus': '\u002B',
'plusacir': '\u2A23',
'pluscir': '\u2A22',
'plusdu': '\u2A25',
'pluse': '\u2A72',
'plussim': '\u2A26',
'plustwo': '\u2A27',
'pointint': '\u2A15',
'popf': '\uD835\uDD61',
'pound': '\u00A3',
'prE': '\u2AB3',
'prap': '\u2AB7',
'precapprox': '\u2AB7',
'precnapprox': '\u2AB9',
'prnap': '\u2AB9',
'precneqq': '\u2AB5',
'prnE': '\u2AB5',
'precnsim': '\u22E8',
'prnsim': '\u22E8',
'prime': '\u2032',
'profalar': '\u232E',
'profline': '\u2312',
'profsurf': '\u2313',
'prurel': '\u22B0',
'pscr': '\uD835\uDCC5',
'psi': '\u03C8',
'puncsp': '\u2008',
'qfr': '\uD835\uDD2E',
'qopf': '\uD835\uDD62',
'qprime': '\u2057',
'qscr': '\uD835\uDCC6',
'quatint': '\u2A16',
'quest': '\u003F',
'rAtail': '\u291C',
'rHar': '\u2964',
'race': '\u223D\u0331',
'racute': '\u0155',
'raemptyv': '\u29B3',
'rangd': '\u2992',
'range': '\u29A5',
'raquo': '\u00BB',
'rarrap': '\u2975',
'rarrbfs': '\u2920',
'rarrc': '\u2933',
'rarrfs': '\u291E',
'rarrpl': '\u2945',
'rarrsim': '\u2974',
'rarrtl': '\u21A3',
'rightarrowtail': '\u21A3',
'rarrw': '\u219D',
'rightsquigarrow': '\u219D',
'ratail': '\u291A',
'ratio': '\u2236',
'rbbrk': '\u2773',
'rbrace': '\u007D',
'rcub': '\u007D',
'rbrack': '\u005D',
'rsqb': '\u005D',
'rbrke': '\u298C',
'rbrksld': '\u298E',
'rbrkslu': '\u2990',
'rcaron': '\u0159',
'rcedil': '\u0157',
'rcy': '\u0440',
'rdca': '\u2937',
'rdldhar': '\u2969',
'rdsh': '\u21B3',
'rect': '\u25AD',
'rfisht': '\u297D',
'rfr': '\uD835\uDD2F',
'rharul': '\u296C',
'rho': '\u03C1',
'rhov': '\u03F1',
'varrho': '\u03F1',
'rightrightarrows': '\u21C9',
'rrarr': '\u21C9',
'rightthreetimes': '\u22CC',
'rthree': '\u22CC',
'ring': '\u02DA',
'rlm': '\u200F',
'rmoust': '\u23B1',
'rmoustache': '\u23B1',
'rnmid': '\u2AEE',
'roang': '\u27ED',
'roarr': '\u21FE',
'ropar': '\u2986',
'ropf': '\uD835\uDD63',
'roplus': '\u2A2E',
'rotimes': '\u2A35',
'rpar': '\u0029',
'rpargt': '\u2994',
'rppolint': '\u2A12',
'rsaquo': '\u203A',
'rscr': '\uD835\uDCC7',
'rtimes': '\u22CA',
'rtri': '\u25B9',
'triangleright': '\u25B9',
'rtriltri': '\u29CE',
'ruluhar': '\u2968',
'rx': '\u211E',
'sacute': '\u015B',
'scE': '\u2AB4',
'scap': '\u2AB8',
'succapprox': '\u2AB8',
'scaron': '\u0161',
'scedil': '\u015F',
'scirc': '\u015D',
'scnE': '\u2AB6',
'succneqq': '\u2AB6',
'scnap': '\u2ABA',
'succnapprox': '\u2ABA',
'scnsim': '\u22E9',
'succnsim': '\u22E9',
'scpolint': '\u2A13',
'scy': '\u0441',
'sdot': '\u22C5',
'sdote': '\u2A66',
'seArr': '\u21D8',
'sect': '\u00A7',
'semi': '\u003B',
'seswar': '\u2929',
'tosa': '\u2929',
'sext': '\u2736',
'sfr': '\uD835\uDD30',
'sharp': '\u266F',
'shchcy': '\u0449',
'shcy': '\u0448',
'shy': '\u00AD',
'sigma': '\u03C3',
'sigmaf': '\u03C2',
'sigmav': '\u03C2',
'varsigma': '\u03C2',
'simdot': '\u2A6A',
'simg': '\u2A9E',
'simgE': '\u2AA0',
'siml': '\u2A9D',
'simlE': '\u2A9F',
'simne': '\u2246',
'simplus': '\u2A24',
'simrarr': '\u2972',
'smashp': '\u2A33',
'smeparsl': '\u29E4',
'smile': '\u2323',
'ssmile': '\u2323',
'smt': '\u2AAA',
'smte': '\u2AAC',
'smtes': '\u2AAC\uFE00',
'softcy': '\u044C',
'sol': '\u002F',
'solb': '\u29C4',
'solbar': '\u233F',
'sopf': '\uD835\uDD64',
'spades': '\u2660',
'spadesuit': '\u2660',
'sqcaps': '\u2293\uFE00',
'sqcups': '\u2294\uFE00',
'sscr': '\uD835\uDCC8',
'star': '\u2606',
'sub': '\u2282',
'subset': '\u2282',
'subE': '\u2AC5',
'subseteqq': '\u2AC5',
'subdot': '\u2ABD',
'subedot': '\u2AC3',
'submult': '\u2AC1',
'subnE': '\u2ACB',
'subsetneqq': '\u2ACB',
'subne': '\u228A',
'subsetneq': '\u228A',
'subplus': '\u2ABF',
'subrarr': '\u2979',
'subsim': '\u2AC7',
'subsub': '\u2AD5',
'subsup': '\u2AD3',
'sung': '\u266A',
'sup1': '\u00B9',
'sup2': '\u00B2',
'sup3': '\u00B3',
'supE': '\u2AC6',
'supseteqq': '\u2AC6',
'supdot': '\u2ABE',
'supdsub': '\u2AD8',
'supedot': '\u2AC4',
'suphsol': '\u27C9',
'suphsub': '\u2AD7',
'suplarr': '\u297B',
'supmult': '\u2AC2',
'supnE': '\u2ACC',
'supsetneqq': '\u2ACC',
'supne': '\u228B',
'supsetneq': '\u228B',
'supplus': '\u2AC0',
'supsim': '\u2AC8',
'supsub': '\u2AD4',
'supsup': '\u2AD6',
'swArr': '\u21D9',
'swnwar': '\u292A',
'szlig': '\u00DF',
'target': '\u2316',
'tau': '\u03C4',
'tcaron': '\u0165',
'tcedil': '\u0163',
'tcy': '\u0442',
'telrec': '\u2315',
'tfr': '\uD835\uDD31',
'theta': '\u03B8',
'thetasym': '\u03D1',
'thetav': '\u03D1',
'vartheta': '\u03D1',
'thorn': '\u00FE',
'times': '\u00D7',
'timesbar': '\u2A31',
'timesd': '\u2A30',
'topbot': '\u2336',
'topcir': '\u2AF1',
'topf': '\uD835\uDD65',
'topfork': '\u2ADA',
'tprime': '\u2034',
'triangle': '\u25B5',
'utri': '\u25B5',
'triangleq': '\u225C',
'trie': '\u225C',
'tridot': '\u25EC',
'triminus': '\u2A3A',
'triplus': '\u2A39',
'trisb': '\u29CD',
'tritime': '\u2A3B',
'trpezium': '\u23E2',
'tscr': '\uD835\uDCC9',
'tscy': '\u0446',
'tshcy': '\u045B',
'tstrok': '\u0167',
'uHar': '\u2963',
'uacute': '\u00FA',
'ubrcy': '\u045E',
'ubreve': '\u016D',
'ucirc': '\u00FB',
'ucy': '\u0443',
'udblac': '\u0171',
'ufisht': '\u297E',
'ufr': '\uD835\uDD32',
'ugrave': '\u00F9',
'uhblk': '\u2580',
'ulcorn': '\u231C',
'ulcorner': '\u231C',
'ulcrop': '\u230F',
'ultri': '\u25F8',
'umacr': '\u016B',
'uogon': '\u0173',
'uopf': '\uD835\uDD66',
'upsi': '\u03C5',
'upsilon': '\u03C5',
'upuparrows': '\u21C8',
'uuarr': '\u21C8',
'urcorn': '\u231D',
'urcorner': '\u231D',
'urcrop': '\u230E',
'uring': '\u016F',
'urtri': '\u25F9',
'uscr': '\uD835\uDCCA',
'utdot': '\u22F0',
'utilde': '\u0169',
'uuml': '\u00FC',
'uwangle': '\u29A7',
'vBar': '\u2AE8',
'vBarv': '\u2AE9',
'vangrt': '\u299C',
'varsubsetneq': '\u228A\uFE00',
'vsubne': '\u228A\uFE00',
'varsubsetneqq': '\u2ACB\uFE00',
'vsubnE': '\u2ACB\uFE00',
'varsupsetneq': '\u228B\uFE00',
'vsupne': '\u228B\uFE00',
'varsupsetneqq': '\u2ACC\uFE00',
'vsupnE': '\u2ACC\uFE00',
'vcy': '\u0432',
'veebar': '\u22BB',
'veeeq': '\u225A',
'vellip': '\u22EE',
'vfr': '\uD835\uDD33',
'vopf': '\uD835\uDD67',
'vscr': '\uD835\uDCCB',
'vzigzag': '\u299A',
'wcirc': '\u0175',
'wedbar': '\u2A5F',
'wedgeq': '\u2259',
'weierp': '\u2118',
'wp': '\u2118',
'wfr': '\uD835\uDD34',
'wopf': '\uD835\uDD68',
'wscr': '\uD835\uDCCC',
'xfr': '\uD835\uDD35',
'xi': '\u03BE',
'xnis': '\u22FB',
'xopf': '\uD835\uDD69',
'xscr': '\uD835\uDCCD',
'yacute': '\u00FD',
'yacy': '\u044F',
'ycirc': '\u0177',
'ycy': '\u044B',
'yen': '\u00A5',
'yfr': '\uD835\uDD36',
'yicy': '\u0457',
'yopf': '\uD835\uDD6A',
'yscr': '\uD835\uDCCE',
'yucy': '\u044E',
'yuml': '\u00FF',
'zacute': '\u017A',
'zcaron': '\u017E',
'zcy': '\u0437',
'zdot': '\u017C',
'zeta': '\u03B6',
'zfr': '\uD835\uDD37',
'zhcy': '\u0436',
'zigrarr': '\u21DD',
'zopf': '\uD835\uDD6B',
'zscr': '\uD835\uDCCF',
'zwj': '\u200D',
'zwnj': '\u200C'
};
const NGSP_UNICODE = '\uE500';
NAMED_ENTITIES['ngsp'] = NGSP_UNICODE;
class TokenizeResult {
tokens;
errors;
nonNormalizedIcuExpressions;
constructor(tokens, errors, nonNormalizedIcuExpressions) {
this.tokens = tokens;
this.errors = errors;
this.nonNormalizedIcuExpressions = nonNormalizedIcuExpressions;
}
}
function tokenize(source, url, getTagDefinition, options = {}) {
const tokenizer = new _Tokenizer(new ParseSourceFile(source, url), getTagDefinition, options);
tokenizer.tokenize();
return new TokenizeResult(mergeTextTokens(tokenizer.tokens), tokenizer.errors, tokenizer.nonNormalizedIcuExpressions);
}
const _CR_OR_CRLF_REGEXP = /\r\n?/g;
function _unexpectedCharacterErrorMsg(charCode) {
const char = charCode === $EOF ? 'EOF' : String.fromCharCode(charCode);
return `Unexpected character "${char}"`;
}
function _unknownEntityErrorMsg(entitySrc) {
return `Unknown entity "${entitySrc}" - use the "&#<decimal>;" or "&#x<hex>;" syntax`;
}
function _unparsableEntityErrorMsg(type, entityStr) {
return `Unable to parse entity "${entityStr}" - ${type} character reference entities must end with ";"`;
}
var CharacterReferenceType;
(function (CharacterReferenceType) {
CharacterReferenceType["HEX"] = "hexadecimal";
CharacterReferenceType["DEC"] = "decimal";
})(CharacterReferenceType || (CharacterReferenceType = {}));
const SUPPORTED_BLOCKS = ['@if', '@else', '@for', '@switch', '@case', '@default', '@empty', '@defer', '@placeholder', '@loading', '@error'];
const INTERPOLATION = {
start: '{{',
end: '}}'
};
class _Tokenizer {
_getTagDefinition;
_cursor;
_tokenizeIcu;
_leadingTriviaCodePoints;
_currentTokenStart = null;
_currentTokenType = null;
_expansionCaseStack = [];
_openDirectiveCount = 0;
_inInterpolation = false;
_preserveLineEndings;
_i18nNormalizeLineEndingsInICUs;
_tokenizeBlocks;
_tokenizeLet;
_selectorlessEnabled;
tokens = [];
errors = [];
nonNormalizedIcuExpressions = [];
constructor(_file, _getTagDefinition, options) {
this._getTagDefinition = _getTagDefinition;
this._tokenizeIcu = options.tokenizeExpansionForms || false;
this._leadingTriviaCodePoints = options.leadingTriviaChars && options.leadingTriviaChars.map(c => c.codePointAt(0) || 0);
const range = options.range || {
endPos: _file.content.length,
startPos: 0,
startLine: 0,
startCol: 0
};
this._cursor = options.escapedString ? new EscapedCharacterCursor(_file, range) : new PlainCharacterCursor(_file, range);
this._preserveLineEndings = options.preserveLineEndings || false;
this._i18nNormalizeLineEndingsInICUs = options.i18nNormalizeLineEndingsInICUs || false;
this._tokenizeBlocks = options.tokenizeBlocks ?? true;
this._tokenizeLet = options.tokenizeLet ?? true;
this._selectorlessEnabled = options.selectorlessEnabled ?? false;
try {
this._cursor.init();
} catch (e) {
this.handleError(e);
}
}
_processCarriageReturns(content) {
if (this._preserveLineEndings) {
return content;
}
return content.replace(_CR_OR_CRLF_REGEXP, '\n');
}
tokenize() {
while (this._cursor.peek() !== $EOF) {
const start = this._cursor.clone();
try {
if (this._attemptCharCode($LT)) {
if (this._attemptCharCode($BANG)) {
if (this._attemptCharCode($LBRACKET)) {
this._consumeCdata(start);
} else if (this._attemptCharCode($MINUS)) {
this._consumeComment(start);
} else {
this._consumeDocType(start);
}
} else if (this._attemptCharCode($SLASH)) {
this._consumeTagClose(start);
} else {
this._consumeTagOpen(start);
}
} else if (this._tokenizeLet && this._cursor.peek() === $AT && !this._inInterpolation && this._isLetStart()) {
this._consumeLetDeclaration(start);
} else if (this._tokenizeBlocks && this._isBlockStart()) {
this._consumeBlockStart(start);
} else if (this._tokenizeBlocks && !this._inInterpolation && !this._isInExpansionCase() && !this._isInExpansionForm() && this._attemptCharCode($RBRACE)) {
this._consumeBlockEnd(start);
} else if (!(this._tokenizeIcu && this._tokenizeExpansionForm())) {
this._consumeWithInterpolation(5, 8, () => this._isTextEnd(), () => this._isTagStart());
}
} catch (e) {
this.handleError(e);
}
}
this._beginToken(41);
this._endToken([]);
}
_getBlockName() {
let spacesInNameAllowed = false;
const nameCursor = this._cursor.clone();
this._attemptCharCodeUntilFn(code => {
if (isWhitespace(code)) {
return !spacesInNameAllowed;
}
if (isBlockNameChar(code)) {
spacesInNameAllowed = true;
return false;
}
return true;
});
return this._cursor.getChars(nameCursor).trim();
}
_consumeBlockStart(start) {
this._requireCharCode($AT);
this._beginToken(24, start);
const startToken = this._endToken([this._getBlockName()]);
if (this._cursor.peek() === $LPAREN) {
this._cursor.advance();
this._consumeBlockParameters();
this._attemptCharCodeUntilFn(isNotWhitespace);
if (this._attemptCharCode($RPAREN)) {
this._attemptCharCodeUntilFn(isNotWhitespace);
} else {
startToken.type = 28;
return;
}
}
if (this._attemptCharCode($LBRACE)) {
this._beginToken(25);
this._endToken([]);
} else if (this._isBlockStart() && (startToken.parts[0] === 'case' || startToken.parts[0] === 'default')) {
this._beginToken(25);
this._endToken([]);
this._beginToken(26);
this._endToken([]);
} else {
startToken.type = 28;
}
}
_consumeBlockEnd(start) {
this._beginToken(26, start);
this._endToken([]);
}
_consumeBlockParameters() {
this._attemptCharCodeUntilFn(isBlockParameterChar);
while (this._cursor.peek() !== $RPAREN && this._cursor.peek() !== $EOF) {
this._beginToken(27);
const start = this._cursor.clone();
let inQuote = null;
let openParens = 0;
while (this._cursor.peek() !== $SEMICOLON && this._cursor.peek() !== $EOF || inQuote !== null) {
const char = this._cursor.peek();
if (char === $BACKSLASH) {
this._cursor.advance();
} else if (char === inQuote) {
inQuote = null;
} else if (inQuote === null && isQuote(char)) {
inQuote = char;
} else if (char === $LPAREN && inQuote === null) {
openParens++;
} else if (char === $RPAREN && inQuote === null) {
if (openParens === 0) {
break;
} else if (openParens > 0) {
openParens--;
}
}
this._cursor.advance();
}
this._endToken([this._cursor.getChars(start)]);
this._attemptCharCodeUntilFn(isBlockParameterChar);
}
}
_consumeLetDeclaration(start) {
this._requireStr('@let');
this._beginToken(29, start);
if (isWhitespace(this._cursor.peek())) {
this._attemptCharCodeUntilFn(isNotWhitespace);
} else {
const token = this._endToken([this._cursor.getChars(start)]);
token.type = 32;
return;
}
const startToken = this._endToken([this._getLetDeclarationName()]);
this._attemptCharCodeUntilFn(isNotWhitespace);
if (!this._attemptCharCode($EQ)) {
startToken.type = 32;
return;
}
this._attemptCharCodeUntilFn(code => isNotWhitespace(code) && !isNewLine(code));
this._consumeLetDeclarationValue();
const endChar = this._cursor.peek();
if (endChar === $SEMICOLON) {
this._beginToken(31);
this._endToken([]);
this._cursor.advance();
} else {
startToken.type = 32;
startToken.sourceSpan = this._cursor.getSpan(start);
}
}
_getLetDeclarationName() {
const nameCursor = this._cursor.clone();
let allowDigit = false;
this._attemptCharCodeUntilFn(code => {
if (isAsciiLetter(code) || code === $$ || code === $_ || allowDigit && isDigit(code)) {
allowDigit = true;
return false;
}
return true;
});
return this._cursor.getChars(nameCursor).trim();
}
_consumeLetDeclarationValue() {
const start = this._cursor.clone();
this._beginToken(30, start);
while (this._cursor.peek() !== $EOF) {
const char = this._cursor.peek();
if (char === $SEMICOLON) {
break;
}
if (isQuote(char)) {
this._cursor.advance();
this._attemptCharCodeUntilFn(inner => {
if (inner === $BACKSLASH) {
this._cursor.advance();
return false;
}
return inner === char;
});
}
this._cursor.advance();
}
this._endToken([this._cursor.getChars(start)]);
}
_tokenizeExpansionForm() {
if (this.isExpansionFormStart()) {
this._consumeExpansionFormStart();
return true;
}
if (isExpansionCaseStart(this._cursor.peek()) && this._isInExpansionForm()) {
this._consumeExpansionCaseStart();
return true;
}
if (this._cursor.peek() === $RBRACE) {
if (this._isInExpansionCase()) {
this._consumeExpansionCaseEnd();
return true;
}
if (this._isInExpansionForm()) {
this._consumeExpansionFormEnd();
return true;
}
}
return false;
}
_beginToken(type, start = this._cursor.clone()) {
this._currentTokenStart = start;
this._currentTokenType = type;
}
_endToken(parts, end) {
if (this._currentTokenStart === null) {
throw new ParseError(this._cursor.getSpan(end), 'Programming error - attempted to end a token when there was no start to the token');
}
if (this._currentTokenType === null) {
throw new ParseError(this._cursor.getSpan(this._currentTokenStart), 'Programming error - attempted to end a token which has no token type');
}
const token = {
type: this._currentTokenType,
parts,
sourceSpan: (end ?? this._cursor).getSpan(this._currentTokenStart, this._leadingTriviaCodePoints)
};
this.tokens.push(token);
this._currentTokenStart = null;
this._currentTokenType = null;
return token;
}
_createError(msg, span) {
if (this._isInExpansionForm()) {
msg += ` (Do you have an unescaped "{" in your template? Use "{{ '{' }}") to escape it.)`;
}
const error = new ParseError(span, msg);
this._currentTokenStart = null;
this._currentTokenType = null;
return error;
}
handleError(e) {
if (e instanceof CursorError) {
e = this._createError(e.msg, this._cursor.getSpan(e.cursor));
}
if (e instanceof ParseError) {
this.errors.push(e);
} else {
throw e;
}
}
_attemptCharCode(charCode) {
if (this._cursor.peek() === charCode) {
this._cursor.advance();
return true;
}
return false;
}
_attemptCharCodeCaseInsensitive(charCode) {
if (compareCharCodeCaseInsensitive(this._cursor.peek(), charCode)) {
this._cursor.advance();
return true;
}
return false;
}
_requireCharCode(charCode) {
const location = this._cursor.clone();
if (!this._attemptCharCode(charCode)) {
throw this._createError(_unexpectedCharacterErrorMsg(this._cursor.peek()), this._cursor.getSpan(location));
}
}
_attemptStr(chars) {
const len = chars.length;
if (this._cursor.charsLeft() < len) {
return false;
}
const initialPosition = this._cursor.clone();
for (let i = 0; i < len; i++) {
if (!this._attemptCharCode(chars.charCodeAt(i))) {
this._cursor = initialPosition;
return false;
}
}
return true;
}
_attemptStrCaseInsensitive(chars) {
for (let i = 0; i < chars.length; i++) {
if (!this._attemptCharCodeCaseInsensitive(chars.charCodeAt(i))) {
return false;
}
}
return true;
}
_requireStr(chars) {
const location = this._cursor.clone();
if (!this._attemptStr(chars)) {
throw this._createError(_unexpectedCharacterErrorMsg(this._cursor.peek()), this._cursor.getSpan(location));
}
}
_attemptCharCodeUntilFn(predicate) {
while (!predicate(this._cursor.peek())) {
this._cursor.advance();
}
}
_requireCharCodeUntilFn(predicate, len) {
const start = this._cursor.clone();
this._attemptCharCodeUntilFn(predicate);
if (this._cursor.diff(start) < len) {
throw this._createError(_unexpectedCharacterErrorMsg(this._cursor.peek()), this._cursor.getSpan(start));
}
}
_attemptUntilChar(char) {
while (this._cursor.peek() !== char) {
this._cursor.advance();
}
}
_readChar() {
const char = String.fromCodePoint(this._cursor.peek());
this._cursor.advance();
return char;
}
_peekStr(chars) {
const len = chars.length;
if (this._cursor.charsLeft() < len) {
return false;
}
const cursor = this._cursor.clone();
for (let i = 0; i < len; i++) {
if (cursor.peek() !== chars.charCodeAt(i)) {
return false;
}
cursor.advance();
}
return true;
}
_isBlockStart() {
return this._cursor.peek() === $AT && SUPPORTED_BLOCKS.some(blockName => this._peekStr(blockName));
}
_isLetStart() {
return this._cursor.peek() === $AT && this._peekStr('@let');
}
_consumeEntity(textTokenType) {
this._beginToken(9);
const start = this._cursor.clone();
this._cursor.advance();
if (this._attemptCharCode($HASH)) {
const isHex = this._attemptCharCode($x) || this._attemptCharCode($X);
const codeStart = this._cursor.clone();
this._attemptCharCodeUntilFn(isDigitEntityEnd);
if (this._cursor.peek() != $SEMICOLON) {
this._cursor.advance();
const entityType = isHex ? CharacterReferenceType.HEX : CharacterReferenceType.DEC;
throw this._createError(_unparsableEntityErrorMsg(entityType, this._cursor.getChars(start)), this._cursor.getSpan());
}
const strNum = this._cursor.getChars(codeStart);
this._cursor.advance();
try {
const charCode = parseInt(strNum, isHex ? 16 : 10);
this._endToken([String.fromCodePoint(charCode), this._cursor.getChars(start)]);
} catch {
throw this._createError(_unknownEntityErrorMsg(this._cursor.getChars(start)), this._cursor.getSpan());
}
} else {
const nameStart = this._cursor.clone();
this._attemptCharCodeUntilFn(isNamedEntityEnd);
if (this._cursor.peek() != $SEMICOLON) {
this._beginToken(textTokenType, start);
this._cursor = nameStart;
this._endToken(['&']);
} else {
const name = this._cursor.getChars(nameStart);
this._cursor.advance();
const char = NAMED_ENTITIES.hasOwnProperty(name) && NAMED_ENTITIES[name];
if (!char) {
throw this._createError(_unknownEntityErrorMsg(name), this._cursor.getSpan(start));
}
this._endToken([char, `&${name};`]);
}
}
}
_consumeRawText(consumeEntities, endMarkerPredicate) {
this._beginToken(consumeEntities ? 6 : 7);
const parts = [];
while (true) {
const tagCloseStart = this._cursor.clone();
const foundEndMarker = endMarkerPredicate();
this._cursor = tagCloseStart;
if (foundEndMarker) {
break;
}
if (consumeEntities && this._cursor.peek() === $AMPERSAND) {
this._endToken([this._processCarriageReturns(parts.join(''))]);
parts.length = 0;
this._consumeEntity(6);
this._beginToken(6);
} else {
parts.push(this._readChar());
}
}
this._endToken([this._processCarriageReturns(parts.join(''))]);
}
_consumeComment(start) {
this._beginToken(10, start);
this._requireCharCode($MINUS);
this._endToken([]);
this._consumeRawText(false, () => this._attemptStr('-->'));
this._beginToken(11);
this._requireStr('-->');
this._endToken([]);
}
_consumeCdata(start) {
this._beginToken(12, start);
this._requireStr('CDATA[');
this._endToken([]);
this._consumeRawText(false, () => this._attemptStr(']]>'));
this._beginToken(13);
this._requireStr(']]>');
this._endToken([]);
}
_consumeDocType(start) {
this._beginToken(18, start);
const contentStart = this._cursor.clone();
this._attemptUntilChar($GT);
const content = this._cursor.getChars(contentStart);
this._cursor.advance();
this._endToken([content]);
}
_consumePrefixAndName(endPredicate) {
const nameOrPrefixStart = this._cursor.clone();
let prefix = '';
while (this._cursor.peek() !== $COLON && !isPrefixEnd(this._cursor.peek())) {
this._cursor.advance();
}
let nameStart;
if (this._cursor.peek() === $COLON) {
prefix = this._cursor.getChars(nameOrPrefixStart);
this._cursor.advance();
nameStart = this._cursor.clone();
} else {
nameStart = nameOrPrefixStart;
}
this._requireCharCodeUntilFn(endPredicate, prefix === '' ? 0 : 1);
const name = this._cursor.getChars(nameStart);
return [prefix, name];
}
_consumeTagOpen(start) {
let tagName;
let prefix;
let closingTagName;
let openToken;
try {
if (this._selectorlessEnabled && isSelectorlessNameStart(this._cursor.peek())) {
openToken = this._consumeComponentOpenStart(start);
[closingTagName, prefix, tagName] = openToken.parts;
if (prefix) {
closingTagName += `:${prefix}`;
}
if (tagName) {
closingTagName += `:${tagName}`;
}
this._attemptCharCodeUntilFn(isNotWhitespace);
} else {
if (!isAsciiLetter(this._cursor.peek())) {
throw this._createError(_unexpectedCharacterErrorMsg(this._cursor.peek()), this._cursor.getSpan(start));
}
openToken = this._consumeTagOpenStart(start);
prefix = openToken.parts[0];
tagName = closingTagName = openToken.parts[1];
this._attemptCharCodeUntilFn(isNotWhitespace);
}
while (!isAttributeTerminator(this._cursor.peek())) {
if (this._selectorlessEnabled && this._cursor.peek() === $AT) {
const start = this._cursor.clone();
const nameStart = start.clone();
nameStart.advance();
if (isSelectorlessNameStart(nameStart.peek())) {
this._consumeDirective(start, nameStart);
}
} else {
this._consumeAttribute();
}
}
if (openToken.type === 33) {
this._consumeComponentOpenEnd();
} else {
this._consumeTagOpenEnd();
}
} catch (e) {
if (e instanceof ParseError) {
if (openToken) {
openToken.type = openToken.type === 33 ? 37 : 4;
} else {
this._beginToken(5, start);
this._endToken(['<']);
}
return;
}
throw e;
}
const contentTokenType = this._getTagDefinition(tagName).getContentType(prefix);
if (contentTokenType === TagContentType.RAW_TEXT) {
this._consumeRawTextWithTagClose(openToken, closingTagName, false);
} else if (contentTokenType === TagContentType.ESCAPABLE_RAW_TEXT) {
this._consumeRawTextWithTagClose(openToken, closingTagName, true);
}
}
_consumeRawTextWithTagClose(openToken, tagName, consumeEntities) {
this._consumeRawText(consumeEntities, () => {
if (!this._attemptCharCode($LT)) return false;
if (!this._attemptCharCode($SLASH)) return false;
this._attemptCharCodeUntilFn(isNotWhitespace);
if (!this._attemptStrCaseInsensitive(tagName)) return false;
this._attemptCharCodeUntilFn(isNotWhitespace);
return this._attemptCharCode($GT);
});
this._beginToken(openToken.type === 33 ? 36 : 3);
this._requireCharCodeUntilFn(code => code === $GT, 3);
this._cursor.advance();
this._endToken(openToken.parts);
}
_consumeTagOpenStart(start) {
this._beginToken(0, start);
const parts = this._consumePrefixAndName(isNameEnd);
return this._endToken(parts);
}
_consumeComponentOpenStart(start) {
this._beginToken(33, start);
const parts = this._consumeComponentName();
return this._endToken(parts);
}
_consumeComponentName() {
const nameStart = this._cursor.clone();
while (isSelectorlessNameChar(this._cursor.peek())) {
this._cursor.advance();
}
const name = this._cursor.getChars(nameStart);
let prefix = '';
let tagName = '';
if (this._cursor.peek() === $COLON) {
this._cursor.advance();
[prefix, tagName] = this._consumePrefixAndName(isNameEnd);
}
return [name, prefix, tagName];
}
_consumeAttribute() {
this._consumeAttributeName();
this._attemptCharCodeUntilFn(isNotWhitespace);
if (this._attemptCharCode($EQ)) {
this._attemptCharCodeUntilFn(isNotWhitespace);
this._consumeAttributeValue();
}
this._attemptCharCodeUntilFn(isNotWhitespace);
}
_consumeAttributeName() {
const attrNameStart = this._cursor.peek();
if (attrNameStart === $SQ || attrNameStart === $DQ) {
throw this._createError(_unexpectedCharacterErrorMsg(attrNameStart), this._cursor.getSpan());
}
this._beginToken(14);
let nameEndPredicate;
if (this._openDirectiveCount > 0) {
let openParens = 0;
nameEndPredicate = code => {
if (this._openDirectiveCount > 0) {
if (code === $LPAREN) {
openParens++;
} else if (code === $RPAREN) {
if (openParens === 0) {
return true;
}
openParens--;
}
}
return isNameEnd(code);
};
} else if (attrNameStart === $LBRACKET) {
let openBrackets = 0;
nameEndPredicate = code => {
if (code === $LBRACKET) {
openBrackets++;
} else if (code === $RBRACKET) {
openBrackets--;
}
return openBrackets <= 0 ? isNameEnd(code) : isNewLine(code);
};
} else {
nameEndPredicate = isNameEnd;
}
const prefixAndName = this._consumePrefixAndName(nameEndPredicate);
this._endToken(prefixAndName);
}
_consumeAttributeValue() {
if (this._cursor.peek() === $SQ || this._cursor.peek() === $DQ) {
const quoteChar = this._cursor.peek();
this._consumeQuote(quoteChar);
const endPredicate = () => this._cursor.peek() === quoteChar;
this._consumeWithInterpolation(16, 17, endPredicate, endPredicate);
this._consumeQuote(quoteChar);
} else {
const endPredicate = () => isNameEnd(this._cursor.peek());
this._consumeWithInterpolation(16, 17, endPredicate, endPredicate);
}
}
_consumeQuote(quoteChar) {
this._beginToken(15);
this._requireCharCode(quoteChar);
this._endToken([String.fromCodePoint(quoteChar)]);
}
_consumeTagOpenEnd() {
const tokenType = this._attemptCharCode($SLASH) ? 2 : 1;
this._beginToken(tokenType);
this._requireCharCode($GT);
this._endToken([]);
}
_consumeComponentOpenEnd() {
const tokenType = this._attemptCharCode($SLASH) ? 35 : 34;
this._beginToken(tokenType);
this._requireCharCode($GT);
this._endToken([]);
}
_consumeTagClose(start) {
if (this._selectorlessEnabled) {
const clone = start.clone();
while (clone.peek() !== $GT && !isSelectorlessNameStart(clone.peek())) {
clone.advance();
}
if (isSelectorlessNameStart(clone.peek())) {
this._beginToken(36, start);
const parts = this._consumeComponentName();
this._attemptCharCodeUntilFn(isNotWhitespace);
this._requireCharCode($GT);
this._endToken(parts);
return;
}
}
this._beginToken(3, start);
this._attemptCharCodeUntilFn(isNotWhitespace);
const prefixAndName = this._consumePrefixAndName(isNameEnd);
this._attemptCharCodeUntilFn(isNotWhitespace);
this._requireCharCode($GT);
this._endToken(prefixAndName);
}
_consumeExpansionFormStart() {
this._beginToken(19);
this._requireCharCode($LBRACE);
this._endToken([]);
this._expansionCaseStack.push(19);
this._beginToken(7);
const condition = this._readUntil($COMMA);
const normalizedCondition = this._processCarriageReturns(condition);
if (this._i18nNormalizeLineEndingsInICUs) {
this._endToken([normalizedCondition]);
} else {
const conditionToken = this._endToken([condition]);
if (normalizedCondition !== condition) {
this.nonNormalizedIcuExpressions.push(conditionToken);
}
}
this._requireCharCode($COMMA);
this._attemptCharCodeUntilFn(isNotWhitespace);
this._beginToken(7);
const type = this._readUntil($COMMA);
this._endToken([type]);
this._requireCharCode($COMMA);
this._attemptCharCodeUntilFn(isNotWhitespace);
}
_consumeExpansionCaseStart() {
this._beginToken(20);
const value = this._readUntil($LBRACE).trim();
this._endToken([value]);
this._attemptCharCodeUntilFn(isNotWhitespace);
this._beginToken(21);
this._requireCharCode($LBRACE);
this._endToken([]);
this._attemptCharCodeUntilFn(isNotWhitespace);
this._expansionCaseStack.push(21);
}
_consumeExpansionCaseEnd() {
this._beginToken(22);
this._requireCharCode($RBRACE);
this._endToken([]);
this._attemptCharCodeUntilFn(isNotWhitespace);
this._expansionCaseStack.pop();
}
_consumeExpansionFormEnd() {
this._beginToken(23);
this._requireCharCode($RBRACE);
this._endToken([]);
this._expansionCaseStack.pop();
}
_consumeWithInterpolation(textTokenType, interpolationTokenType, endPredicate, endInterpolation) {
this._beginToken(textTokenType);
const parts = [];
while (!endPredicate()) {
const current = this._cursor.clone();
if (this._attemptStr(INTERPOLATION.start)) {
this._endToken([this._processCarriageReturns(parts.join(''))], current);
parts.length = 0;
this._consumeInterpolation(interpolationTokenType, current, endInterpolation);
this._beginToken(textTokenType);
} else if (this._cursor.peek() === $AMPERSAND) {
this._endToken([this._processCarriageReturns(parts.join(''))]);
parts.length = 0;
this._consumeEntity(textTokenType);
this._beginToken(textTokenType);
} else {
parts.push(this._readChar());
}
}
this._inInterpolation = false;
this._endToken([this._processCarriageReturns(parts.join(''))]);
}
_consumeInterpolation(interpolationTokenType, interpolationStart, prematureEndPredicate) {
const parts = [];
this._beginToken(interpolationTokenType, interpolationStart);
parts.push(INTERPOLATION.start);
const expressionStart = this._cursor.clone();
let inQuote = null;
let inComment = false;
while (this._cursor.peek() !== $EOF && (prematureEndPredicate === null || !prematureEndPredicate())) {
const current = this._cursor.clone();
if (this._isTagStart()) {
this._cursor = current;
parts.push(this._getProcessedChars(expressionStart, current));
this._endToken(parts);
return;
}
if (inQuote === null) {
if (this._attemptStr(INTERPOLATION.end)) {
parts.push(this._getProcessedChars(expressionStart, current));
parts.push(INTERPOLATION.end);
this._endToken(parts);
return;
} else if (this._attemptStr('//')) {
inComment = true;
}
}
const char = this._cursor.peek();
this._cursor.advance();
if (char === $BACKSLASH) {
this._cursor.advance();
} else if (char === inQuote) {
inQuote = null;
} else if (!inComment && inQuote === null && isQuote(char)) {
inQuote = char;
}
}
parts.push(this._getProcessedChars(expressionStart, this._cursor));
this._endToken(parts);
}
_consumeDirective(start, nameStart) {
this._requireCharCode($AT);
this._cursor.advance();
while (isSelectorlessNameChar(this._cursor.peek())) {
this._cursor.advance();
}
this._beginToken(38, start);
const name = this._cursor.getChars(nameStart);
this._endToken([name]);
this._attemptCharCodeUntilFn(isNotWhitespace);
if (this._cursor.peek() !== $LPAREN) {
return;
}
this._openDirectiveCount++;
this._beginToken(39);
this._cursor.advance();
this._endToken([]);
this._attemptCharCodeUntilFn(isNotWhitespace);
while (!isAttributeTerminator(this._cursor.peek()) && this._cursor.peek() !== $RPAREN) {
this._consumeAttribute();
}
this._attemptCharCodeUntilFn(isNotWhitespace);
this._openDirectiveCount--;
if (this._cursor.peek() !== $RPAREN) {
if (this._cursor.peek() === $GT || this._cursor.peek() === $SLASH) {
return;
}
throw this._createError(_unexpectedCharacterErrorMsg(this._cursor.peek()), this._cursor.getSpan(start));
}
this._beginToken(40);
this._cursor.advance();
this._endToken([]);
this._attemptCharCodeUntilFn(isNotWhitespace);
}
_getProcessedChars(start, end) {
return this._processCarriageReturns(end.getChars(start));
}
_isTextEnd() {
if (this._isTagStart() || this._cursor.peek() === $EOF) {
return true;
}
if (this._tokenizeIcu && !this._inInterpolation) {
if (this.isExpansionFormStart()) {
return true;
}
if (this._cursor.peek() === $RBRACE && this._isInExpansionCase()) {
return true;
}
}
if (this._tokenizeBlocks && !this._inInterpolation && !this._isInExpansion() && (this._isBlockStart() || this._isLetStart() || this._cursor.peek() === $RBRACE)) {
return true;
}
return false;
}
_isTagStart() {
if (this._cursor.peek() === $LT) {
const tmp = this._cursor.clone();
tmp.advance();
const code = tmp.peek();
if ($a <= code && code <= $z || $A <= code && code <= $Z || code === $SLASH || code === $BANG) {
return true;
}
}
return false;
}
_readUntil(char) {
const start = this._cursor.clone();
this._attemptUntilChar(char);
return this._cursor.getChars(start);
}
_isInExpansion() {
return this._isInExpansionCase() || this._isInExpansionForm();
}
_isInExpansionCase() {
return this._expansionCaseStack.length > 0 && this._expansionCaseStack[this._expansionCaseStack.length - 1] === 21;
}
_isInExpansionForm() {
return this._expansionCaseStack.length > 0 && this._expansionCaseStack[this._expansionCaseStack.length - 1] === 19;
}
isExpansionFormStart() {
if (this._cursor.peek() !== $LBRACE) {
return false;
}
const start = this._cursor.clone();
const isInterpolation = this._attemptStr(INTERPOLATION.start);
this._cursor = start;
return !isInterpolation;
}
}
function isNotWhitespace(code) {
return !isWhitespace(code) || code === $EOF;
}
function isNameEnd(code) {
return isWhitespace(code) || code === $GT || code === $LT || code === $SLASH || code === $SQ || code === $DQ || code === $EQ || code === $EOF;
}
function isPrefixEnd(code) {
return (code < $a || $z < code) && (code < $A || $Z < code) && (code < $0 || code > $9);
}
function isDigitEntityEnd(code) {
return code === $SEMICOLON || code === $EOF || !isAsciiHexDigit(code);
}
function isNamedEntityEnd(code) {
return code === $SEMICOLON || code === $EOF || !isAsciiLetter(code);
}
function isExpansionCaseStart(peek) {
return peek !== $RBRACE;
}
function compareCharCodeCaseInsensitive(code1, code2) {
return toUpperCaseCharCode(code1) === toUpperCaseCharCode(code2);
}
function toUpperCaseCharCode(code) {
return code >= $a && code <= $z ? code - $a + $A : code;
}
function isBlockNameChar(code) {
return isAsciiLetter(code) || isDigit(code) || code === $_;
}
function isBlockParameterChar(code) {
return code !== $SEMICOLON && isNotWhitespace(code);
}
function isSelectorlessNameStart(code) {
return code === $_ || code >= $A && code <= $Z;
}
function isSelectorlessNameChar(code) {
return isAsciiLetter(code) || isDigit(code) || code === $_;
}
function isAttributeTerminator(code) {
return code === $SLASH || code === $GT || code === $LT || code === $EOF;
}
function mergeTextTokens(srcTokens) {
const dstTokens = [];
let lastDstToken = undefined;
for (let i = 0; i < srcTokens.length; i++) {
const token = srcTokens[i];
if (lastDstToken && lastDstToken.type === 5 && token.type === 5 || lastDstToken && lastDstToken.type === 16 && token.type === 16) {
lastDstToken.parts[0] += token.parts[0];
lastDstToken.sourceSpan.end = token.sourceSpan.end;
} else {
lastDstToken = token;
dstTokens.push(lastDstToken);
}
}
return dstTokens;
}
class PlainCharacterCursor {
state;
file;
input;
end;
constructor(fileOrCursor, range) {
if (fileOrCursor instanceof PlainCharacterCursor) {
this.file = fileOrCursor.file;
this.input = fileOrCursor.input;
this.end = fileOrCursor.end;
const state = fileOrCursor.state;
this.state = {
peek: state.peek,
offset: state.offset,
line: state.line,
column: state.column
};
} else {
if (!range) {
throw new Error('Programming error: the range argument must be provided with a file argument.');
}
this.file = fileOrCursor;
this.input = fileOrCursor.content;
this.end = range.endPos;
this.state = {
peek: -1,
offset: range.startPos,
line: range.startLine,
column: range.startCol
};
}
}
clone() {
return new PlainCharacterCursor(this);
}
peek() {
return this.state.peek;
}
charsLeft() {
return this.end - this.state.offset;
}
diff(other) {
return this.state.offset - other.state.offset;
}
advance() {
this.advanceState(this.state);
}
init() {
this.updatePeek(this.state);
}
getSpan(start, leadingTriviaCodePoints) {
start = start || this;
let fullStart = start;
if (leadingTriviaCodePoints) {
while (this.diff(start) > 0 && leadingTriviaCodePoints.indexOf(start.peek()) !== -1) {
if (fullStart === start) {
start = start.clone();
}
start.advance();
}
}
const startLocation = this.locationFromCursor(start);
const endLocation = this.locationFromCursor(this);
const fullStartLocation = fullStart !== start ? this.locationFromCursor(fullStart) : startLocation;
return new ParseSourceSpan(startLocation, endLocation, fullStartLocation);
}
getChars(start) {
return this.input.substring(start.state.offset, this.state.offset);
}
charAt(pos) {
return this.input.charCodeAt(pos);
}
advanceState(state) {
if (state.offset >= this.end) {
this.state = state;
throw new CursorError('Unexpected character "EOF"', this);
}
const currentChar = this.charAt(state.offset);
if (currentChar === $LF) {
state.line++;
state.column = 0;
} else if (!isNewLine(currentChar)) {
state.column++;
}
state.offset++;
this.updatePeek(state);
}
updatePeek(state) {
state.peek = state.offset >= this.end ? $EOF : this.charAt(state.offset);
}
locationFromCursor(cursor) {
return new ParseLocation(cursor.file, cursor.state.offset, cursor.state.line, cursor.state.column);
}
}
class EscapedCharacterCursor extends PlainCharacterCursor {
internalState;
constructor(fileOrCursor, range) {
if (fileOrCursor instanceof EscapedCharacterCursor) {
super(fileOrCursor);
this.internalState = {
...fileOrCursor.internalState
};
} else {
super(fileOrCursor, range);
this.internalState = this.state;
}
}
advance() {
this.state = this.internalState;
super.advance();
this.processEscapeSequence();
}
init() {
super.init();
this.processEscapeSequence();
}
clone() {
return new EscapedCharacterCursor(this);
}
getChars(start) {
const cursor = start.clone();
let chars = '';
while (cursor.internalState.offset < this.internalState.offset) {
chars += String.fromCodePoint(cursor.peek());
cursor.advance();
}
return chars;
}
processEscapeSequence() {
const peek = () => this.internalState.peek;
if (peek() === $BACKSLASH) {
this.internalState = {
...this.state
};
this.advanceState(this.internalState);
if (peek() === $n) {
this.state.peek = $LF;
} else if (peek() === $r) {
this.state.peek = $CR;
} else if (peek() === $v) {
this.state.peek = $VTAB;
} else if (peek() === $t) {
this.state.peek = $TAB;
} else if (peek() === $b) {
this.state.peek = $BSPACE;
} else if (peek() === $f) {
this.state.peek = $FF;
} else if (peek() === $u) {
this.advanceState(this.internalState);
if (peek() === $LBRACE) {
this.advanceState(this.internalState);
const digitStart = this.clone();
let length = 0;
while (peek() !== $RBRACE) {
this.advanceState(this.internalState);
length++;
}
this.state.peek = this.decodeHexDigits(digitStart, length);
} else {
const digitStart = this.clone();
this.advanceState(this.internalState);
this.advanceState(this.internalState);
this.advanceState(this.internalState);
this.state.peek = this.decodeHexDigits(digitStart, 4);
}
} else if (peek() === $x) {
this.advanceState(this.internalState);
const digitStart = this.clone();
this.advanceState(this.internalState);
this.state.peek = this.decodeHexDigits(digitStart, 2);
} else if (isOctalDigit(peek())) {
let octal = '';
let length = 0;
let previous = this.clone();
while (isOctalDigit(peek()) && length < 3) {
previous = this.clone();
octal += String.fromCodePoint(peek());
this.advanceState(this.internalState);
length++;
}
this.state.peek = parseInt(octal, 8);
this.internalState = previous.internalState;
} else if (isNewLine(this.internalState.peek)) {
this.advanceState(this.internalState);
this.state = this.internalState;
} else {
this.state.peek = this.internalState.peek;
}
}
}
decodeHexDigits(start, length) {
const hex = this.input.slice(start.internalState.offset, start.internalState.offset + length);
const charCode = parseInt(hex, 16);
if (!isNaN(charCode)) {
return charCode;
} else {
start.state = start.internalState;
throw new CursorError('Invalid hexadecimal escape sequence', start);
}
}
}
class CursorError extends Error {
msg;
cursor;
constructor(msg, cursor) {
super(msg);
this.msg = msg;
this.cursor = cursor;
Object.setPrototypeOf(this, new.target.prototype);
}
}
class TreeError extends ParseError {
elementName;
static create(elementName, span, msg) {
return new TreeError(elementName, span, msg);
}
constructor(elementName, span, msg) {
super(span, msg);
this.elementName = elementName;
}
}
class ParseTreeResult {
rootNodes;
errors;
constructor(rootNodes, errors) {
this.rootNodes = rootNodes;
this.errors = errors;
}
}
let Parser$1 = class Parser {
getTagDefinition;
constructor(getTagDefinition) {
this.getTagDefinition = getTagDefinition;
}
parse(source, url, options) {
const tokenizeResult = tokenize(source, url, this.getTagDefinition, options);
const parser = new _TreeBuilder(tokenizeResult.tokens, this.getTagDefinition);
parser.build();
return new ParseTreeResult(parser.rootNodes, [...tokenizeResult.errors, ...parser.errors]);
}
};
class _TreeBuilder {
tokens;
tagDefinitionResolver;
_index = -1;
_peek;
_containerStack = [];
rootNodes = [];
errors = [];
constructor(tokens, tagDefinitionResolver) {
this.tokens = tokens;
this.tagDefinitionResolver = tagDefinitionResolver;
this._advance();
}
build() {
while (this._peek.type !== 41) {
if (this._peek.type === 0 || this._peek.type === 4) {
this._consumeElementStartTag(this._advance());
} else if (this._peek.type === 3) {
this._consumeElementEndTag(this._advance());
} else if (this._peek.type === 12) {
this._closeVoidElement();
this._consumeCdata(this._advance());
} else if (this._peek.type === 10) {
this._closeVoidElement();
this._consumeComment(this._advance());
} else if (this._peek.type === 5 || this._peek.type === 7 || this._peek.type === 6) {
this._closeVoidElement();
this._consumeText(this._advance());
} else if (this._peek.type === 19) {
this._consumeExpansion(this._advance());
} else if (this._peek.type === 24) {
this._closeVoidElement();
this._consumeBlockOpen(this._advance());
} else if (this._peek.type === 26) {
this._closeVoidElement();
this._consumeBlockClose(this._advance());
} else if (this._peek.type === 28) {
this._closeVoidElement();
this._consumeIncompleteBlock(this._advance());
} else if (this._peek.type === 29) {
this._closeVoidElement();
this._consumeLet(this._advance());
} else if (this._peek.type === 32) {
this._closeVoidElement();
this._consumeIncompleteLet(this._advance());
} else if (this._peek.type === 33 || this._peek.type === 37) {
this._consumeComponentStartTag(this._advance());
} else if (this._peek.type === 36) {
this._consumeComponentEndTag(this._advance());
} else {
this._advance();
}
}
for (const leftoverContainer of this._containerStack) {
if (leftoverContainer instanceof Block) {
this.errors.push(TreeError.create(leftoverContainer.name, leftoverContainer.sourceSpan, `Unclosed block "${leftoverContainer.name}"`));
}
}
}
_advance() {
const prev = this._peek;
if (this._index < this.tokens.length - 1) {
this._index++;
}
this._peek = this.tokens[this._index];
return prev;
}
_advanceIf(type) {
if (this._peek.type === type) {
return this._advance();
}
return null;
}
_consumeCdata(_startToken) {
this._consumeText(this._advance());
this._advanceIf(13);
}
_consumeComment(token) {
const text = this._advanceIf(7);
const endToken = this._advanceIf(11);
const value = text != null ? text.parts[0].trim() : null;
const sourceSpan = endToken == null ? token.sourceSpan : new ParseSourceSpan(token.sourceSpan.start, endToken.sourceSpan.end, token.sourceSpan.fullStart);
this._addToParent(new Comment(value, sourceSpan));
}
_consumeExpansion(token) {
const switchValue = this._advance();
const type = this._advance();
const cases = [];
while (this._peek.type === 20) {
const expCase = this._parseExpansionCase();
if (!expCase) return;
cases.push(expCase);
}
if (this._peek.type !== 23) {
this.errors.push(TreeError.create(null, this._peek.sourceSpan, `Invalid ICU message. Missing '}'.`));
return;
}
const sourceSpan = new ParseSourceSpan(token.sourceSpan.start, this._peek.sourceSpan.end, token.sourceSpan.fullStart);
this._addToParent(new Expansion(switchValue.parts[0], type.parts[0], cases, sourceSpan, switchValue.sourceSpan));
this._advance();
}
_parseExpansionCase() {
const value = this._advance();
if (this._peek.type !== 21) {
this.errors.push(TreeError.create(null, this._peek.sourceSpan, `Invalid ICU message. Missing '{'.`));
return null;
}
const start = this._advance();
const exp = this._collectExpansionExpTokens(start);
if (!exp) return null;
const end = this._advance();
exp.push({
type: 41,
parts: [],
sourceSpan: end.sourceSpan
});
const expansionCaseParser = new _TreeBuilder(exp, this.tagDefinitionResolver);
expansionCaseParser.build();
if (expansionCaseParser.errors.length > 0) {
this.errors = this.errors.concat(expansionCaseParser.errors);
return null;
}
const sourceSpan = new ParseSourceSpan(value.sourceSpan.start, end.sourceSpan.end, value.sourceSpan.fullStart);
const expSourceSpan = new ParseSourceSpan(start.sourceSpan.start, end.sourceSpan.end, start.sourceSpan.fullStart);
return new ExpansionCase(value.parts[0], expansionCaseParser.rootNodes, sourceSpan, value.sourceSpan, expSourceSpan);
}
_collectExpansionExpTokens(start) {
const exp = [];
const expansionFormStack = [21];
while (true) {
if (this._peek.type === 19 || this._peek.type === 21) {
expansionFormStack.push(this._peek.type);
}
if (this._peek.type === 22) {
if (lastOnStack(expansionFormStack, 21)) {
expansionFormStack.pop();
if (expansionFormStack.length === 0) return exp;
} else {
this.errors.push(TreeError.create(null, start.sourceSpan, `Invalid ICU message. Missing '}'.`));
return null;
}
}
if (this._peek.type === 23) {
if (lastOnStack(expansionFormStack, 19)) {
expansionFormStack.pop();
} else {
this.errors.push(TreeError.create(null, start.sourceSpan, `Invalid ICU message. Missing '}'.`));
return null;
}
}
if (this._peek.type === 41) {
this.errors.push(TreeError.create(null, start.sourceSpan, `Invalid ICU message. Missing '}'.`));
return null;
}
exp.push(this._advance());
}
}
_consumeText(token) {
const tokens = [token];
const startSpan = token.sourceSpan;
let text = token.parts[0];
if (text.length > 0 && text[0] === '\n') {
const parent = this._getContainer();
if (parent != null && parent.children.length === 0 && this._getTagDefinition(parent)?.ignoreFirstLf) {
text = text.substring(1);
tokens[0] = {
type: token.type,
sourceSpan: token.sourceSpan,
parts: [text]
};
}
}
while (this._peek.type === 8 || this._peek.type === 5 || this._peek.type === 9) {
token = this._advance();
tokens.push(token);
if (token.type === 8) {
text += token.parts.join('').replace(/&([^;]+);/g, decodeEntity);
} else if (token.type === 9) {
text += token.parts[0];
} else {
text += token.parts.join('');
}
}
if (text.length > 0) {
const endSpan = token.sourceSpan;
this._addToParent(new Text(text, new ParseSourceSpan(startSpan.start, endSpan.end, startSpan.fullStart, startSpan.details), tokens));
}
}
_closeVoidElement() {
const el = this._getContainer();
if (el !== null && this._getTagDefinition(el)?.isVoid) {
this._containerStack.pop();
}
}
_consumeElementStartTag(startTagToken) {
const attrs = [];
const directives = [];
this._consumeAttributesAndDirectives(attrs, directives);
const fullName = this._getElementFullName(startTagToken, this._getClosestElementLikeParent());
const tagDef = this._getTagDefinition(fullName);
let selfClosing = false;
if (this._peek.type === 2) {
this._advance();
selfClosing = true;
if (!(tagDef?.canSelfClose || getNsPrefix(fullName) !== null || tagDef?.isVoid)) {
this.errors.push(TreeError.create(fullName, startTagToken.sourceSpan, `Only void, custom and foreign elements can be self closed "${startTagToken.parts[1]}"`));
}
} else if (this._peek.type === 1) {
this._advance();
selfClosing = false;
}
const end = this._peek.sourceSpan.fullStart;
const span = new ParseSourceSpan(startTagToken.sourceSpan.start, end, startTagToken.sourceSpan.fullStart);
const startSpan = new ParseSourceSpan(startTagToken.sourceSpan.start, end, startTagToken.sourceSpan.fullStart);
const el = new Element(fullName, attrs, directives, [], selfClosing, span, startSpan, undefined, tagDef?.isVoid ?? false);
const parent = this._getContainer();
const isClosedByChild = parent !== null && !!this._getTagDefinition(parent)?.isClosedByChild(el.name);
this._pushContainer(el, isClosedByChild);
if (selfClosing) {
this._popContainer(fullName, Element, span);
} else if (startTagToken.type === 4) {
this._popContainer(fullName, Element, null);
this.errors.push(TreeError.create(fullName, span, `Opening tag "${fullName}" not terminated.`));
}
}
_consumeComponentStartTag(startToken) {
const componentName = startToken.parts[0];
const attrs = [];
const directives = [];
this._consumeAttributesAndDirectives(attrs, directives);
const closestElement = this._getClosestElementLikeParent();
const tagName = this._getComponentTagName(startToken, closestElement);
const fullName = this._getComponentFullName(startToken, closestElement);
const selfClosing = this._peek.type === 35;
this._advance();
const end = this._peek.sourceSpan.fullStart;
const span = new ParseSourceSpan(startToken.sourceSpan.start, end, startToken.sourceSpan.fullStart);
const startSpan = new ParseSourceSpan(startToken.sourceSpan.start, end, startToken.sourceSpan.fullStart);
const node = new Component(componentName, tagName, fullName, attrs, directives, [], selfClosing, span, startSpan, undefined);
const parent = this._getContainer();
const isClosedByChild = parent !== null && node.tagName !== null && !!this._getTagDefinition(parent)?.isClosedByChild(node.tagName);
this._pushContainer(node, isClosedByChild);
if (selfClosing) {
this._popContainer(fullName, Component, span);
} else if (startToken.type === 37) {
this._popContainer(fullName, Component, null);
this.errors.push(TreeError.create(fullName, span, `Opening tag "${fullName}" not terminated.`));
}
}
_consumeAttributesAndDirectives(attributesResult, directivesResult) {
while (this._peek.type === 14 || this._peek.type === 38) {
if (this._peek.type === 38) {
directivesResult.push(this._consumeDirective(this._peek));
} else {
attributesResult.push(this._consumeAttr(this._advance()));
}
}
}
_consumeComponentEndTag(endToken) {
const fullName = this._getComponentFullName(endToken, this._getClosestElementLikeParent());
if (!this._popContainer(fullName, Component, endToken.sourceSpan)) {
const container = this._containerStack[this._containerStack.length - 1];
let suffix;
if (container instanceof Component && container.componentName === endToken.parts[0]) {
suffix = `, did you mean "${container.fullName}"?`;
} else {
suffix = '. It may happen when the tag has already been closed by another tag.';
}
const errMsg = `Unexpected closing tag "${fullName}"${suffix}`;
this.errors.push(TreeError.create(fullName, endToken.sourceSpan, errMsg));
}
}
_getTagDefinition(nodeOrName) {
if (typeof nodeOrName === 'string') {
return this.tagDefinitionResolver(nodeOrName);
} else if (nodeOrName instanceof Element) {
return this.tagDefinitionResolver(nodeOrName.name);
} else if (nodeOrName instanceof Component && nodeOrName.tagName !== null) {
return this.tagDefinitionResolver(nodeOrName.tagName);
} else {
return null;
}
}
_pushContainer(node, isClosedByChild) {
if (isClosedByChild) {
this._containerStack.pop();
}
this._addToParent(node);
this._containerStack.push(node);
}
_consumeElementEndTag(endTagToken) {
const fullName = this._getElementFullName(endTagToken, this._getClosestElementLikeParent());
if (this._getTagDefinition(fullName)?.isVoid) {
this.errors.push(TreeError.create(fullName, endTagToken.sourceSpan, `Void elements do not have end tags "${endTagToken.parts[1]}"`));
} else if (!this._popContainer(fullName, Element, endTagToken.sourceSpan)) {
const errMsg = `Unexpected closing tag "${fullName}". It may happen when the tag has already been closed by another tag. For more info see https://www.w3.org/TR/html5/syntax.html#closing-elements-that-have-implied-end-tags`;
this.errors.push(TreeError.create(fullName, endTagToken.sourceSpan, errMsg));
}
}
_popContainer(expectedName, expectedType, endSourceSpan) {
let unexpectedCloseTagDetected = false;
for (let stackIndex = this._containerStack.length - 1; stackIndex >= 0; stackIndex--) {
const node = this._containerStack[stackIndex];
const nodeName = node instanceof Component ? node.fullName : node.name;
if ((nodeName === expectedName || expectedName === null) && node instanceof expectedType) {
node.endSourceSpan = endSourceSpan;
node.sourceSpan.end = endSourceSpan !== null ? endSourceSpan.end : node.sourceSpan.end;
this._containerStack.splice(stackIndex, this._containerStack.length - stackIndex);
return !unexpectedCloseTagDetected;
}
if (node instanceof Block || !this._getTagDefinition(node)?.closedByParent) {
unexpectedCloseTagDetected = true;
}
}
return false;
}
_consumeAttr(attrName) {
const fullName = mergeNsAndName(attrName.parts[0], attrName.parts[1]);
let attrEnd = attrName.sourceSpan.end;
if (this._peek.type === 15) {
this._advance();
}
let value = '';
const valueTokens = [];
let valueStartSpan = undefined;
let valueEnd = undefined;
const nextTokenType = this._peek.type;
if (nextTokenType === 16) {
valueStartSpan = this._peek.sourceSpan;
valueEnd = this._peek.sourceSpan.end;
while (this._peek.type === 16 || this._peek.type === 17 || this._peek.type === 9) {
const valueToken = this._advance();
valueTokens.push(valueToken);
if (valueToken.type === 17) {
value += valueToken.parts.join('').replace(/&([^;]+);/g, decodeEntity);
} else if (valueToken.type === 9) {
value += valueToken.parts[0];
} else {
value += valueToken.parts.join('');
}
valueEnd = attrEnd = valueToken.sourceSpan.end;
}
}
if (this._peek.type === 15) {
const quoteToken = this._advance();
attrEnd = quoteToken.sourceSpan.end;
}
const valueSpan = valueStartSpan && valueEnd && new ParseSourceSpan(valueStartSpan.start, valueEnd, valueStartSpan.fullStart);
return new Attribute(fullName, value, new ParseSourceSpan(attrName.sourceSpan.start, attrEnd, attrName.sourceSpan.fullStart), attrName.sourceSpan, valueSpan, valueTokens.length > 0 ? valueTokens : undefined, undefined);
}
_consumeDirective(nameToken) {
const attributes = [];
let startSourceSpanEnd = nameToken.sourceSpan.end;
let endSourceSpan = null;
this._advance();
if (this._peek.type === 39) {
startSourceSpanEnd = this._peek.sourceSpan.end;
this._advance();
while (this._peek.type === 14) {
attributes.push(this._consumeAttr(this._advance()));
}
if (this._peek.type === 40) {
endSourceSpan = this._peek.sourceSpan;
this._advance();
} else {
this.errors.push(TreeError.create(null, nameToken.sourceSpan, 'Unterminated directive definition'));
}
}
const startSourceSpan = new ParseSourceSpan(nameToken.sourceSpan.start, startSourceSpanEnd, nameToken.sourceSpan.fullStart);
const sourceSpan = new ParseSourceSpan(startSourceSpan.start, endSourceSpan === null ? nameToken.sourceSpan.end : endSourceSpan.end, startSourceSpan.fullStart);
return new Directive(nameToken.parts[0], attributes, sourceSpan, startSourceSpan, endSourceSpan);
}
_consumeBlockOpen(token) {
const parameters = [];
while (this._peek.type === 27) {
const paramToken = this._advance();
parameters.push(new BlockParameter(paramToken.parts[0], paramToken.sourceSpan));
}
if (this._peek.type === 25) {
this._advance();
}
const end = this._peek.sourceSpan.fullStart;
const span = new ParseSourceSpan(token.sourceSpan.start, end, token.sourceSpan.fullStart);
const startSpan = new ParseSourceSpan(token.sourceSpan.start, end, token.sourceSpan.fullStart);
const block = new Block(token.parts[0], parameters, [], span, token.sourceSpan, startSpan);
this._pushContainer(block, false);
}
_consumeBlockClose(token) {
if (!this._popContainer(null, Block, token.sourceSpan)) {
this.errors.push(TreeError.create(null, token.sourceSpan, `Unexpected closing block. The block may have been closed earlier. ` + `If you meant to write the } character, you should use the "&#125;" ` + `HTML entity instead.`));
}
}
_consumeIncompleteBlock(token) {
const parameters = [];
while (this._peek.type === 27) {
const paramToken = this._advance();
parameters.push(new BlockParameter(paramToken.parts[0], paramToken.sourceSpan));
}
const end = this._peek.sourceSpan.fullStart;
const span = new ParseSourceSpan(token.sourceSpan.start, end, token.sourceSpan.fullStart);
const startSpan = new ParseSourceSpan(token.sourceSpan.start, end, token.sourceSpan.fullStart);
const block = new Block(token.parts[0], parameters, [], span, token.sourceSpan, startSpan);
this._pushContainer(block, false);
this._popContainer(null, Block, null);
this.errors.push(TreeError.create(token.parts[0], span, `Incomplete block "${token.parts[0]}". If you meant to write the @ character, ` + `you should use the "&#64;" HTML entity instead.`));
}
_consumeLet(startToken) {
const name = startToken.parts[0];
let valueToken;
let endToken;
if (this._peek.type !== 30) {
this.errors.push(TreeError.create(startToken.parts[0], startToken.sourceSpan, `Invalid @let declaration "${name}". Declaration must have a value.`));
return;
} else {
valueToken = this._advance();
}
if (this._peek.type !== 31) {
this.errors.push(TreeError.create(startToken.parts[0], startToken.sourceSpan, `Unterminated @let declaration "${name}". Declaration must be terminated with a semicolon.`));
return;
} else {
endToken = this._advance();
}
const end = endToken.sourceSpan.fullStart;
const span = new ParseSourceSpan(startToken.sourceSpan.start, end, startToken.sourceSpan.fullStart);
const startOffset = startToken.sourceSpan.toString().lastIndexOf(name);
const nameStart = startToken.sourceSpan.start.moveBy(startOffset);
const nameSpan = new ParseSourceSpan(nameStart, startToken.sourceSpan.end);
const node = new LetDeclaration(name, valueToken.parts[0], span, nameSpan, valueToken.sourceSpan);
this._addToParent(node);
}
_consumeIncompleteLet(token) {
const name = token.parts[0] ?? '';
const nameString = name ? ` "${name}"` : '';
if (name.length > 0) {
const startOffset = token.sourceSpan.toString().lastIndexOf(name);
const nameStart = token.sourceSpan.start.moveBy(startOffset);
const nameSpan = new ParseSourceSpan(nameStart, token.sourceSpan.end);
const valueSpan = new ParseSourceSpan(token.sourceSpan.start, token.sourceSpan.start.moveBy(0));
const node = new LetDeclaration(name, '', token.sourceSpan, nameSpan, valueSpan);
this._addToParent(node);
}
this.errors.push(TreeError.create(token.parts[0], token.sourceSpan, `Incomplete @let declaration${nameString}. ` + `@let declarations must be written as \`@let <name> = <value>;\``));
}
_getContainer() {
return this._containerStack.length > 0 ? this._containerStack[this._containerStack.length - 1] : null;
}
_getClosestElementLikeParent() {
for (let i = this._containerStack.length - 1; i > -1; i--) {
const current = this._containerStack[i];
if (current instanceof Element || current instanceof Component) {
return current;
}
}
return null;
}
_addToParent(node) {
const parent = this._getContainer();
if (parent === null) {
this.rootNodes.push(node);
} else {
parent.children.push(node);
}
}
_getElementFullName(token, parent) {
const prefix = this._getPrefix(token, parent);
return mergeNsAndName(prefix, token.parts[1]);
}
_getComponentFullName(token, parent) {
const componentName = token.parts[0];
const tagName = this._getComponentTagName(token, parent);
if (tagName === null) {
return componentName;
}
return tagName.startsWith(':') ? componentName + tagName : `${componentName}:${tagName}`;
}
_getComponentTagName(token, parent) {
const prefix = this._getPrefix(token, parent);
const tagName = token.parts[2];
if (!prefix && !tagName) {
return null;
} else if (!prefix && tagName) {
return tagName;
} else {
return mergeNsAndName(prefix, tagName || 'ng-component');
}
}
_getPrefix(token, parent) {
let prefix;
let tagName;
if (token.type === 33 || token.type === 37 || token.type === 36) {
prefix = token.parts[1];
tagName = token.parts[2];
} else {
prefix = token.parts[0];
tagName = token.parts[1];
}
prefix = prefix || this._getTagDefinition(tagName)?.implicitNamespacePrefix || '';
if (!prefix && parent) {
const parentName = parent instanceof Element ? parent.name : parent.tagName;
if (parentName !== null) {
const parentTagName = splitNsName(parentName)[1];
const parentTagDefinition = this._getTagDefinition(parentTagName);
if (parentTagDefinition !== null && !parentTagDefinition.preventNamespaceInheritance) {
prefix = getNsPrefix(parentName);
}
}
}
return prefix;
}
}
function lastOnStack(stack, element) {
return stack.length > 0 && stack[stack.length - 1] === element;
}
function decodeEntity(match, entity) {
if (NAMED_ENTITIES[entity] !== undefined) {
return NAMED_ENTITIES[entity] || match;
}
if (/^#x[a-f0-9]+$/i.test(entity)) {
return String.fromCodePoint(parseInt(entity.slice(2), 16));
}
if (/^#\d+$/.test(entity)) {
return String.fromCodePoint(parseInt(entity.slice(1), 10));
}
return match;
}
const PRESERVE_WS_ATTR_NAME = 'ngPreserveWhitespaces';
const SKIP_WS_TRIM_TAGS = new Set(['pre', 'template', 'textarea', 'script', 'style']);
const WS_CHARS = ' \f\n\r\t\v\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff';
const NO_WS_REGEXP = new RegExp(`[^${WS_CHARS}]`);
const WS_REPLACE_REGEXP = new RegExp(`[${WS_CHARS}]{2,}`, 'g');
function hasPreserveWhitespacesAttr(attrs) {
return attrs.some(attr => attr.name === PRESERVE_WS_ATTR_NAME);
}
function replaceNgsp(value) {
return value.replace(new RegExp(NGSP_UNICODE, 'g'), ' ');
}
class WhitespaceVisitor {
preserveSignificantWhitespace;
originalNodeMap;
requireContext;
icuExpansionDepth = 0;
constructor(preserveSignificantWhitespace, originalNodeMap, requireContext = true) {
this.preserveSignificantWhitespace = preserveSignificantWhitespace;
this.originalNodeMap = originalNodeMap;
this.requireContext = requireContext;
}
visitElement(element, context) {
if (SKIP_WS_TRIM_TAGS.has(element.name) || hasPreserveWhitespacesAttr(element.attrs)) {
const newElement = new Element(element.name, visitAllWithSiblings(this, element.attrs), visitAllWithSiblings(this, element.directives), element.children, element.isSelfClosing, element.sourceSpan, element.startSourceSpan, element.endSourceSpan, element.isVoid, element.i18n);
this.originalNodeMap?.set(newElement, element);
return newElement;
}
const newElement = new Element(element.name, element.attrs, element.directives, visitAllWithSiblings(this, element.children), element.isSelfClosing, element.sourceSpan, element.startSourceSpan, element.endSourceSpan, element.isVoid, element.i18n);
this.originalNodeMap?.set(newElement, element);
return newElement;
}
visitAttribute(attribute, context) {
return attribute.name !== PRESERVE_WS_ATTR_NAME ? attribute : null;
}
visitText(text, context) {
const isNotBlank = text.value.match(NO_WS_REGEXP);
const hasExpansionSibling = context && (context.prev instanceof Expansion || context.next instanceof Expansion);
const inIcuExpansion = this.icuExpansionDepth > 0;
if (inIcuExpansion && this.preserveSignificantWhitespace) return text;
if (isNotBlank || hasExpansionSibling) {
const tokens = text.tokens.map(token => token.type === 5 ? createWhitespaceProcessedTextToken(token) : token);
if (!this.preserveSignificantWhitespace && tokens.length > 0) {
const firstToken = tokens[0];
tokens.splice(0, 1, trimLeadingWhitespace(firstToken, context));
const lastToken = tokens[tokens.length - 1];
tokens.splice(tokens.length - 1, 1, trimTrailingWhitespace(lastToken, context));
}
const processed = processWhitespace(text.value);
const value = this.preserveSignificantWhitespace ? processed : trimLeadingAndTrailingWhitespace(processed, context);
const result = new Text(value, text.sourceSpan, tokens, text.i18n);
this.originalNodeMap?.set(result, text);
return result;
}
return null;
}
visitComment(comment, context) {
return comment;
}
visitExpansion(expansion, context) {
this.icuExpansionDepth++;
let newExpansion;
try {
newExpansion = new Expansion(expansion.switchValue, expansion.type, visitAllWithSiblings(this, expansion.cases), expansion.sourceSpan, expansion.switchValueSourceSpan, expansion.i18n);
} finally {
this.icuExpansionDepth--;
}
this.originalNodeMap?.set(newExpansion, expansion);
return newExpansion;
}
visitExpansionCase(expansionCase, context) {
const newExpansionCase = new ExpansionCase(expansionCase.value, visitAllWithSiblings(this, expansionCase.expression), expansionCase.sourceSpan, expansionCase.valueSourceSpan, expansionCase.expSourceSpan);
this.originalNodeMap?.set(newExpansionCase, expansionCase);
return newExpansionCase;
}
visitBlock(block, context) {
const newBlock = new Block(block.name, block.parameters, visitAllWithSiblings(this, block.children), block.sourceSpan, block.nameSpan, block.startSourceSpan, block.endSourceSpan);
this.originalNodeMap?.set(newBlock, block);
return newBlock;
}
visitBlockParameter(parameter, context) {
return parameter;
}
visitLetDeclaration(decl, context) {
return decl;
}
visitComponent(node, context) {
if (node.tagName && SKIP_WS_TRIM_TAGS.has(node.tagName) || hasPreserveWhitespacesAttr(node.attrs)) {
const newElement = new Component(node.componentName, node.tagName, node.fullName, visitAllWithSiblings(this, node.attrs), visitAllWithSiblings(this, node.directives), node.children, node.isSelfClosing, node.sourceSpan, node.startSourceSpan, node.endSourceSpan, node.i18n);
this.originalNodeMap?.set(newElement, node);
return newElement;
}
const newElement = new Component(node.componentName, node.tagName, node.fullName, node.attrs, node.directives, visitAllWithSiblings(this, node.children), node.isSelfClosing, node.sourceSpan, node.startSourceSpan, node.endSourceSpan, node.i18n);
this.originalNodeMap?.set(newElement, node);
return newElement;
}
visitDirective(directive, context) {
return directive;
}
visit(_node, context) {
if (this.requireContext && !context) {
throw new Error(`WhitespaceVisitor requires context. Visit via \`visitAllWithSiblings\` to get this context.`);
}
return false;
}
}
function trimLeadingWhitespace(token, context) {
if (token.type !== 5) return token;
const isFirstTokenInTag = !context?.prev;
if (!isFirstTokenInTag) return token;
return transformTextToken(token, text => text.trimStart());
}
function trimTrailingWhitespace(token, context) {
if (token.type !== 5) return token;
const isLastTokenInTag = !context?.next;
if (!isLastTokenInTag) return token;
return transformTextToken(token, text => text.trimEnd());
}
function trimLeadingAndTrailingWhitespace(text, context) {
const isFirstTokenInTag = !context?.prev;
const isLastTokenInTag = !context?.next;
const maybeTrimmedStart = isFirstTokenInTag ? text.trimStart() : text;
const maybeTrimmed = isLastTokenInTag ? maybeTrimmedStart.trimEnd() : maybeTrimmedStart;
return maybeTrimmed;
}
function createWhitespaceProcessedTextToken({
type,
parts,
sourceSpan
}) {
return {
type,
parts: [processWhitespace(parts[0])],
sourceSpan
};
}
function transformTextToken({
type,
parts,
sourceSpan
}, transform) {
return {
type,
parts: [transform(parts[0])],
sourceSpan
};
}
function processWhitespace(text) {
return replaceNgsp(text).replace(WS_REPLACE_REGEXP, ' ');
}
function visitAllWithSiblings(visitor, nodes) {
const result = [];
nodes.forEach((ast, i) => {
const context = {
prev: nodes[i - 1],
next: nodes[i + 1]
};
const astResult = ast.visit(visitor, context);
if (astResult) {
result.push(astResult);
}
});
return result;
}
var TokenType;
(function (TokenType) {
TokenType[TokenType["Character"] = 0] = "Character";
TokenType[TokenType["Identifier"] = 1] = "Identifier";
TokenType[TokenType["PrivateIdentifier"] = 2] = "PrivateIdentifier";
TokenType[TokenType["Keyword"] = 3] = "Keyword";
TokenType[TokenType["String"] = 4] = "String";
TokenType[TokenType["Operator"] = 5] = "Operator";
TokenType[TokenType["Number"] = 6] = "Number";
TokenType[TokenType["RegExpBody"] = 7] = "RegExpBody";
TokenType[TokenType["RegExpFlags"] = 8] = "RegExpFlags";
TokenType[TokenType["Error"] = 9] = "Error";
})(TokenType || (TokenType = {}));
var StringTokenKind;
(function (StringTokenKind) {
StringTokenKind[StringTokenKind["Plain"] = 0] = "Plain";
StringTokenKind[StringTokenKind["TemplateLiteralPart"] = 1] = "TemplateLiteralPart";
StringTokenKind[StringTokenKind["TemplateLiteralEnd"] = 2] = "TemplateLiteralEnd";
})(StringTokenKind || (StringTokenKind = {}));
const KEYWORDS = ['var', 'let', 'as', 'null', 'undefined', 'true', 'false', 'if', 'else', 'this', 'typeof', 'void', 'in'];
class Lexer {
tokenize(text) {
return new _Scanner(text).scan();
}
}
class Token {
index;
end;
type;
numValue;
strValue;
constructor(index, end, type, numValue, strValue) {
this.index = index;
this.end = end;
this.type = type;
this.numValue = numValue;
this.strValue = strValue;
}
isCharacter(code) {
return this.type === TokenType.Character && this.numValue === code;
}
isNumber() {
return this.type === TokenType.Number;
}
isString() {
return this.type === TokenType.String;
}
isOperator(operator) {
return this.type === TokenType.Operator && this.strValue === operator;
}
isIdentifier() {
return this.type === TokenType.Identifier;
}
isPrivateIdentifier() {
return this.type === TokenType.PrivateIdentifier;
}
isKeyword() {
return this.type === TokenType.Keyword;
}
isKeywordLet() {
return this.type === TokenType.Keyword && this.strValue === 'let';
}
isKeywordAs() {
return this.type === TokenType.Keyword && this.strValue === 'as';
}
isKeywordNull() {
return this.type === TokenType.Keyword && this.strValue === 'null';
}
isKeywordUndefined() {
return this.type === TokenType.Keyword && this.strValue === 'undefined';
}
isKeywordTrue() {
return this.type === TokenType.Keyword && this.strValue === 'true';
}
isKeywordFalse() {
return this.type === TokenType.Keyword && this.strValue === 'false';
}
isKeywordThis() {
return this.type === TokenType.Keyword && this.strValue === 'this';
}
isKeywordTypeof() {
return this.type === TokenType.Keyword && this.strValue === 'typeof';
}
isKeywordVoid() {
return this.type === TokenType.Keyword && this.strValue === 'void';
}
isKeywordIn() {
return this.type === TokenType.Keyword && this.strValue === 'in';
}
isError() {
return this.type === TokenType.Error;
}
isRegExpBody() {
return this.type === TokenType.RegExpBody;
}
isRegExpFlags() {
return this.type === TokenType.RegExpFlags;
}
toNumber() {
return this.type === TokenType.Number ? this.numValue : -1;
}
isTemplateLiteralPart() {
return this.isString() && this.kind === StringTokenKind.TemplateLiteralPart;
}
isTemplateLiteralEnd() {
return this.isString() && this.kind === StringTokenKind.TemplateLiteralEnd;
}
isTemplateLiteralInterpolationStart() {
return this.isOperator('${');
}
toString() {
switch (this.type) {
case TokenType.Character:
case TokenType.Identifier:
case TokenType.Keyword:
case TokenType.Operator:
case TokenType.PrivateIdentifier:
case TokenType.String:
case TokenType.Error:
case TokenType.RegExpBody:
case TokenType.RegExpFlags:
return this.strValue;
case TokenType.Number:
return this.numValue.toString();
default:
return null;
}
}
}
class StringToken extends Token {
kind;
constructor(index, end, strValue, kind) {
super(index, end, TokenType.String, 0, strValue);
this.kind = kind;
}
}
function newCharacterToken(index, end, code) {
return new Token(index, end, TokenType.Character, code, String.fromCharCode(code));
}
function newIdentifierToken(index, end, text) {
return new Token(index, end, TokenType.Identifier, 0, text);
}
function newPrivateIdentifierToken(index, end, text) {
return new Token(index, end, TokenType.PrivateIdentifier, 0, text);
}
function newKeywordToken(index, end, text) {
return new Token(index, end, TokenType.Keyword, 0, text);
}
function newOperatorToken(index, end, text) {
return new Token(index, end, TokenType.Operator, 0, text);
}
function newNumberToken(index, end, n) {
return new Token(index, end, TokenType.Number, n, '');
}
function newErrorToken(index, end, message) {
return new Token(index, end, TokenType.Error, 0, message);
}
function newRegExpBodyToken(index, end, text) {
return new Token(index, end, TokenType.RegExpBody, 0, text);
}
function newRegExpFlagsToken(index, end, text) {
return new Token(index, end, TokenType.RegExpFlags, 0, text);
}
const EOF = new Token(-1, -1, TokenType.Character, 0, '');
class _Scanner {
input;
tokens = [];
length;
peek = 0;
index = -1;
braceStack = [];
constructor(input) {
this.input = input;
this.length = input.length;
this.advance();
}
scan() {
let token = this.scanToken();
while (token !== null) {
this.tokens.push(token);
token = this.scanToken();
}
return this.tokens;
}
advance() {
this.peek = ++this.index >= this.length ? $EOF : this.input.charCodeAt(this.index);
}
scanToken() {
const input = this.input;
const length = this.length;
let peek = this.peek;
let index = this.index;
while (peek <= $SPACE) {
if (++index >= length) {
peek = $EOF;
break;
} else {
peek = input.charCodeAt(index);
}
}
this.peek = peek;
this.index = index;
if (index >= length) {
return null;
}
if (isIdentifierStart(peek)) {
return this.scanIdentifier();
}
if (isDigit(peek)) {
return this.scanNumber(index);
}
const start = index;
switch (peek) {
case $PERIOD:
this.advance();
if (isDigit(this.peek)) {
return this.scanNumber(start);
}
if (this.peek !== $PERIOD) {
return newCharacterToken(start, this.index, $PERIOD);
}
this.advance();
if (this.peek === $PERIOD) {
this.advance();
return newOperatorToken(start, this.index, '...');
}
return this.error(`Unexpected character [${String.fromCharCode(peek)}]`, 0);
case $LPAREN:
case $RPAREN:
case $LBRACKET:
case $RBRACKET:
case $COMMA:
case $COLON:
case $SEMICOLON:
return this.scanCharacter(start, peek);
case $LBRACE:
return this.scanOpenBrace(start, peek);
case $RBRACE:
return this.scanCloseBrace(start, peek);
case $SQ:
case $DQ:
return this.scanString();
case $BT:
this.advance();
return this.scanTemplateLiteralPart(start);
case $HASH:
return this.scanPrivateIdentifier();
case $PLUS:
return this.scanComplexOperator(start, '+', $EQ, '=');
case $MINUS:
return this.scanComplexOperator(start, '-', $EQ, '=');
case $SLASH:
return this.isStartOfRegex() ? this.scanRegex(index) : this.scanComplexOperator(start, '/', $EQ, '=');
case $PERCENT:
return this.scanComplexOperator(start, '%', $EQ, '=');
case $CARET:
return this.scanOperator(start, '^');
case $STAR:
return this.scanStar(start);
case $QUESTION:
return this.scanQuestion(start);
case $LT:
case $GT:
return this.scanComplexOperator(start, String.fromCharCode(peek), $EQ, '=');
case $BANG:
case $EQ:
return this.scanComplexOperator(start, String.fromCharCode(peek), $EQ, '=', $EQ, '=');
case $AMPERSAND:
return this.scanComplexOperator(start, '&', $AMPERSAND, '&', $EQ, '=');
case $BAR:
return this.scanComplexOperator(start, '|', $BAR, '|', $EQ, '=');
case $NBSP:
while (isWhitespace(this.peek)) this.advance();
return this.scanToken();
}
this.advance();
return this.error(`Unexpected character [${String.fromCharCode(peek)}]`, 0);
}
scanCharacter(start, code) {
this.advance();
return newCharacterToken(start, this.index, code);
}
scanOperator(start, str) {
this.advance();
return newOperatorToken(start, this.index, str);
}
scanOpenBrace(start, code) {
this.braceStack.push('expression');
this.advance();
return newCharacterToken(start, this.index, code);
}
scanCloseBrace(start, code) {
this.advance();
const currentBrace = this.braceStack.pop();
if (currentBrace === 'interpolation') {
this.tokens.push(newCharacterToken(start, this.index, $RBRACE));
return this.scanTemplateLiteralPart(this.index);
}
return newCharacterToken(start, this.index, code);
}
scanComplexOperator(start, one, twoCode, two, threeCode, three) {
this.advance();
let str = one;
if (this.peek == twoCode) {
this.advance();
str += two;
}
if (threeCode != null && this.peek == threeCode) {
this.advance();
str += three;
}
return newOperatorToken(start, this.index, str);
}
scanIdentifier() {
const start = this.index;
this.advance();
while (isIdentifierPart(this.peek)) this.advance();
const str = this.input.substring(start, this.index);
return KEYWORDS.indexOf(str) > -1 ? newKeywordToken(start, this.index, str) : newIdentifierToken(start, this.index, str);
}
scanPrivateIdentifier() {
const start = this.index;
this.advance();
if (!isIdentifierStart(this.peek)) {
return this.error('Invalid character [#]', -1);
}
while (isIdentifierPart(this.peek)) this.advance();
const identifierName = this.input.substring(start, this.index);
return newPrivateIdentifierToken(start, this.index, identifierName);
}
scanNumber(start) {
let simple = this.index === start;
let hasSeparators = false;
this.advance();
while (true) {
if (isDigit(this.peek)) ; else if (this.peek === $_) {
if (!isDigit(this.input.charCodeAt(this.index - 1)) || !isDigit(this.input.charCodeAt(this.index + 1))) {
return this.error('Invalid numeric separator', 0);
}
hasSeparators = true;
} else if (this.peek === $PERIOD) {
simple = false;
} else if (isExponentStart(this.peek)) {
this.advance();
if (isExponentSign(this.peek)) this.advance();
if (!isDigit(this.peek)) return this.error('Invalid exponent', -1);
simple = false;
} else {
break;
}
this.advance();
}
let str = this.input.substring(start, this.index);
if (hasSeparators) {
str = str.replace(/_/g, '');
}
const value = simple ? parseIntAutoRadix(str) : parseFloat(str);
return newNumberToken(start, this.index, value);
}
scanString() {
const start = this.index;
const quote = this.peek;
this.advance();
let buffer = '';
let marker = this.index;
const input = this.input;
while (this.peek != quote) {
if (this.peek == $BACKSLASH) {
const result = this.scanStringBackslash(buffer, marker);
if (typeof result !== 'string') {
return result;
}
buffer = result;
marker = this.index;
} else if (this.peek == $EOF) {
return this.error('Unterminated quote', 0);
} else {
this.advance();
}
}
const last = input.substring(marker, this.index);
this.advance();
return new StringToken(start, this.index, buffer + last, StringTokenKind.Plain);
}
scanQuestion(start) {
this.advance();
let operator = '?';
if (this.peek === $QUESTION) {
operator += '?';
this.advance();
if (this.peek === $EQ) {
operator += '=';
this.advance();
}
} else if (this.peek === $PERIOD) {
operator += '.';
this.advance();
}
return newOperatorToken(start, this.index, operator);
}
scanTemplateLiteralPart(start) {
let buffer = '';
let marker = this.index;
while (this.peek !== $BT) {
if (this.peek === $BACKSLASH) {
const result = this.scanStringBackslash(buffer, marker);
if (typeof result !== 'string') {
return result;
}
buffer = result;
marker = this.index;
} else if (this.peek === $$) {
const dollar = this.index;
this.advance();
if (this.peek === $LBRACE) {
this.braceStack.push('interpolation');
this.tokens.push(new StringToken(start, dollar, buffer + this.input.substring(marker, dollar), StringTokenKind.TemplateLiteralPart));
this.advance();
return newOperatorToken(dollar, this.index, this.input.substring(dollar, this.index));
}
} else if (this.peek === $EOF) {
return this.error('Unterminated template literal', 0);
} else {
this.advance();
}
}
const last = this.input.substring(marker, this.index);
this.advance();
return new StringToken(start, this.index, buffer + last, StringTokenKind.TemplateLiteralEnd);
}
error(message, offset) {
const position = this.index + offset;
return newErrorToken(position, this.index, `Lexer Error: ${message} at column ${position} in expression [${this.input}]`);
}
scanStringBackslash(buffer, marker) {
buffer += this.input.substring(marker, this.index);
let unescapedCode;
this.advance();
if (this.peek === $u) {
const hex = this.input.substring(this.index + 1, this.index + 5);
if (/^[0-9a-f]+$/i.test(hex)) {
unescapedCode = parseInt(hex, 16);
} else {
return this.error(`Invalid unicode escape [\\u${hex}]`, 0);
}
for (let i = 0; i < 5; i++) {
this.advance();
}
} else {
unescapedCode = unescape(this.peek);
this.advance();
}
buffer += String.fromCharCode(unescapedCode);
return buffer;
}
scanStar(start) {
this.advance();
let operator = '*';
if (this.peek === $STAR) {
operator += '*';
this.advance();
if (this.peek === $EQ) {
operator += '=';
this.advance();
}
} else if (this.peek === $EQ) {
operator += '=';
this.advance();
}
return newOperatorToken(start, this.index, operator);
}
isStartOfRegex() {
if (this.tokens.length === 0) {
return true;
}
const prevToken = this.tokens[this.tokens.length - 1];
if (prevToken.isOperator('!')) {
const beforePrevToken = this.tokens.length > 1 ? this.tokens[this.tokens.length - 2] : null;
const isNegation = beforePrevToken === null || beforePrevToken.type !== TokenType.Identifier && !beforePrevToken.isCharacter($RPAREN) && !beforePrevToken.isCharacter($RBRACKET);
return isNegation;
}
return prevToken.type === TokenType.Operator || prevToken.isCharacter($LPAREN) || prevToken.isCharacter($LBRACKET) || prevToken.isCharacter($COMMA) || prevToken.isCharacter($COLON);
}
scanRegex(tokenStart) {
this.advance();
const textStart = this.index;
let inEscape = false;
let inCharacterClass = false;
while (true) {
const peek = this.peek;
if (peek === $EOF) {
return this.error('Unterminated regular expression', 0);
}
if (inEscape) {
inEscape = false;
} else if (peek === $BACKSLASH) {
inEscape = true;
} else if (peek === $LBRACKET) {
inCharacterClass = true;
} else if (peek === $RBRACKET) {
inCharacterClass = false;
} else if (peek === $SLASH && !inCharacterClass) {
break;
}
this.advance();
}
const value = this.input.substring(textStart, this.index);
this.advance();
const bodyToken = newRegExpBodyToken(tokenStart, this.index, value);
const flagsToken = this.scanRegexFlags(this.index);
if (flagsToken !== null) {
this.tokens.push(bodyToken);
return flagsToken;
}
return bodyToken;
}
scanRegexFlags(start) {
if (!isAsciiLetter(this.peek)) {
return null;
}
while (isAsciiLetter(this.peek)) {
this.advance();
}
return newRegExpFlagsToken(start, this.index, this.input.substring(start, this.index));
}
}
function isIdentifierStart(code) {
return $a <= code && code <= $z || $A <= code && code <= $Z || code == $_ || code == $$;
}
function isIdentifierPart(code) {
return isAsciiLetter(code) || isDigit(code) || code == $_ || code == $$;
}
function isExponentStart(code) {
return code == $e || code == $E;
}
function isExponentSign(code) {
return code == $MINUS || code == $PLUS;
}
function unescape(code) {
switch (code) {
case $n:
return $LF;
case $f:
return $FF;
case $r:
return $CR;
case $t:
return $TAB;
case $v:
return $VTAB;
default:
return code;
}
}
function parseIntAutoRadix(text) {
const result = parseInt(text);
if (isNaN(result)) {
throw new Error('Invalid integer literal when parsing ' + text);
}
return result;
}
class SplitInterpolation {
strings;
expressions;
offsets;
constructor(strings, expressions, offsets) {
this.strings = strings;
this.expressions = expressions;
this.offsets = offsets;
}
}
class TemplateBindingParseResult {
templateBindings;
warnings;
errors;
constructor(templateBindings, warnings, errors) {
this.templateBindings = templateBindings;
this.warnings = warnings;
this.errors = errors;
}
}
function getLocation(span) {
return span.start.toString() || '(unknown)';
}
class Parser {
_lexer;
_supportsDirectPipeReferences;
constructor(_lexer, _supportsDirectPipeReferences = false) {
this._lexer = _lexer;
this._supportsDirectPipeReferences = _supportsDirectPipeReferences;
}
parseAction(input, parseSourceSpan, absoluteOffset) {
const errors = [];
this._checkNoInterpolation(errors, input, parseSourceSpan);
const {
stripped: sourceToLex
} = this._stripComments(input);
const tokens = this._lexer.tokenize(sourceToLex);
const ast = new _ParseAST(input, parseSourceSpan, absoluteOffset, tokens, 1, errors, 0, this._supportsDirectPipeReferences).parseChain();
return new ASTWithSource(ast, input, getLocation(parseSourceSpan), absoluteOffset, errors);
}
parseBinding(input, parseSourceSpan, absoluteOffset) {
const errors = [];
const ast = this._parseBindingAst(input, parseSourceSpan, absoluteOffset, errors);
return new ASTWithSource(ast, input, getLocation(parseSourceSpan), absoluteOffset, errors);
}
checkSimpleExpression(ast) {
const checker = new SimpleExpressionChecker();
ast.visit(checker);
return checker.errors;
}
parseSimpleBinding(input, parseSourceSpan, absoluteOffset) {
const errors = [];
const ast = this._parseBindingAst(input, parseSourceSpan, absoluteOffset, errors);
const simplExpressionErrors = this.checkSimpleExpression(ast);
if (simplExpressionErrors.length > 0) {
errors.push(getParseError(`Host binding expression cannot contain ${simplExpressionErrors.join(' ')}`, input, '', parseSourceSpan));
}
return new ASTWithSource(ast, input, getLocation(parseSourceSpan), absoluteOffset, errors);
}
_parseBindingAst(input, parseSourceSpan, absoluteOffset, errors) {
this._checkNoInterpolation(errors, input, parseSourceSpan);
const {
stripped: sourceToLex
} = this._stripComments(input);
const tokens = this._lexer.tokenize(sourceToLex);
return new _ParseAST(input, parseSourceSpan, absoluteOffset, tokens, 0, errors, 0, this._supportsDirectPipeReferences).parseChain();
}
parseTemplateBindings(templateKey, templateValue, parseSourceSpan, absoluteKeyOffset, absoluteValueOffset) {
const tokens = this._lexer.tokenize(templateValue);
const errors = [];
const parser = new _ParseAST(templateValue, parseSourceSpan, absoluteValueOffset, tokens, 0, errors, 0, this._supportsDirectPipeReferences);
return parser.parseTemplateBindings({
source: templateKey,
span: new AbsoluteSourceSpan(absoluteKeyOffset, absoluteKeyOffset + templateKey.length)
});
}
parseInterpolation(input, parseSourceSpan, absoluteOffset, interpolatedTokens) {
const errors = [];
const {
strings,
expressions,
offsets
} = this.splitInterpolation(input, parseSourceSpan, errors, interpolatedTokens);
if (expressions.length === 0) return null;
const expressionNodes = [];
for (let i = 0; i < expressions.length; ++i) {
const expressionSpan = interpolatedTokens?.[i * 2 + 1]?.sourceSpan;
const expressionText = expressions[i].text;
const {
stripped: sourceToLex,
hasComments
} = this._stripComments(expressionText);
const tokens = this._lexer.tokenize(sourceToLex);
if (hasComments && sourceToLex.trim().length === 0 && tokens.length === 0) {
errors.push(getParseError('Interpolation expression cannot only contain a comment', input, `at column ${expressions[i].start} in`, parseSourceSpan));
continue;
}
const ast = new _ParseAST(expressionSpan ? expressionText : input, expressionSpan || parseSourceSpan, absoluteOffset, tokens, 0, errors, offsets[i], this._supportsDirectPipeReferences).parseChain();
expressionNodes.push(ast);
}
return this.createInterpolationAst(strings.map(s => s.text), expressionNodes, input, getLocation(parseSourceSpan), absoluteOffset, errors);
}
parseInterpolationExpression(expression, parseSourceSpan, absoluteOffset) {
const {
stripped: sourceToLex
} = this._stripComments(expression);
const tokens = this._lexer.tokenize(sourceToLex);
const errors = [];
const ast = new _ParseAST(expression, parseSourceSpan, absoluteOffset, tokens, 0, errors, 0, this._supportsDirectPipeReferences).parseChain();
const strings = ['', ''];
return this.createInterpolationAst(strings, [ast], expression, getLocation(parseSourceSpan), absoluteOffset, errors);
}
createInterpolationAst(strings, expressions, input, location, absoluteOffset, errors) {
const span = new ParseSpan(0, input.length);
const interpolation = new Interpolation$1(span, span.toAbsolute(absoluteOffset), strings, expressions);
return new ASTWithSource(interpolation, input, location, absoluteOffset, errors);
}
splitInterpolation(input, parseSourceSpan, errors, interpolatedTokens) {
const strings = [];
const expressions = [];
const offsets = [];
const inputToTemplateIndexMap = interpolatedTokens ? getIndexMapForOriginalTemplate(interpolatedTokens) : null;
let i = 0;
let atInterpolation = false;
let extendLastString = false;
const interpStart = '{{';
const interpEnd = '}}';
while (i < input.length) {
if (!atInterpolation) {
const start = i;
i = input.indexOf(interpStart, i);
if (i === -1) {
i = input.length;
}
const text = input.substring(start, i);
strings.push({
text,
start,
end: i
});
atInterpolation = true;
} else {
const fullStart = i;
const exprStart = fullStart + interpStart.length;
const exprEnd = this._getInterpolationEndIndex(input, interpEnd, exprStart);
if (exprEnd === -1) {
atInterpolation = false;
extendLastString = true;
break;
}
const fullEnd = exprEnd + interpEnd.length;
const text = input.substring(exprStart, exprEnd);
if (text.trim().length === 0) {
errors.push(getParseError('Blank expressions are not allowed in interpolated strings', input, `at column ${i} in`, parseSourceSpan));
}
expressions.push({
text,
start: fullStart,
end: fullEnd
});
const startInOriginalTemplate = inputToTemplateIndexMap?.get(fullStart) ?? fullStart;
const offset = startInOriginalTemplate + interpStart.length;
offsets.push(offset);
i = fullEnd;
atInterpolation = false;
}
}
if (!atInterpolation) {
if (extendLastString) {
const piece = strings[strings.length - 1];
piece.text += input.substring(i);
piece.end = input.length;
} else {
strings.push({
text: input.substring(i),
start: i,
end: input.length
});
}
}
return new SplitInterpolation(strings, expressions, offsets);
}
wrapLiteralPrimitive(input, sourceSpanOrLocation, absoluteOffset) {
const span = new ParseSpan(0, input == null ? 0 : input.length);
return new ASTWithSource(new LiteralPrimitive(span, span.toAbsolute(absoluteOffset), input), input, typeof sourceSpanOrLocation === 'string' ? sourceSpanOrLocation : getLocation(sourceSpanOrLocation), absoluteOffset, []);
}
_stripComments(input) {
const i = this._commentStart(input);
return i != null ? {
stripped: input.substring(0, i),
hasComments: true
} : {
stripped: input,
hasComments: false
};
}
_commentStart(input) {
let outerQuote = null;
for (let i = 0; i < input.length - 1; i++) {
const char = input.charCodeAt(i);
const nextChar = input.charCodeAt(i + 1);
if (char === $SLASH && nextChar == $SLASH && outerQuote == null) return i;
if (outerQuote === char) {
outerQuote = null;
} else if (outerQuote == null && isQuote(char)) {
outerQuote = char;
}
}
return null;
}
_checkNoInterpolation(errors, input, parseSourceSpan) {
let startIndex = -1;
let endIndex = -1;
for (const charIndex of this._forEachUnquotedChar(input, 0)) {
if (startIndex === -1) {
if (input.startsWith('{{')) {
startIndex = charIndex;
}
} else {
endIndex = this._getInterpolationEndIndex(input, '}}', charIndex);
if (endIndex > -1) {
break;
}
}
}
if (startIndex > -1 && endIndex > -1) {
errors.push(getParseError(`Got interpolation ({{}}) where expression was expected`, input, `at column ${startIndex} in`, parseSourceSpan));
}
}
_getInterpolationEndIndex(input, expressionEnd, start) {
for (const charIndex of this._forEachUnquotedChar(input, start)) {
if (input.startsWith(expressionEnd, charIndex)) {
return charIndex;
}
if (input.startsWith('//', charIndex)) {
return input.indexOf(expressionEnd, charIndex);
}
}
return -1;
}
*_forEachUnquotedChar(input, start) {
let currentQuote = null;
let escapeCount = 0;
for (let i = start; i < input.length; i++) {
const char = input[i];
if (isQuote(input.charCodeAt(i)) && (currentQuote === null || currentQuote === char) && escapeCount % 2 === 0) {
currentQuote = currentQuote === null ? char : null;
} else if (currentQuote === null) {
yield i;
}
escapeCount = char === '\\' ? escapeCount + 1 : 0;
}
}
}
var ParseContextFlags;
(function (ParseContextFlags) {
ParseContextFlags[ParseContextFlags["None"] = 0] = "None";
ParseContextFlags[ParseContextFlags["Writable"] = 1] = "Writable";
})(ParseContextFlags || (ParseContextFlags = {}));
const SUPPORTED_REGEX_FLAGS = new Set(['d', 'g', 'i', 'm', 's', 'u', 'v', 'y']);
class _ParseAST {
input;
parseSourceSpan;
absoluteOffset;
tokens;
parseFlags;
errors;
offset;
supportsDirectPipeReferences;
rparensExpected = 0;
rbracketsExpected = 0;
rbracesExpected = 0;
context = ParseContextFlags.None;
sourceSpanCache = new Map();
index = 0;
constructor(input, parseSourceSpan, absoluteOffset, tokens, parseFlags, errors, offset, supportsDirectPipeReferences) {
this.input = input;
this.parseSourceSpan = parseSourceSpan;
this.absoluteOffset = absoluteOffset;
this.tokens = tokens;
this.parseFlags = parseFlags;
this.errors = errors;
this.offset = offset;
this.supportsDirectPipeReferences = supportsDirectPipeReferences;
}
peek(offset) {
const i = this.index + offset;
return i < this.tokens.length ? this.tokens[i] : EOF;
}
get next() {
return this.peek(0);
}
get atEOF() {
return this.index >= this.tokens.length;
}
get inputIndex() {
return this.atEOF ? this.currentEndIndex : this.next.index + this.offset;
}
get currentEndIndex() {
if (this.index > 0) {
const curToken = this.peek(-1);
return curToken.end + this.offset;
}
if (this.tokens.length === 0) {
return this.input.length + this.offset;
}
return this.next.index + this.offset;
}
get currentAbsoluteOffset() {
return this.absoluteOffset + this.inputIndex;
}
span(start, artificialEndIndex) {
let endIndex = this.currentEndIndex;
if (artificialEndIndex !== undefined && artificialEndIndex > this.currentEndIndex) {
endIndex = artificialEndIndex;
}
if (start > endIndex) {
const tmp = endIndex;
endIndex = start;
start = tmp;
}
return new ParseSpan(start, endIndex);
}
sourceSpan(start, artificialEndIndex) {
const serial = `${start}@${this.inputIndex}:${artificialEndIndex}`;
if (!this.sourceSpanCache.has(serial)) {
this.sourceSpanCache.set(serial, this.span(start, artificialEndIndex).toAbsolute(this.absoluteOffset));
}
return this.sourceSpanCache.get(serial);
}
advance() {
this.index++;
}
withContext(context, cb) {
this.context |= context;
const ret = cb();
this.context ^= context;
return ret;
}
consumeOptionalCharacter(code) {
if (this.next.isCharacter(code)) {
this.advance();
return true;
} else {
return false;
}
}
peekKeywordLet() {
return this.next.isKeywordLet();
}
peekKeywordAs() {
return this.next.isKeywordAs();
}
expectCharacter(code) {
if (this.consumeOptionalCharacter(code)) return;
this.error(`Missing expected ${String.fromCharCode(code)}`);
}
consumeOptionalOperator(op) {
if (this.next.isOperator(op)) {
this.advance();
return true;
} else {
return false;
}
}
isAssignmentOperator(token) {
return token.type === TokenType.Operator && Binary.isAssignmentOperation(token.strValue);
}
expectOperator(operator) {
if (this.consumeOptionalOperator(operator)) return;
this.error(`Missing expected operator ${operator}`);
}
prettyPrintToken(tok) {
return tok === EOF ? 'end of input' : `token ${tok}`;
}
expectIdentifierOrKeyword() {
const n = this.next;
if (!n.isIdentifier() && !n.isKeyword()) {
if (n.isPrivateIdentifier()) {
this._reportErrorForPrivateIdentifier(n, 'expected identifier or keyword');
} else {
this.error(`Unexpected ${this.prettyPrintToken(n)}, expected identifier or keyword`);
}
return null;
}
this.advance();
return n.toString();
}
expectIdentifierOrKeywordOrString() {
const n = this.next;
if (!n.isIdentifier() && !n.isKeyword() && !n.isString()) {
if (n.isPrivateIdentifier()) {
this._reportErrorForPrivateIdentifier(n, 'expected identifier, keyword or string');
} else {
this.error(`Unexpected ${this.prettyPrintToken(n)}, expected identifier, keyword, or string`);
}
return '';
}
this.advance();
return n.toString();
}
parseChain() {
const exprs = [];
const start = this.inputIndex;
while (this.index < this.tokens.length) {
const expr = this.parsePipe();
exprs.push(expr);
if (this.consumeOptionalCharacter($SEMICOLON)) {
if (!(this.parseFlags & 1)) {
this.error('Binding expression cannot contain chained expression');
}
while (this.consumeOptionalCharacter($SEMICOLON)) {}
} else if (this.index < this.tokens.length) {
const errorIndex = this.index;
this.error(`Unexpected token '${this.next}'`);
if (this.index === errorIndex) {
break;
}
}
}
if (exprs.length === 0) {
const artificialStart = this.offset;
const artificialEnd = this.offset + this.input.length;
return new EmptyExpr$1(this.span(artificialStart, artificialEnd), this.sourceSpan(artificialStart, artificialEnd));
}
if (exprs.length == 1) return exprs[0];
return new Chain(this.span(start), this.sourceSpan(start), exprs);
}
parsePipe() {
const start = this.inputIndex;
let result = this.parseExpression();
if (this.consumeOptionalOperator('|')) {
if (this.parseFlags & 1) {
this.error(`Cannot have a pipe in an action expression`);
}
do {
const nameStart = this.inputIndex;
let nameId = this.expectIdentifierOrKeyword();
let nameSpan;
let fullSpanEnd = undefined;
if (nameId !== null) {
nameSpan = this.sourceSpan(nameStart);
} else {
nameId = '';
fullSpanEnd = this.next.index !== -1 ? this.next.index : this.input.length + this.offset;
nameSpan = new ParseSpan(fullSpanEnd, fullSpanEnd).toAbsolute(this.absoluteOffset);
}
const args = [];
while (this.consumeOptionalCharacter($COLON)) {
args.push(this.parseExpression());
}
let type;
if (this.supportsDirectPipeReferences) {
const charCode = nameId.charCodeAt(0);
type = charCode === $_ || charCode >= $A && charCode <= $Z ? BindingPipeType.ReferencedDirectly : BindingPipeType.ReferencedByName;
} else {
type = BindingPipeType.ReferencedByName;
}
result = new BindingPipe(this.span(start), this.sourceSpan(start, fullSpanEnd), result, nameId, args, type, nameSpan);
} while (this.consumeOptionalOperator('|'));
}
return result;
}
parseExpression() {
return this.parseConditional();
}
parseConditional() {
const start = this.inputIndex;
const result = this.parseLogicalOr();
if (this.consumeOptionalOperator('?')) {
const yes = this.parsePipe();
let no;
if (!this.consumeOptionalCharacter($COLON)) {
const end = this.inputIndex;
const expression = this.input.substring(start, end);
this.error(`Conditional expression ${expression} requires all 3 expressions`);
no = new EmptyExpr$1(this.span(start), this.sourceSpan(start));
} else {
no = this.parsePipe();
}
return new Conditional(this.span(start), this.sourceSpan(start), result, yes, no);
} else {
return result;
}
}
parseLogicalOr() {
const start = this.inputIndex;
let result = this.parseLogicalAnd();
while (this.consumeOptionalOperator('||')) {
const right = this.parseLogicalAnd();
result = new Binary(this.span(start), this.sourceSpan(start), '||', result, right);
}
return result;
}
parseLogicalAnd() {
const start = this.inputIndex;
let result = this.parseNullishCoalescing();
while (this.consumeOptionalOperator('&&')) {
const right = this.parseNullishCoalescing();
result = new Binary(this.span(start), this.sourceSpan(start), '&&', result, right);
}
return result;
}
parseNullishCoalescing() {
const start = this.inputIndex;
let result = this.parseEquality();
while (this.consumeOptionalOperator('??')) {
const right = this.parseEquality();
result = new Binary(this.span(start), this.sourceSpan(start), '??', result, right);
}
return result;
}
parseEquality() {
const start = this.inputIndex;
let result = this.parseRelational();
while (this.next.type == TokenType.Operator) {
const operator = this.next.strValue;
switch (operator) {
case '==':
case '===':
case '!=':
case '!==':
this.advance();
const right = this.parseRelational();
result = new Binary(this.span(start), this.sourceSpan(start), operator, result, right);
continue;
}
break;
}
return result;
}
parseRelational() {
const start = this.inputIndex;
let result = this.parseAdditive();
while (this.next.type == TokenType.Operator || this.next.isKeywordIn) {
const operator = this.next.strValue;
switch (operator) {
case '<':
case '>':
case '<=':
case '>=':
case 'in':
this.advance();
const right = this.parseAdditive();
result = new Binary(this.span(start), this.sourceSpan(start), operator, result, right);
continue;
}
break;
}
return result;
}
parseAdditive() {
const start = this.inputIndex;
let result = this.parseMultiplicative();
while (this.next.type == TokenType.Operator) {
const operator = this.next.strValue;
switch (operator) {
case '+':
case '-':
this.advance();
let right = this.parseMultiplicative();
result = new Binary(this.span(start), this.sourceSpan(start), operator, result, right);
continue;
}
break;
}
return result;
}
parseMultiplicative() {
const start = this.inputIndex;
let result = this.parseExponentiation();
while (this.next.type == TokenType.Operator) {
const operator = this.next.strValue;
switch (operator) {
case '*':
case '%':
case '/':
this.advance();
const right = this.parseExponentiation();
result = new Binary(this.span(start), this.sourceSpan(start), operator, result, right);
continue;
}
break;
}
return result;
}
parseExponentiation() {
const start = this.inputIndex;
let result = this.parsePrefix();
while (this.next.type == TokenType.Operator && this.next.strValue === '**') {
if (result instanceof Unary || result instanceof PrefixNot || result instanceof TypeofExpression || result instanceof VoidExpression) {
this.error('Unary operator used immediately before exponentiation expression. Parenthesis must be used to disambiguate operator precedence');
}
this.advance();
const right = this.parseExponentiation();
result = new Binary(this.span(start), this.sourceSpan(start), '**', result, right);
}
return result;
}
parsePrefix() {
if (this.next.type == TokenType.Operator) {
const start = this.inputIndex;
const operator = this.next.strValue;
let result;
switch (operator) {
case '+':
this.advance();
result = this.parsePrefix();
return Unary.createPlus(this.span(start), this.sourceSpan(start), result);
case '-':
this.advance();
result = this.parsePrefix();
return Unary.createMinus(this.span(start), this.sourceSpan(start), result);
case '!':
this.advance();
result = this.parsePrefix();
return new PrefixNot(this.span(start), this.sourceSpan(start), result);
}
} else if (this.next.isKeywordTypeof()) {
const start = this.inputIndex;
this.advance();
const result = this.parsePrefix();
return new TypeofExpression(this.span(start), this.sourceSpan(start), result);
} else if (this.next.isKeywordVoid()) {
const start = this.inputIndex;
this.advance();
const result = this.parsePrefix();
return new VoidExpression(this.span(start), this.sourceSpan(start), result);
}
return this.parseCallChain();
}
parseCallChain() {
const start = this.inputIndex;
let result = this.parsePrimary();
while (true) {
if (this.consumeOptionalCharacter($PERIOD)) {
result = this.parseAccessMember(result, start, false);
} else if (this.consumeOptionalOperator('?.')) {
if (this.consumeOptionalCharacter($LPAREN)) {
result = this.parseCall(result, start, true);
} else {
result = this.consumeOptionalCharacter($LBRACKET) ? this.parseKeyedReadOrWrite(result, start, true) : this.parseAccessMember(result, start, true);
}
} else if (this.consumeOptionalCharacter($LBRACKET)) {
result = this.parseKeyedReadOrWrite(result, start, false);
} else if (this.consumeOptionalCharacter($LPAREN)) {
result = this.parseCall(result, start, false);
} else if (this.consumeOptionalOperator('!')) {
result = new NonNullAssert(this.span(start), this.sourceSpan(start), result);
} else if (this.next.isTemplateLiteralEnd()) {
result = this.parseNoInterpolationTaggedTemplateLiteral(result, start);
} else if (this.next.isTemplateLiteralPart()) {
result = this.parseTaggedTemplateLiteral(result, start);
} else {
return result;
}
}
}
parsePrimary() {
const start = this.inputIndex;
if (this.consumeOptionalCharacter($LPAREN)) {
this.rparensExpected++;
const result = this.parsePipe();
if (!this.consumeOptionalCharacter($RPAREN)) {
this.error('Missing closing parentheses');
this.consumeOptionalCharacter($RPAREN);
}
this.rparensExpected--;
return new ParenthesizedExpression(this.span(start), this.sourceSpan(start), result);
} else if (this.next.isKeywordNull()) {
this.advance();
return new LiteralPrimitive(this.span(start), this.sourceSpan(start), null);
} else if (this.next.isKeywordUndefined()) {
this.advance();
return new LiteralPrimitive(this.span(start), this.sourceSpan(start), void 0);
} else if (this.next.isKeywordTrue()) {
this.advance();
return new LiteralPrimitive(this.span(start), this.sourceSpan(start), true);
} else if (this.next.isKeywordFalse()) {
this.advance();
return new LiteralPrimitive(this.span(start), this.sourceSpan(start), false);
} else if (this.next.isKeywordIn()) {
this.advance();
return new LiteralPrimitive(this.span(start), this.sourceSpan(start), 'in');
} else if (this.next.isKeywordThis()) {
this.advance();
return new ThisReceiver(this.span(start), this.sourceSpan(start));
} else if (this.consumeOptionalCharacter($LBRACKET)) {
return this.parseLiteralArray(start);
} else if (this.next.isCharacter($LBRACE)) {
return this.parseLiteralMap();
} else if (this.next.isIdentifier()) {
return this.parseAccessMember(new ImplicitReceiver(this.span(start), this.sourceSpan(start)), start, false);
} else if (this.next.isNumber()) {
const value = this.next.toNumber();
this.advance();
return new LiteralPrimitive(this.span(start), this.sourceSpan(start), value);
} else if (this.next.isTemplateLiteralEnd()) {
return this.parseNoInterpolationTemplateLiteral();
} else if (this.next.isTemplateLiteralPart()) {
return this.parseTemplateLiteral();
} else if (this.next.isString() && this.next.kind === StringTokenKind.Plain) {
const literalValue = this.next.toString();
this.advance();
return new LiteralPrimitive(this.span(start), this.sourceSpan(start), literalValue);
} else if (this.next.isPrivateIdentifier()) {
this._reportErrorForPrivateIdentifier(this.next, null);
return new EmptyExpr$1(this.span(start), this.sourceSpan(start));
} else if (this.next.isRegExpBody()) {
return this.parseRegularExpressionLiteral();
} else if (this.index >= this.tokens.length) {
this.error(`Unexpected end of expression: ${this.input}`);
return new EmptyExpr$1(this.span(start), this.sourceSpan(start));
} else {
this.error(`Unexpected token ${this.next}`);
return new EmptyExpr$1(this.span(start), this.sourceSpan(start));
}
}
parseLiteralArray(arrayStart) {
this.rbracketsExpected++;
const elements = [];
do {
if (this.next.isOperator('...')) {
elements.push(this.parseSpreadElement());
} else if (!this.next.isCharacter($RBRACKET)) {
elements.push(this.parsePipe());
} else {
break;
}
} while (this.consumeOptionalCharacter($COMMA));
this.rbracketsExpected--;
this.expectCharacter($RBRACKET);
return new LiteralArray(this.span(arrayStart), this.sourceSpan(arrayStart), elements);
}
parseLiteralMap() {
const keys = [];
const values = [];
const start = this.inputIndex;
this.expectCharacter($LBRACE);
if (!this.consumeOptionalCharacter($RBRACE)) {
this.rbracesExpected++;
do {
const keyStart = this.inputIndex;
if (this.next.isOperator('...')) {
this.advance();
keys.push({
kind: 'spread',
span: this.span(keyStart),
sourceSpan: this.sourceSpan(keyStart)
});
values.push(this.parsePipe());
continue;
}
const quoted = this.next.isString();
const key = this.expectIdentifierOrKeywordOrString();
const keySpan = this.span(keyStart);
const keySourceSpan = this.sourceSpan(keyStart);
const literalMapKey = {
kind: 'property',
key,
quoted,
span: keySpan,
sourceSpan: keySourceSpan
};
keys.push(literalMapKey);
if (quoted) {
this.expectCharacter($COLON);
values.push(this.parsePipe());
} else if (this.consumeOptionalCharacter($COLON)) {
values.push(this.parsePipe());
} else {
literalMapKey.isShorthandInitialized = true;
values.push(new PropertyRead(keySpan, keySourceSpan, keySourceSpan, new ImplicitReceiver(keySpan, keySourceSpan), key));
}
} while (this.consumeOptionalCharacter($COMMA) && !this.next.isCharacter($RBRACE));
this.rbracesExpected--;
this.expectCharacter($RBRACE);
}
return new LiteralMap(this.span(start), this.sourceSpan(start), keys, values);
}
parseAccessMember(readReceiver, start, isSafe) {
const nameStart = this.inputIndex;
const id = this.withContext(ParseContextFlags.Writable, () => {
const id = this.expectIdentifierOrKeyword() ?? '';
if (id.length === 0) {
this.error(`Expected identifier for property access`, readReceiver.span.end);
}
return id;
});
const nameSpan = this.sourceSpan(nameStart);
if (isSafe) {
if (this.isAssignmentOperator(this.next)) {
this.advance();
this.error("The '?.' operator cannot be used in the assignment");
return new EmptyExpr$1(this.span(start), this.sourceSpan(start));
} else {
return new SafePropertyRead(this.span(start), this.sourceSpan(start), nameSpan, readReceiver, id);
}
} else {
if (this.isAssignmentOperator(this.next)) {
const operation = this.next.strValue;
if (!(this.parseFlags & 1)) {
this.advance();
this.error('Bindings cannot contain assignments');
return new EmptyExpr$1(this.span(start), this.sourceSpan(start));
}
const receiver = new PropertyRead(this.span(start), this.sourceSpan(start), nameSpan, readReceiver, id);
this.advance();
const value = this.parseConditional();
return new Binary(this.span(start), this.sourceSpan(start), operation, receiver, value);
} else {
return new PropertyRead(this.span(start), this.sourceSpan(start), nameSpan, readReceiver, id);
}
}
}
parseCall(receiver, start, isSafe) {
const argumentStart = this.inputIndex;
this.rparensExpected++;
const args = this.parseCallArguments();
const argumentSpan = this.span(argumentStart, this.inputIndex).toAbsolute(this.absoluteOffset);
this.expectCharacter($RPAREN);
this.rparensExpected--;
const span = this.span(start);
const sourceSpan = this.sourceSpan(start);
return isSafe ? new SafeCall(span, sourceSpan, receiver, args, argumentSpan) : new Call(span, sourceSpan, receiver, args, argumentSpan);
}
parseCallArguments() {
if (this.next.isCharacter($RPAREN)) {
return [];
}
const positionals = [];
do {
positionals.push(this.next.isOperator('...') ? this.parseSpreadElement() : this.parsePipe());
} while (this.consumeOptionalCharacter($COMMA));
return positionals;
}
parseSpreadElement() {
if (!this.next.isOperator('...')) {
this.error("Spread element must start with '...' operator");
}
const spreadStart = this.inputIndex;
this.advance();
const expression = this.parsePipe();
const span = this.span(spreadStart);
const sourceSpan = this.sourceSpan(spreadStart);
return new SpreadElement(span, sourceSpan, expression);
}
expectTemplateBindingKey() {
let result = '';
let operatorFound = false;
const start = this.currentAbsoluteOffset;
do {
result += this.expectIdentifierOrKeywordOrString();
operatorFound = this.consumeOptionalOperator('-');
if (operatorFound) {
result += '-';
}
} while (operatorFound);
return {
source: result,
span: new AbsoluteSourceSpan(start, start + result.length)
};
}
parseTemplateBindings(templateKey) {
const bindings = [];
bindings.push(...this.parseDirectiveKeywordBindings(templateKey));
while (this.index < this.tokens.length) {
const letBinding = this.parseLetBinding();
if (letBinding) {
bindings.push(letBinding);
} else {
const key = this.expectTemplateBindingKey();
const binding = this.parseAsBinding(key);
if (binding) {
bindings.push(binding);
} else {
key.source = templateKey.source + key.source.charAt(0).toUpperCase() + key.source.substring(1);
bindings.push(...this.parseDirectiveKeywordBindings(key));
}
}
this.consumeStatementTerminator();
}
return new TemplateBindingParseResult(bindings, [], this.errors);
}
parseKeyedReadOrWrite(receiver, start, isSafe) {
return this.withContext(ParseContextFlags.Writable, () => {
this.rbracketsExpected++;
const key = this.parsePipe();
if (key instanceof EmptyExpr$1) {
this.error(`Key access cannot be empty`);
}
this.rbracketsExpected--;
this.expectCharacter($RBRACKET);
if (this.isAssignmentOperator(this.next)) {
const operation = this.next.strValue;
if (isSafe) {
this.advance();
this.error("The '?.' operator cannot be used in the assignment");
} else {
const binaryReceiver = new KeyedRead(this.span(start), this.sourceSpan(start), receiver, key);
this.advance();
const value = this.parseConditional();
return new Binary(this.span(start), this.sourceSpan(start), operation, binaryReceiver, value);
}
} else {
return isSafe ? new SafeKeyedRead(this.span(start), this.sourceSpan(start), receiver, key) : new KeyedRead(this.span(start), this.sourceSpan(start), receiver, key);
}
return new EmptyExpr$1(this.span(start), this.sourceSpan(start));
});
}
parseDirectiveKeywordBindings(key) {
const bindings = [];
this.consumeOptionalCharacter($COLON);
const value = this.getDirectiveBoundTarget();
let spanEnd = this.currentAbsoluteOffset;
const asBinding = this.parseAsBinding(key);
if (!asBinding) {
this.consumeStatementTerminator();
spanEnd = this.currentAbsoluteOffset;
}
const sourceSpan = new AbsoluteSourceSpan(key.span.start, spanEnd);
bindings.push(new ExpressionBinding(sourceSpan, key, value));
if (asBinding) {
bindings.push(asBinding);
}
return bindings;
}
getDirectiveBoundTarget() {
if (this.next === EOF || this.peekKeywordAs() || this.peekKeywordLet()) {
return null;
}
const ast = this.parsePipe();
const {
start,
end
} = ast.span;
const value = this.input.substring(start, end);
return new ASTWithSource(ast, value, getLocation(this.parseSourceSpan), this.absoluteOffset + start, this.errors);
}
parseAsBinding(value) {
if (!this.peekKeywordAs()) {
return null;
}
this.advance();
const key = this.expectTemplateBindingKey();
this.consumeStatementTerminator();
const sourceSpan = new AbsoluteSourceSpan(value.span.start, this.currentAbsoluteOffset);
return new VariableBinding(sourceSpan, key, value);
}
parseLetBinding() {
if (!this.peekKeywordLet()) {
return null;
}
const spanStart = this.currentAbsoluteOffset;
this.advance();
const key = this.expectTemplateBindingKey();
let value = null;
if (this.consumeOptionalOperator('=')) {
value = this.expectTemplateBindingKey();
}
this.consumeStatementTerminator();
const sourceSpan = new AbsoluteSourceSpan(spanStart, this.currentAbsoluteOffset);
return new VariableBinding(sourceSpan, key, value);
}
parseNoInterpolationTaggedTemplateLiteral(tag, start) {
const template = this.parseNoInterpolationTemplateLiteral();
return new TaggedTemplateLiteral(this.span(start), this.sourceSpan(start), tag, template);
}
parseNoInterpolationTemplateLiteral() {
const text = this.next.strValue;
const start = this.inputIndex;
this.advance();
const span = this.span(start);
const sourceSpan = this.sourceSpan(start);
return new TemplateLiteral(span, sourceSpan, [new TemplateLiteralElement(span, sourceSpan, text)], []);
}
parseTaggedTemplateLiteral(tag, start) {
const template = this.parseTemplateLiteral();
return new TaggedTemplateLiteral(this.span(start), this.sourceSpan(start), tag, template);
}
parseTemplateLiteral() {
const elements = [];
const expressions = [];
const start = this.inputIndex;
while (this.next !== EOF) {
const token = this.next;
if (token.isTemplateLiteralPart() || token.isTemplateLiteralEnd()) {
const partStart = this.inputIndex;
this.advance();
elements.push(new TemplateLiteralElement(this.span(partStart), this.sourceSpan(partStart), token.strValue));
if (token.isTemplateLiteralEnd()) {
break;
}
} else if (token.isTemplateLiteralInterpolationStart()) {
this.advance();
this.rbracesExpected++;
const expression = this.parsePipe();
if (expression instanceof EmptyExpr$1) {
this.error('Template literal interpolation cannot be empty');
} else {
expressions.push(expression);
}
this.rbracesExpected--;
} else {
this.advance();
}
}
return new TemplateLiteral(this.span(start), this.sourceSpan(start), elements, expressions);
}
parseRegularExpressionLiteral() {
const bodyToken = this.next;
this.advance();
if (!bodyToken.isRegExpBody()) {
return new EmptyExpr$1(this.span(this.inputIndex), this.sourceSpan(this.inputIndex));
}
let flagsToken = null;
if (this.next.isRegExpFlags()) {
flagsToken = this.next;
this.advance();
const seenFlags = new Set();
for (let i = 0; i < flagsToken.strValue.length; i++) {
const char = flagsToken.strValue[i];
if (!SUPPORTED_REGEX_FLAGS.has(char)) {
this.error(`Unsupported regular expression flag "${char}". The supported flags are: ` + Array.from(SUPPORTED_REGEX_FLAGS, f => `"${f}"`).join(', '), flagsToken.index + i);
} else if (seenFlags.has(char)) {
this.error(`Duplicate regular expression flag "${char}"`, flagsToken.index + i);
} else {
seenFlags.add(char);
}
}
}
const start = bodyToken.index;
const end = flagsToken ? flagsToken.end : bodyToken.end;
return new RegularExpressionLiteral(this.span(start, end), this.sourceSpan(start, end), bodyToken.strValue, flagsToken ? flagsToken.strValue : null);
}
consumeStatementTerminator() {
this.consumeOptionalCharacter($SEMICOLON) || this.consumeOptionalCharacter($COMMA);
}
error(message, index = this.index) {
this.errors.push(getParseError(message, this.input, this.getErrorLocationText(index), this.parseSourceSpan));
this.skip();
}
getErrorLocationText(index) {
return index < this.tokens.length ? `at column ${this.tokens[index].index + 1} in` : `at the end of the expression`;
}
_reportErrorForPrivateIdentifier(token, extraMessage) {
let errorMessage = `Private identifiers are not supported. Unexpected private identifier: ${token}`;
if (extraMessage !== null) {
errorMessage += `, ${extraMessage}`;
}
this.error(errorMessage);
}
skip() {
let n = this.next;
while (this.index < this.tokens.length && !n.isCharacter($SEMICOLON) && !n.isOperator('|') && (this.rparensExpected <= 0 || !n.isCharacter($RPAREN)) && (this.rbracesExpected <= 0 || !n.isCharacter($RBRACE)) && (this.rbracketsExpected <= 0 || !n.isCharacter($RBRACKET)) && (!(this.context & ParseContextFlags.Writable) || !this.isAssignmentOperator(n))) {
if (this.next.isError()) {
this.errors.push(getParseError(this.next.toString(), this.input, this.getErrorLocationText(this.next.index), this.parseSourceSpan));
}
this.advance();
n = this.next;
}
}
}
function getParseError(message, input, locationText, parseSourceSpan) {
if (locationText.length > 0) {
locationText = ` ${locationText} `;
}
const location = getLocation(parseSourceSpan);
const error = `Parser Error: ${message}${locationText}[${input}] in ${location}`;
return new ParseError(parseSourceSpan, error);
}
class SimpleExpressionChecker extends RecursiveAstVisitor {
errors = [];
visitPipe() {
this.errors.push('pipes');
}
}
function getIndexMapForOriginalTemplate(interpolatedTokens) {
let offsetMap = new Map();
let consumedInOriginalTemplate = 0;
let consumedInInput = 0;
let tokenIndex = 0;
while (tokenIndex < interpolatedTokens.length) {
const currentToken = interpolatedTokens[tokenIndex];
if (currentToken.type === 9) {
const [decoded, encoded] = currentToken.parts;
consumedInOriginalTemplate += encoded.length;
consumedInInput += decoded.length;
} else {
const lengthOfParts = currentToken.parts.reduce((sum, current) => sum + current.length, 0);
consumedInInput += lengthOfParts;
consumedInOriginalTemplate += lengthOfParts;
}
offsetMap.set(consumedInInput, consumedInOriginalTemplate);
tokenIndex++;
}
return offsetMap;
}
function serialize(expression) {
return expression.visit(new SerializeExpressionVisitor());
}
class SerializeExpressionVisitor {
visitUnary(ast, context) {
return `${ast.operator}${ast.expr.visit(this, context)}`;
}
visitBinary(ast, context) {
return `${ast.left.visit(this, context)} ${ast.operation} ${ast.right.visit(this, context)}`;
}
visitChain(ast, context) {
return ast.expressions.map(e => e.visit(this, context)).join('; ');
}
visitConditional(ast, context) {
return `${ast.condition.visit(this, context)} ? ${ast.trueExp.visit(this, context)} : ${ast.falseExp.visit(this, context)}`;
}
visitThisReceiver() {
return 'this';
}
visitImplicitReceiver() {
return '';
}
visitInterpolation(ast, context) {
return interleave(ast.strings, ast.expressions.map(e => e.visit(this, context))).join('');
}
visitKeyedRead(ast, context) {
return `${ast.receiver.visit(this, context)}[${ast.key.visit(this, context)}]`;
}
visitLiteralArray(ast, context) {
return `[${ast.expressions.map(e => e.visit(this, context)).join(', ')}]`;
}
visitLiteralMap(ast, context) {
return `{${zip(ast.keys.map(literal => {
if (literal.kind === 'spread') {
return '...';
}
return literal.quoted ? `'${literal.key}'` : literal.key;
}), ast.values.map(value => value.visit(this, context))).map(([key, value]) => `${key}: ${value}`).join(', ')}}`;
}
visitLiteralPrimitive(ast) {
if (ast.value === null) return 'null';
switch (typeof ast.value) {
case 'number':
case 'boolean':
return ast.value.toString();
case 'undefined':
return 'undefined';
case 'string':
return `'${ast.value.replace(/'/g, `\\'`)}'`;
default:
throw new Error(`Unsupported primitive type: ${ast.value}`);
}
}
visitPipe(ast, context) {
return `${ast.exp.visit(this, context)} | ${ast.name}`;
}
visitPrefixNot(ast, context) {
return `!${ast.expression.visit(this, context)}`;
}
visitNonNullAssert(ast, context) {
return `${ast.expression.visit(this, context)}!`;
}
visitPropertyRead(ast, context) {
if (ast.receiver instanceof ImplicitReceiver || ast.receiver instanceof ThisReceiver) {
return ast.name;
} else {
return `${ast.receiver.visit(this, context)}.${ast.name}`;
}
}
visitSafePropertyRead(ast, context) {
return `${ast.receiver.visit(this, context)}?.${ast.name}`;
}
visitSafeKeyedRead(ast, context) {
return `${ast.receiver.visit(this, context)}?.[${ast.key.visit(this, context)}]`;
}
visitCall(ast, context) {
return `${ast.receiver.visit(this, context)}(${ast.args.map(e => e.visit(this, context)).join(', ')})`;
}
visitSafeCall(ast, context) {
return `${ast.receiver.visit(this, context)}?.(${ast.args.map(e => e.visit(this, context)).join(', ')})`;
}
visitTypeofExpression(ast, context) {
return `typeof ${ast.expression.visit(this, context)}`;
}
visitVoidExpression(ast, context) {
return `void ${ast.expression.visit(this, context)}`;
}
visitRegularExpressionLiteral(ast, context) {
return `/${ast.body}/${ast.flags || ''}`;
}
visitASTWithSource(ast, context) {
return ast.ast.visit(this, context);
}
visitTemplateLiteral(ast, context) {
let result = '';
for (let i = 0; i < ast.elements.length; i++) {
result += ast.elements[i].visit(this, context);
const expression = i < ast.expressions.length ? ast.expressions[i] : null;
if (expression !== null) {
result += '${' + expression.visit(this, context) + '}';
}
}
return '`' + result + '`';
}
visitTemplateLiteralElement(ast, context) {
return ast.text;
}
visitTaggedTemplateLiteral(ast, context) {
return ast.tag.visit(this, context) + ast.template.visit(this, context);
}
visitSpreadElement(ast, context) {
return `...${ast.expression.visit(this, context)}`;
}
visitParenthesizedExpression(ast, context) {
return '(' + ast.expression.visit(this, context) + ')';
}
}
function zip(left, right) {
if (left.length !== right.length) throw new Error('Array lengths must match');
return left.map((l, i) => [l, right[i]]);
}
function interleave(left, right) {
const result = [];
for (let index = 0; index < Math.max(left.length, right.length); index++) {
if (index < left.length) result.push(left[index]);
if (index < right.length) result.push(right[index]);
}
return result;
}
let _SECURITY_SCHEMA;
function SECURITY_SCHEMA() {
if (!_SECURITY_SCHEMA) {
_SECURITY_SCHEMA = {};
registerContext(SecurityContext.HTML, ['iframe|srcdoc', '*|innerHTML', '*|outerHTML']);
registerContext(SecurityContext.STYLE, ['*|style']);
registerContext(SecurityContext.URL, ['*|formAction', 'area|href', 'a|href', 'a|xlink:href', 'form|action', 'annotation|href', 'annotation|xlink:href', 'annotation-xml|href', 'annotation-xml|xlink:href', 'maction|href', 'maction|xlink:href', 'malignmark|href', 'malignmark|xlink:href', 'math|href', 'math|xlink:href', 'mroot|href', 'mroot|xlink:href', 'msqrt|href', 'msqrt|xlink:href', 'merror|href', 'merror|xlink:href', 'mfrac|href', 'mfrac|xlink:href', 'mglyph|href', 'mglyph|xlink:href', 'msub|href', 'msub|xlink:href', 'msup|href', 'msup|xlink:href', 'msubsup|href', 'msubsup|xlink:href', 'mmultiscripts|href', 'mmultiscripts|xlink:href', 'mprescripts|href', 'mprescripts|xlink:href', 'mi|href', 'mi|xlink:href', 'mn|href', 'mn|xlink:href', 'mo|href', 'mo|xlink:href', 'mpadded|href', 'mpadded|xlink:href', 'mphantom|href', 'mphantom|xlink:href', 'mrow|href', 'mrow|xlink:href', 'ms|href', 'ms|xlink:href', 'mspace|href', 'mspace|xlink:href', 'mstyle|href', 'mstyle|xlink:href', 'mtable|href', 'mtable|xlink:href', 'mtd|href', 'mtd|xlink:href', 'mtr|href', 'mtr|xlink:href', 'mtext|href', 'mtext|xlink:href', 'mover|href', 'mover|xlink:href', 'munder|href', 'munder|xlink:href', 'munderover|href', 'munderover|xlink:href', 'semantics|href', 'semantics|xlink:href', 'none|href', 'none|xlink:href', 'img|src', 'video|src']);
registerContext(SecurityContext.RESOURCE_URL, ['base|href', 'embed|src', 'frame|src', 'iframe|src', 'link|href', 'object|codebase', 'object|data', 'script|src', 'script|href', 'script|xlink:href']);
registerContext(SecurityContext.ATTRIBUTE_NO_BINDING, ['animate|attributeName', 'set|attributeName', 'animateMotion|attributeName', 'animateTransform|attributeName', 'unknown|attributeName', 'iframe|sandbox', 'iframe|allow', 'iframe|allowFullscreen', 'iframe|referrerPolicy', 'iframe|csp', 'iframe|fetchPriority', 'unknown|sandbox', 'unknown|allow', 'unknown|allowFullscreen', 'unknown|referrerPolicy', 'unknown|csp', 'unknown|fetchPriority']);
}
return _SECURITY_SCHEMA;
}
function registerContext(ctx, specs) {
for (const spec of specs) _SECURITY_SCHEMA[spec.toLowerCase()] = ctx;
}
class ElementSchemaRegistry {}
const BOOLEAN = 'boolean';
const NUMBER = 'number';
const STRING = 'string';
const OBJECT = 'object';
const SCHEMA = ['[Element]|textContent,%ariaActiveDescendantElement,%ariaAtomic,%ariaAutoComplete,%ariaBusy,%ariaChecked,%ariaColCount,%ariaColIndex,%ariaColIndexText,%ariaColSpan,%ariaControlsElements,%ariaCurrent,%ariaDescribedByElements,%ariaDescription,%ariaDetailsElements,%ariaDisabled,%ariaErrorMessageElements,%ariaExpanded,%ariaFlowToElements,%ariaHasPopup,%ariaHidden,%ariaInvalid,%ariaKeyShortcuts,%ariaLabel,%ariaLabelledByElements,%ariaLevel,%ariaLive,%ariaModal,%ariaMultiLine,%ariaMultiSelectable,%ariaOrientation,%ariaOwnsElements,%ariaPlaceholder,%ariaPosInSet,%ariaPressed,%ariaReadOnly,%ariaRelevant,%ariaRequired,%ariaRoleDescription,%ariaRowCount,%ariaRowIndex,%ariaRowIndexText,%ariaRowSpan,%ariaSelected,%ariaSetSize,%ariaSort,%ariaValueMax,%ariaValueMin,%ariaValueNow,%ariaValueText,%classList,className,elementTiming,id,innerHTML,*beforecopy,*beforecut,*beforepaste,*fullscreenchange,*fullscreenerror,*search,*webkitfullscreenchange,*webkitfullscreenerror,outerHTML,%part,#scrollLeft,#scrollTop,slot' + ',*message,*mozfullscreenchange,*mozfullscreenerror,*mozpointerlockchange,*mozpointerlockerror,*webglcontextcreationerror,*webglcontextlost,*webglcontextrestored', '[HTMLElement]^[Element]|accessKey,autocapitalize,!autofocus,contentEditable,dir,!draggable,enterKeyHint,!hidden,!inert,innerText,inputMode,lang,nonce,*abort,*animationend,*animationiteration,*animationstart,*auxclick,*beforexrselect,*blur,*cancel,*canplay,*canplaythrough,*change,*click,*close,*contextmenu,*copy,*cuechange,*cut,*dblclick,*drag,*dragend,*dragenter,*dragleave,*dragover,*dragstart,*drop,*durationchange,*emptied,*ended,*error,*focus,*formdata,*gotpointercapture,*input,*invalid,*keydown,*keypress,*keyup,*load,*loadeddata,*loadedmetadata,*loadstart,*lostpointercapture,*mousedown,*mouseenter,*mouseleave,*mousemove,*mouseout,*mouseover,*mouseup,*mousewheel,*paste,*pause,*play,*playing,*pointercancel,*pointerdown,*pointerenter,*pointerleave,*pointermove,*pointerout,*pointerover,*pointerrawupdate,*pointerup,*progress,*ratechange,*reset,*resize,*scroll,*securitypolicyviolation,*seeked,*seeking,*select,*selectionchange,*selectstart,*slotchange,*stalled,*submit,*suspend,*timeupdate,*toggle,*transitioncancel,*transitionend,*transitionrun,*transitionstart,*volumechange,*waiting,*webkitanimationend,*webkitanimationiteration,*webkitanimationstart,*webkittransitionend,*wheel,outerText,!spellcheck,%style,#tabIndex,title,!translate,virtualKeyboardPolicy', 'abbr,address,article,aside,b,bdi,bdo,cite,content,code,dd,dfn,dt,em,figcaption,figure,footer,header,hgroup,i,kbd,main,mark,nav,noscript,rb,rp,rt,rtc,ruby,s,samp,search,section,small,strong,sub,sup,u,var,wbr^[HTMLElement]|accessKey,autocapitalize,!autofocus,contentEditable,dir,!draggable,enterKeyHint,!hidden,innerText,inputMode,lang,nonce,*abort,*animationend,*animationiteration,*animationstart,*auxclick,*beforexrselect,*blur,*cancel,*canplay,*canplaythrough,*change,*click,*close,*contextmenu,*copy,*cuechange,*cut,*dblclick,*drag,*dragend,*dragenter,*dragleave,*dragover,*dragstart,*drop,*durationchange,*emptied,*ended,*error,*focus,*formdata,*gotpointercapture,*input,*invalid,*keydown,*keypress,*keyup,*load,*loadeddata,*loadedmetadata,*loadstart,*lostpointercapture,*mousedown,*mouseenter,*mouseleave,*mousemove,*mouseout,*mouseover,*mouseup,*mousewheel,*paste,*pause,*play,*playing,*pointercancel,*pointerdown,*pointerenter,*pointerleave,*pointermove,*pointerout,*pointerover,*pointerrawupdate,*pointerup,*progress,*ratechange,*reset,*resize,*scroll,*securitypolicyviolation,*seeked,*seeking,*select,*selectionchange,*selectstart,*slotchange,*stalled,*submit,*suspend,*timeupdate,*toggle,*transitioncancel,*transitionend,*transitionrun,*transitionstart,*volumechange,*waiting,*webkitanimationend,*webkitanimationiteration,*webkitanimationstart,*webkittransitionend,*wheel,outerText,!spellcheck,%style,#tabIndex,title,!translate,virtualKeyboardPolicy', 'media^[HTMLElement]|!autoplay,!controls,%controlsList,%crossOrigin,#currentTime,!defaultMuted,#defaultPlaybackRate,!disableRemotePlayback,!loop,!muted,*encrypted,*waitingforkey,#playbackRate,preload,!preservesPitch,src,%srcObject,#volume', ':svg:^[HTMLElement]|!autofocus,nonce,*abort,*animationend,*animationiteration,*animationstart,*auxclick,*beforexrselect,*blur,*cancel,*canplay,*canplaythrough,*change,*click,*close,*contextmenu,*copy,*cuechange,*cut,*dblclick,*drag,*dragend,*dragenter,*dragleave,*dragover,*dragstart,*drop,*durationchange,*emptied,*ended,*error,*focus,*formdata,*gotpointercapture,*input,*invalid,*keydown,*keypress,*keyup,*load,*loadeddata,*loadedmetadata,*loadstart,*lostpointercapture,*mousedown,*mouseenter,*mouseleave,*mousemove,*mouseout,*mouseover,*mouseup,*mousewheel,*paste,*pause,*play,*playing,*pointercancel,*pointerdown,*pointerenter,*pointerleave,*pointermove,*pointerout,*pointerover,*pointerrawupdate,*pointerup,*progress,*ratechange,*reset,*resize,*scroll,*securitypolicyviolation,*seeked,*seeking,*select,*selectionchange,*selectstart,*slotchange,*stalled,*submit,*suspend,*timeupdate,*toggle,*transitioncancel,*transitionend,*transitionrun,*transitionstart,*volumechange,*waiting,*webkitanimationend,*webkitanimationiteration,*webkitanimationstart,*webkittransitionend,*wheel,%style,#tabIndex', ':svg:graphics^:svg:|', ':svg:animation^:svg:|*begin,*end,*repeat', ':svg:geometry^:svg:|', ':svg:componentTransferFunction^:svg:|', ':svg:gradient^:svg:|', ':svg:textContent^:svg:graphics|', ':svg:textPositioning^:svg:textContent|', 'a^[HTMLElement]|charset,coords,download,hash,host,hostname,href,hreflang,name,password,pathname,ping,port,protocol,referrerPolicy,rel,%relList,rev,search,shape,target,text,type,username', 'area^[HTMLElement]|alt,coords,download,hash,host,hostname,href,!noHref,password,pathname,ping,port,protocol,referrerPolicy,rel,%relList,search,shape,target,username', 'audio^media|', 'br^[HTMLElement]|clear', 'base^[HTMLElement]|href,target', 'body^[HTMLElement]|aLink,background,bgColor,link,*afterprint,*beforeprint,*beforeunload,*blur,*error,*focus,*hashchange,*languagechange,*load,*message,*messageerror,*offline,*online,*pagehide,*pageshow,*popstate,*rejectionhandled,*resize,*scroll,*storage,*unhandledrejection,*unload,text,vLink', 'button^[HTMLElement]|!disabled,formAction,formEnctype,formMethod,!formNoValidate,formTarget,name,type,value', 'canvas^[HTMLElement]|#height,#width', 'content^[HTMLElement]|select', 'dl^[HTMLElement]|!compact', 'data^[HTMLElement]|value', 'datalist^[HTMLElement]|', 'details^[HTMLElement]|!open', 'dialog^[HTMLElement]|!open,returnValue', 'dir^[HTMLElement]|!compact', 'div^[HTMLElement]|align', 'embed^[HTMLElement]|align,height,name,src,type,width', 'fieldset^[HTMLElement]|!disabled,name', 'font^[HTMLElement]|color,face,size', 'form^[HTMLElement]|acceptCharset,action,autocomplete,encoding,enctype,method,name,!noValidate,target', 'frame^[HTMLElement]|frameBorder,longDesc,marginHeight,marginWidth,name,!noResize,scrolling,src', 'frameset^[HTMLElement]|cols,*afterprint,*beforeprint,*beforeunload,*blur,*error,*focus,*hashchange,*languagechange,*load,*message,*messageerror,*offline,*online,*pagehide,*pageshow,*popstate,*rejectionhandled,*resize,*scroll,*storage,*unhandledrejection,*unload,rows', 'hr^[HTMLElement]|align,color,!noShade,size,width', 'head^[HTMLElement]|', 'h1,h2,h3,h4,h5,h6^[HTMLElement]|align', 'html^[HTMLElement]|version', 'iframe^[HTMLElement]|align,allow,!allowFullscreen,!allowPaymentRequest,csp,frameBorder,height,loading,longDesc,marginHeight,marginWidth,name,referrerPolicy,%sandbox,scrolling,src,srcdoc,width', 'img^[HTMLElement]|align,alt,border,%crossOrigin,decoding,#height,#hspace,!isMap,loading,longDesc,lowsrc,name,referrerPolicy,sizes,src,srcset,useMap,#vspace,#width', 'input^[HTMLElement]|accept,align,alt,autocomplete,!checked,!defaultChecked,defaultValue,dirName,!disabled,%files,formAction,formEnctype,formMethod,!formNoValidate,formTarget,#height,!incremental,!indeterminate,max,#maxLength,min,#minLength,!multiple,name,pattern,placeholder,!readOnly,!required,selectionDirection,#selectionEnd,#selectionStart,#size,src,step,type,useMap,value,%valueAsDate,#valueAsNumber,#width', 'li^[HTMLElement]|type,#value', 'label^[HTMLElement]|htmlFor', 'legend^[HTMLElement]|align', 'link^[HTMLElement]|as,charset,%crossOrigin,!disabled,href,hreflang,imageSizes,imageSrcset,integrity,media,referrerPolicy,rel,%relList,rev,%sizes,target,type', 'map^[HTMLElement]|name', 'marquee^[HTMLElement]|behavior,bgColor,direction,height,#hspace,#loop,#scrollAmount,#scrollDelay,!trueSpeed,#vspace,width', 'menu^[HTMLElement]|!compact', 'meta^[HTMLElement]|content,httpEquiv,media,name,scheme', 'meter^[HTMLElement]|#high,#low,#max,#min,#optimum,#value', 'ins,del^[HTMLElement]|cite,dateTime', 'ol^[HTMLElement]|!compact,!reversed,#start,type', 'object^[HTMLElement]|align,archive,border,code,codeBase,codeType,data,!declare,height,#hspace,name,standby,type,useMap,#vspace,width', 'optgroup^[HTMLElement]|!disabled,label', 'option^[HTMLElement]|!defaultSelected,!disabled,label,!selected,text,value', 'output^[HTMLElement]|defaultValue,%htmlFor,name,value', 'p^[HTMLElement]|align', 'param^[HTMLElement]|name,type,value,valueType', 'picture^[HTMLElement]|', 'pre^[HTMLElement]|#width', 'progress^[HTMLElement]|#max,#value', 'q,blockquote,cite^[HTMLElement]|', 'script^[HTMLElement]|!async,charset,%crossOrigin,!defer,event,htmlFor,integrity,!noModule,%referrerPolicy,src,text,type', 'select^[HTMLElement]|autocomplete,!disabled,#length,!multiple,name,!required,#selectedIndex,#size,value', 'selectedcontent^[HTMLElement]|', 'slot^[HTMLElement]|name', 'source^[HTMLElement]|#height,media,sizes,src,srcset,type,#width', 'span^[HTMLElement]|', 'style^[HTMLElement]|!disabled,media,type', 'search^[HTMLELement]|', 'caption^[HTMLElement]|align', 'th,td^[HTMLElement]|abbr,align,axis,bgColor,ch,chOff,#colSpan,headers,height,!noWrap,#rowSpan,scope,vAlign,width', 'col,colgroup^[HTMLElement]|align,ch,chOff,#span,vAlign,width', 'table^[HTMLElement]|align,bgColor,border,%caption,cellPadding,cellSpacing,frame,rules,summary,%tFoot,%tHead,width', 'tr^[HTMLElement]|align,bgColor,ch,chOff,vAlign', 'tfoot,thead,tbody^[HTMLElement]|align,ch,chOff,vAlign', 'template^[HTMLElement]|', 'textarea^[HTMLElement]|autocomplete,#cols,defaultValue,dirName,!disabled,#maxLength,#minLength,name,placeholder,!readOnly,!required,#rows,selectionDirection,#selectionEnd,#selectionStart,value,wrap', 'time^[HTMLElement]|dateTime', 'title^[HTMLElement]|text', 'track^[HTMLElement]|!default,kind,label,src,srclang', 'ul^[HTMLElement]|!compact,type', 'unknown^[HTMLElement]|', 'video^media|!disablePictureInPicture,#height,*enterpictureinpicture,*leavepictureinpicture,!playsInline,poster,#width', ':svg:a^:svg:graphics|', ':svg:animate^:svg:animation|', ':svg:animateMotion^:svg:animation|', ':svg:animateTransform^:svg:animation|', ':svg:circle^:svg:geometry|', ':svg:clipPath^:svg:graphics|', ':svg:defs^:svg:graphics|', ':svg:desc^:svg:|', ':svg:discard^:svg:|', ':svg:ellipse^:svg:geometry|', ':svg:feBlend^:svg:|', ':svg:feColorMatrix^:svg:|', ':svg:feComponentTransfer^:svg:|', ':svg:feComposite^:svg:|', ':svg:feConvolveMatrix^:svg:|', ':svg:feDiffuseLighting^:svg:|', ':svg:feDisplacementMap^:svg:|', ':svg:feDistantLight^:svg:|', ':svg:feDropShadow^:svg:|', ':svg:feFlood^:svg:|', ':svg:feFuncA^:svg:componentTransferFunction|', ':svg:feFuncB^:svg:componentTransferFunction|', ':svg:feFuncG^:svg:componentTransferFunction|', ':svg:feFuncR^:svg:componentTransferFunction|', ':svg:feGaussianBlur^:svg:|', ':svg:feImage^:svg:|', ':svg:feMerge^:svg:|', ':svg:feMergeNode^:svg:|', ':svg:feMorphology^:svg:|', ':svg:feOffset^:svg:|', ':svg:fePointLight^:svg:|', ':svg:feSpecularLighting^:svg:|', ':svg:feSpotLight^:svg:|', ':svg:feTile^:svg:|', ':svg:feTurbulence^:svg:|', ':svg:filter^:svg:|', ':svg:foreignObject^:svg:graphics|', ':svg:g^:svg:graphics|', ':svg:image^:svg:graphics|decoding', ':svg:line^:svg:geometry|', ':svg:linearGradient^:svg:gradient|', ':svg:mpath^:svg:|', ':svg:marker^:svg:|', ':svg:mask^:svg:|', ':svg:metadata^:svg:|', ':svg:path^:svg:geometry|', ':svg:pattern^:svg:|', ':svg:polygon^:svg:geometry|', ':svg:polyline^:svg:geometry|', ':svg:radialGradient^:svg:gradient|', ':svg:rect^:svg:geometry|', ':svg:svg^:svg:graphics|#currentScale,#zoomAndPan', ':svg:script^:svg:|type', ':svg:set^:svg:animation|', ':svg:stop^:svg:|', ':svg:style^:svg:|!disabled,media,title,type', ':svg:switch^:svg:graphics|', ':svg:symbol^:svg:|', ':svg:tspan^:svg:textPositioning|', ':svg:text^:svg:textPositioning|', ':svg:textPath^:svg:textContent|', ':svg:title^:svg:|', ':svg:use^:svg:graphics|', ':svg:view^:svg:|#zoomAndPan', 'data^[HTMLElement]|value', 'keygen^[HTMLElement]|!autofocus,challenge,!disabled,form,keytype,name', 'menuitem^[HTMLElement]|type,label,icon,!disabled,!checked,radiogroup,!default', 'summary^[HTMLElement]|', 'time^[HTMLElement]|dateTime', ':svg:cursor^:svg:|', ':math:^[HTMLElement]|!autofocus,nonce,*abort,*animationend,*animationiteration,*animationstart,*auxclick,*beforeinput,*beforematch,*beforetoggle,*beforexrselect,*blur,*cancel,*canplay,*canplaythrough,*change,*click,*close,*contentvisibilityautostatechange,*contextlost,*contextmenu,*contextrestored,*copy,*cuechange,*cut,*dblclick,*drag,*dragend,*dragenter,*dragleave,*dragover,*dragstart,*drop,*durationchange,*emptied,*ended,*error,*focus,*formdata,*gotpointercapture,*input,*invalid,*keydown,*keypress,*keyup,*load,*loadeddata,*loadedmetadata,*loadstart,*lostpointercapture,*mousedown,*mouseenter,*mouseleave,*mousemove,*mouseout,*mouseover,*mouseup,*mousewheel,*paste,*pause,*play,*playing,*pointercancel,*pointerdown,*pointerenter,*pointerleave,*pointermove,*pointerout,*pointerover,*pointerrawupdate,*pointerup,*progress,*ratechange,*reset,*resize,*scroll,*scrollend,*securitypolicyviolation,*seeked,*seeking,*select,*selectionchange,*selectstart,*slotchange,*stalled,*submit,*suspend,*timeupdate,*toggle,*transitioncancel,*transitionend,*transitionrun,*transitionstart,*volumechange,*waiting,*webkitanimationend,*webkitanimationiteration,*webkitanimationstart,*webkittransitionend,*wheel,%style,#tabIndex', ':math:math^:math:|', ':math:maction^:math:|', ':math:menclose^:math:|', ':math:merror^:math:|', ':math:mfenced^:math:|', ':math:mfrac^:math:|', ':math:mi^:math:|', ':math:mmultiscripts^:math:|', ':math:mn^:math:|', ':math:mo^:math:|', ':math:mover^:math:|', ':math:mpadded^:math:|', ':math:mphantom^:math:|', ':math:mroot^:math:|', ':math:mrow^:math:|', ':math:ms^:math:|', ':math:mspace^:math:|', ':math:msqrt^:math:|', ':math:mstyle^:math:|', ':math:msub^:math:|', ':math:msubsup^:math:|', ':math:msup^:math:|', ':math:mtable^:math:|', ':math:mtd^:math:|', ':math:mtext^:math:|', ':math:mtr^:math:|', ':math:munder^:math:|', ':math:munderover^:math:|', ':math:semantics^:math:|'];
const _ATTR_TO_PROP = new Map(Object.entries({
'class': 'className',
'for': 'htmlFor',
'formaction': 'formAction',
'innerHtml': 'innerHTML',
'readonly': 'readOnly',
'tabindex': 'tabIndex',
'aria-activedescendant': 'ariaActiveDescendantElement',
'aria-atomic': 'ariaAtomic',
'aria-autocomplete': 'ariaAutoComplete',
'aria-busy': 'ariaBusy',
'aria-checked': 'ariaChecked',
'aria-colcount': 'ariaColCount',
'aria-colindex': 'ariaColIndex',
'aria-colindextext': 'ariaColIndexText',
'aria-colspan': 'ariaColSpan',
'aria-controls': 'ariaControlsElements',
'aria-current': 'ariaCurrent',
'aria-describedby': 'ariaDescribedByElements',
'aria-description': 'ariaDescription',
'aria-details': 'ariaDetailsElements',
'aria-disabled': 'ariaDisabled',
'aria-errormessage': 'ariaErrorMessageElements',
'aria-expanded': 'ariaExpanded',
'aria-flowto': 'ariaFlowToElements',
'aria-haspopup': 'ariaHasPopup',
'aria-hidden': 'ariaHidden',
'aria-invalid': 'ariaInvalid',
'aria-keyshortcuts': 'ariaKeyShortcuts',
'aria-label': 'ariaLabel',
'aria-labelledby': 'ariaLabelledByElements',
'aria-level': 'ariaLevel',
'aria-live': 'ariaLive',
'aria-modal': 'ariaModal',
'aria-multiline': 'ariaMultiLine',
'aria-multiselectable': 'ariaMultiSelectable',
'aria-orientation': 'ariaOrientation',
'aria-owns': 'ariaOwnsElements',
'aria-placeholder': 'ariaPlaceholder',
'aria-posinset': 'ariaPosInSet',
'aria-pressed': 'ariaPressed',
'aria-readonly': 'ariaReadOnly',
'aria-required': 'ariaRequired',
'aria-roledescription': 'ariaRoleDescription',
'aria-rowcount': 'ariaRowCount',
'aria-rowindex': 'ariaRowIndex',
'aria-rowindextext': 'ariaRowIndexText',
'aria-rowspan': 'ariaRowSpan',
'aria-selected': 'ariaSelected',
'aria-setsize': 'ariaSetSize',
'aria-sort': 'ariaSort',
'aria-valuemax': 'ariaValueMax',
'aria-valuemin': 'ariaValueMin',
'aria-valuenow': 'ariaValueNow',
'aria-valuetext': 'ariaValueText'
}));
const _PROP_TO_ATTR = Array.from(_ATTR_TO_PROP).reduce((inverted, [propertyName, attributeName]) => {
inverted.set(propertyName, attributeName);
return inverted;
}, new Map());
class DomElementSchemaRegistry extends ElementSchemaRegistry {
_schema = new Map();
_eventSchema = new Map();
constructor() {
super();
SCHEMA.forEach(encodedType => {
const type = new Map();
const events = new Set();
const [strType, strProperties] = encodedType.split('|');
const properties = strProperties.split(',');
const [typeNames, superName] = strType.split('^');
typeNames.split(',').forEach(tag => {
this._schema.set(tag.toLowerCase(), type);
this._eventSchema.set(tag.toLowerCase(), events);
});
const superType = superName && this._schema.get(superName.toLowerCase());
if (superType) {
for (const [prop, value] of superType) {
type.set(prop, value);
}
for (const superEvent of this._eventSchema.get(superName.toLowerCase())) {
events.add(superEvent);
}
}
properties.forEach(property => {
if (property.length > 0) {
switch (property[0]) {
case '*':
events.add(property.substring(1));
break;
case '!':
type.set(property.substring(1), BOOLEAN);
break;
case '#':
type.set(property.substring(1), NUMBER);
break;
case '%':
type.set(property.substring(1), OBJECT);
break;
default:
type.set(property, STRING);
}
}
});
});
}
hasProperty(tagName, propName, schemaMetas) {
if (schemaMetas.some(schema => schema.name === NO_ERRORS_SCHEMA.name)) {
return true;
}
if (tagName.indexOf('-') > -1) {
if (isNgContainer(tagName) || isNgContent(tagName)) {
return false;
}
if (schemaMetas.some(schema => schema.name === CUSTOM_ELEMENTS_SCHEMA.name)) {
return true;
}
}
const elementProperties = this._schema.get(tagName.toLowerCase()) || this._schema.get('unknown');
return elementProperties.has(propName);
}
hasElement(tagName, schemaMetas) {
if (schemaMetas.some(schema => schema.name === NO_ERRORS_SCHEMA.name)) {
return true;
}
if (tagName.indexOf('-') > -1) {
if (isNgContainer(tagName) || isNgContent(tagName)) {
return true;
}
if (schemaMetas.some(schema => schema.name === CUSTOM_ELEMENTS_SCHEMA.name)) {
return true;
}
}
return this._schema.has(tagName.toLowerCase());
}
securityContext(tagName, propName, isAttribute) {
if (isAttribute) {
propName = this.getMappedPropName(propName);
}
tagName = tagName.toLowerCase();
propName = propName.toLowerCase();
let ctx = SECURITY_SCHEMA()[tagName + '|' + propName];
if (ctx) {
return ctx;
}
ctx = SECURITY_SCHEMA()['*|' + propName];
return ctx ? ctx : SecurityContext.NONE;
}
getMappedPropName(propName) {
return _ATTR_TO_PROP.get(propName) ?? propName;
}
getDefaultComponentElementName() {
return 'ng-component';
}
validateProperty(name) {
if (name.toLowerCase().startsWith('on')) {
const msg = `Binding to event property '${name}' is disallowed for security reasons, ` + `please use (${name.slice(2)})=...` + `\nIf '${name}' is a directive input, make sure the directive is imported by the` + ` current module.`;
return {
error: true,
msg: msg
};
} else {
return {
error: false
};
}
}
validateAttribute(name) {
if (name.toLowerCase().startsWith('on')) {
const msg = `Binding to event attribute '${name}' is disallowed for security reasons, ` + `please use (${name.slice(2)})=...`;
return {
error: true,
msg: msg
};
} else {
return {
error: false
};
}
}
allKnownElementNames() {
return Array.from(this._schema.keys());
}
allKnownAttributesOfElement(tagName) {
const elementProperties = this._schema.get(tagName.toLowerCase()) || this._schema.get('unknown');
return Array.from(elementProperties.keys()).map(prop => _PROP_TO_ATTR.get(prop) ?? prop);
}
allKnownEventsOfElement(tagName) {
return Array.from(this._eventSchema.get(tagName.toLowerCase()) ?? []);
}
normalizeAnimationStyleProperty(propName) {
return dashCaseToCamelCase(propName);
}
normalizeAnimationStyleValue(camelCaseProp, userProvidedProp, val) {
let unit = '';
const strVal = val.toString().trim();
let errorMsg = null;
if (_isPixelDimensionStyle(camelCaseProp) && val !== 0 && val !== '0') {
if (typeof val === 'number') {
unit = 'px';
} else {
const valAndSuffixMatch = val.match(/^[+-]?[\d\.]+([a-z]*)$/);
if (valAndSuffixMatch && valAndSuffixMatch[1].length == 0) {
errorMsg = `Please provide a CSS unit value for ${userProvidedProp}:${val}`;
}
}
}
return {
error: errorMsg,
value: strVal + unit
};
}
}
function _isPixelDimensionStyle(prop) {
switch (prop) {
case 'width':
case 'height':
case 'minWidth':
case 'minHeight':
case 'maxWidth':
case 'maxHeight':
case 'left':
case 'top':
case 'bottom':
case 'right':
case 'fontSize':
case 'outlineWidth':
case 'outlineOffset':
case 'paddingTop':
case 'paddingLeft':
case 'paddingBottom':
case 'paddingRight':
case 'marginTop':
case 'marginLeft':
case 'marginBottom':
case 'marginRight':
case 'borderRadius':
case 'borderWidth':
case 'borderTopWidth':
case 'borderLeftWidth':
case 'borderRightWidth':
case 'borderBottomWidth':
case 'textIndent':
return true;
default:
return false;
}
}
class HtmlTagDefinition {
closedByChildren = {};
contentType;
closedByParent = false;
implicitNamespacePrefix;
isVoid;
ignoreFirstLf;
canSelfClose;
preventNamespaceInheritance;
constructor({
closedByChildren,
implicitNamespacePrefix,
contentType = TagContentType.PARSABLE_DATA,
closedByParent = false,
isVoid = false,
ignoreFirstLf = false,
preventNamespaceInheritance = false,
canSelfClose = false
} = {}) {
if (closedByChildren && closedByChildren.length > 0) {
closedByChildren.forEach(tagName => this.closedByChildren[tagName] = true);
}
this.isVoid = isVoid;
this.closedByParent = closedByParent || isVoid;
this.implicitNamespacePrefix = implicitNamespacePrefix || null;
this.contentType = contentType;
this.ignoreFirstLf = ignoreFirstLf;
this.preventNamespaceInheritance = preventNamespaceInheritance;
this.canSelfClose = canSelfClose ?? isVoid;
}
isClosedByChild(name) {
return this.isVoid || name.toLowerCase() in this.closedByChildren;
}
getContentType(prefix) {
if (typeof this.contentType === 'object') {
const overrideType = prefix === undefined ? undefined : this.contentType[prefix];
return overrideType ?? this.contentType.default;
}
return this.contentType;
}
}
let DEFAULT_TAG_DEFINITION;
let TAG_DEFINITIONS;
function getHtmlTagDefinition(tagName) {
if (!TAG_DEFINITIONS) {
DEFAULT_TAG_DEFINITION = new HtmlTagDefinition({
canSelfClose: true
});
TAG_DEFINITIONS = Object.assign(Object.create(null), {
'base': new HtmlTagDefinition({
isVoid: true
}),
'meta': new HtmlTagDefinition({
isVoid: true
}),
'area': new HtmlTagDefinition({
isVoid: true
}),
'embed': new HtmlTagDefinition({
isVoid: true
}),
'link': new HtmlTagDefinition({
isVoid: true
}),
'img': new HtmlTagDefinition({
isVoid: true
}),
'input': new HtmlTagDefinition({
isVoid: true
}),
'param': new HtmlTagDefinition({
isVoid: true
}),
'hr': new HtmlTagDefinition({
isVoid: true
}),
'br': new HtmlTagDefinition({
isVoid: true
}),
'source': new HtmlTagDefinition({
isVoid: true
}),
'track': new HtmlTagDefinition({
isVoid: true
}),
'wbr': new HtmlTagDefinition({
isVoid: true
}),
'p': new HtmlTagDefinition({
closedByChildren: ['address', 'article', 'aside', 'blockquote', 'div', 'dl', 'fieldset', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'hgroup', 'hr', 'main', 'nav', 'ol', 'p', 'pre', 'section', 'table', 'ul'],
closedByParent: true
}),
'thead': new HtmlTagDefinition({
closedByChildren: ['tbody', 'tfoot']
}),
'tbody': new HtmlTagDefinition({
closedByChildren: ['tbody', 'tfoot'],
closedByParent: true
}),
'tfoot': new HtmlTagDefinition({
closedByChildren: ['tbody'],
closedByParent: true
}),
'tr': new HtmlTagDefinition({
closedByChildren: ['tr'],
closedByParent: true
}),
'td': new HtmlTagDefinition({
closedByChildren: ['td', 'th'],
closedByParent: true
}),
'th': new HtmlTagDefinition({
closedByChildren: ['td', 'th'],
closedByParent: true
}),
'col': new HtmlTagDefinition({
isVoid: true
}),
'svg': new HtmlTagDefinition({
implicitNamespacePrefix: 'svg'
}),
'foreignObject': new HtmlTagDefinition({
implicitNamespacePrefix: 'svg',
preventNamespaceInheritance: true
}),
'math': new HtmlTagDefinition({
implicitNamespacePrefix: 'math'
}),
'li': new HtmlTagDefinition({
closedByChildren: ['li'],
closedByParent: true
}),
'dt': new HtmlTagDefinition({
closedByChildren: ['dt', 'dd']
}),
'dd': new HtmlTagDefinition({
closedByChildren: ['dt', 'dd'],
closedByParent: true
}),
'rb': new HtmlTagDefinition({
closedByChildren: ['rb', 'rt', 'rtc', 'rp'],
closedByParent: true
}),
'rt': new HtmlTagDefinition({
closedByChildren: ['rb', 'rt', 'rtc', 'rp'],
closedByParent: true
}),
'rtc': new HtmlTagDefinition({
closedByChildren: ['rb', 'rtc', 'rp'],
closedByParent: true
}),
'rp': new HtmlTagDefinition({
closedByChildren: ['rb', 'rt', 'rtc', 'rp'],
closedByParent: true
}),
'optgroup': new HtmlTagDefinition({
closedByChildren: ['optgroup'],
closedByParent: true
}),
'option': new HtmlTagDefinition({
closedByChildren: ['option', 'optgroup'],
closedByParent: true
}),
'pre': new HtmlTagDefinition({
ignoreFirstLf: true
}),
'listing': new HtmlTagDefinition({
ignoreFirstLf: true
}),
'style': new HtmlTagDefinition({
contentType: TagContentType.RAW_TEXT
}),
'script': new HtmlTagDefinition({
contentType: TagContentType.RAW_TEXT
}),
'title': new HtmlTagDefinition({
contentType: {
default: TagContentType.ESCAPABLE_RAW_TEXT,
svg: TagContentType.PARSABLE_DATA
}
}),
'textarea': new HtmlTagDefinition({
contentType: TagContentType.ESCAPABLE_RAW_TEXT,
ignoreFirstLf: true
})
});
new DomElementSchemaRegistry().allKnownElementNames().forEach(knownTagName => {
if (!TAG_DEFINITIONS[knownTagName] && getNsPrefix(knownTagName) === null) {
TAG_DEFINITIONS[knownTagName] = new HtmlTagDefinition({
canSelfClose: false
});
}
});
}
return TAG_DEFINITIONS[tagName] ?? TAG_DEFINITIONS[tagName.toLowerCase()] ?? DEFAULT_TAG_DEFINITION;
}
const TAG_TO_PLACEHOLDER_NAMES = {
'A': 'LINK',
'B': 'BOLD_TEXT',
'BR': 'LINE_BREAK',
'EM': 'EMPHASISED_TEXT',
'H1': 'HEADING_LEVEL1',
'H2': 'HEADING_LEVEL2',
'H3': 'HEADING_LEVEL3',
'H4': 'HEADING_LEVEL4',
'H5': 'HEADING_LEVEL5',
'H6': 'HEADING_LEVEL6',
'HR': 'HORIZONTAL_RULE',
'I': 'ITALIC_TEXT',
'LI': 'LIST_ITEM',
'LINK': 'MEDIA_LINK',
'OL': 'ORDERED_LIST',
'P': 'PARAGRAPH',
'Q': 'QUOTATION',
'S': 'STRIKETHROUGH_TEXT',
'SMALL': 'SMALL_TEXT',
'SUB': 'SUBSTRIPT',
'SUP': 'SUPERSCRIPT',
'TBODY': 'TABLE_BODY',
'TD': 'TABLE_CELL',
'TFOOT': 'TABLE_FOOTER',
'TH': 'TABLE_HEADER_CELL',
'THEAD': 'TABLE_HEADER',
'TR': 'TABLE_ROW',
'TT': 'MONOSPACED_TEXT',
'U': 'UNDERLINED_TEXT',
'UL': 'UNORDERED_LIST'
};
class PlaceholderRegistry {
_placeHolderNameCounts = {};
_signatureToName = {};
getStartTagPlaceholderName(tag, attrs, isVoid) {
const signature = this._hashTag(tag, attrs, isVoid);
if (this._signatureToName[signature]) {
return this._signatureToName[signature];
}
const upperTag = tag.toUpperCase();
const baseName = TAG_TO_PLACEHOLDER_NAMES[upperTag] || `TAG_${upperTag}`;
const name = this._generateUniqueName(isVoid ? baseName : `START_${baseName}`);
this._signatureToName[signature] = name;
return name;
}
getCloseTagPlaceholderName(tag) {
const signature = this._hashClosingTag(tag);
if (this._signatureToName[signature]) {
return this._signatureToName[signature];
}
const upperTag = tag.toUpperCase();
const baseName = TAG_TO_PLACEHOLDER_NAMES[upperTag] || `TAG_${upperTag}`;
const name = this._generateUniqueName(`CLOSE_${baseName}`);
this._signatureToName[signature] = name;
return name;
}
getPlaceholderName(name, content) {
const upperName = name.toUpperCase();
const signature = `PH: ${upperName}=${content}`;
if (this._signatureToName[signature]) {
return this._signatureToName[signature];
}
const uniqueName = this._generateUniqueName(upperName);
this._signatureToName[signature] = uniqueName;
return uniqueName;
}
getUniquePlaceholder(name) {
return this._generateUniqueName(name.toUpperCase());
}
getStartBlockPlaceholderName(name, parameters) {
const signature = this._hashBlock(name, parameters);
if (this._signatureToName[signature]) {
return this._signatureToName[signature];
}
const placeholder = this._generateUniqueName(`START_BLOCK_${this._toSnakeCase(name)}`);
this._signatureToName[signature] = placeholder;
return placeholder;
}
getCloseBlockPlaceholderName(name) {
const signature = this._hashClosingBlock(name);
if (this._signatureToName[signature]) {
return this._signatureToName[signature];
}
const placeholder = this._generateUniqueName(`CLOSE_BLOCK_${this._toSnakeCase(name)}`);
this._signatureToName[signature] = placeholder;
return placeholder;
}
_hashTag(tag, attrs, isVoid) {
const start = `<${tag}`;
const strAttrs = Object.keys(attrs).sort().map(name => ` ${name}=${attrs[name]}`).join('');
const end = isVoid ? '/>' : `></${tag}>`;
return start + strAttrs + end;
}
_hashClosingTag(tag) {
return this._hashTag(`/${tag}`, {}, false);
}
_hashBlock(name, parameters) {
const params = parameters.length === 0 ? '' : ` (${parameters.sort().join('; ')})`;
return `@${name}${params} {}`;
}
_hashClosingBlock(name) {
return this._hashBlock(`close_${name}`, []);
}
_toSnakeCase(name) {
return name.toUpperCase().replace(/[^A-Z0-9]/g, '_');
}
_generateUniqueName(base) {
const seen = this._placeHolderNameCounts.hasOwnProperty(base);
if (!seen) {
this._placeHolderNameCounts[base] = 1;
return base;
}
const id = this._placeHolderNameCounts[base];
this._placeHolderNameCounts[base] = id + 1;
return `${base}_${id}`;
}
}
const _expParser = new Parser(new Lexer());
function createI18nMessageFactory(retainEmptyTokens, preserveExpressionWhitespace) {
const visitor = new _I18nVisitor(_expParser, retainEmptyTokens, preserveExpressionWhitespace);
return (nodes, meaning, description, customId, visitNodeFn) => visitor.toI18nMessage(nodes, meaning, description, customId, visitNodeFn);
}
function noopVisitNodeFn(_html, i18n) {
return i18n;
}
class _I18nVisitor {
_expressionParser;
_retainEmptyTokens;
_preserveExpressionWhitespace;
constructor(_expressionParser, _retainEmptyTokens, _preserveExpressionWhitespace) {
this._expressionParser = _expressionParser;
this._retainEmptyTokens = _retainEmptyTokens;
this._preserveExpressionWhitespace = _preserveExpressionWhitespace;
}
toI18nMessage(nodes, meaning = '', description = '', customId = '', visitNodeFn) {
const context = {
isIcu: nodes.length == 1 && nodes[0] instanceof Expansion,
icuDepth: 0,
placeholderRegistry: new PlaceholderRegistry(),
placeholderToContent: {},
placeholderToMessage: {},
visitNodeFn: visitNodeFn || noopVisitNodeFn
};
const i18nodes = visitAll(this, nodes, context);
return new Message(i18nodes, context.placeholderToContent, context.placeholderToMessage, meaning, description, customId);
}
visitElement(el, context) {
return this._visitElementLike(el, context);
}
visitComponent(component, context) {
return this._visitElementLike(component, context);
}
visitDirective(directive, context) {
throw new Error('Unreachable code');
}
visitAttribute(attribute, context) {
const node = attribute.valueTokens === undefined || attribute.valueTokens.length === 1 ? new Text$2(attribute.value, attribute.valueSpan || attribute.sourceSpan) : this._visitTextWithInterpolation(attribute.valueTokens, attribute.valueSpan || attribute.sourceSpan, context, attribute.i18n);
return context.visitNodeFn(attribute, node);
}
visitText(text, context) {
const node = text.tokens.length === 1 ? new Text$2(text.value, text.sourceSpan) : this._visitTextWithInterpolation(text.tokens, text.sourceSpan, context, text.i18n);
return context.visitNodeFn(text, node);
}
visitComment(comment, context) {
return null;
}
visitExpansion(icu, context) {
context.icuDepth++;
const i18nIcuCases = {};
const i18nIcu = new Icu(icu.switchValue, icu.type, i18nIcuCases, icu.sourceSpan);
icu.cases.forEach(caze => {
i18nIcuCases[caze.value] = new Container(caze.expression.map(node => node.visit(this, context)), caze.expSourceSpan);
});
context.icuDepth--;
if (context.isIcu || context.icuDepth > 0) {
const expPh = context.placeholderRegistry.getUniquePlaceholder(`VAR_${icu.type}`);
i18nIcu.expressionPlaceholder = expPh;
context.placeholderToContent[expPh] = {
text: icu.switchValue,
sourceSpan: icu.switchValueSourceSpan
};
return context.visitNodeFn(icu, i18nIcu);
}
const phName = context.placeholderRegistry.getPlaceholderName('ICU', icu.sourceSpan.toString());
context.placeholderToMessage[phName] = this.toI18nMessage([icu], '', '', '', undefined);
const node = new IcuPlaceholder(i18nIcu, phName, icu.sourceSpan);
return context.visitNodeFn(icu, node);
}
visitExpansionCase(_icuCase, _context) {
throw new Error('Unreachable code');
}
visitBlock(block, context) {
const children = visitAll(this, block.children, context);
if (block.name === 'switch') {
return new Container(children, block.sourceSpan);
}
const parameters = block.parameters.map(param => param.expression);
const startPhName = context.placeholderRegistry.getStartBlockPlaceholderName(block.name, parameters);
const closePhName = context.placeholderRegistry.getCloseBlockPlaceholderName(block.name);
context.placeholderToContent[startPhName] = {
text: block.startSourceSpan.toString(),
sourceSpan: block.startSourceSpan
};
context.placeholderToContent[closePhName] = {
text: block.endSourceSpan ? block.endSourceSpan.toString() : '}',
sourceSpan: block.endSourceSpan ?? block.sourceSpan
};
const node = new BlockPlaceholder(block.name, parameters, startPhName, closePhName, children, block.sourceSpan, block.startSourceSpan, block.endSourceSpan);
return context.visitNodeFn(block, node);
}
visitBlockParameter(_parameter, _context) {
throw new Error('Unreachable code');
}
visitLetDeclaration(decl, context) {
return null;
}
_visitElementLike(node, context) {
const children = visitAll(this, node.children, context);
const attrs = {};
const visitAttribute = attr => {
attrs[attr.name] = attr.value;
};
let nodeName;
let isVoid;
if (node instanceof Element) {
nodeName = node.name;
isVoid = getHtmlTagDefinition(node.name).isVoid;
} else {
nodeName = node.fullName;
isVoid = node.tagName ? getHtmlTagDefinition(node.tagName).isVoid : false;
}
node.attrs.forEach(visitAttribute);
node.directives.forEach(dir => dir.attrs.forEach(visitAttribute));
const startPhName = context.placeholderRegistry.getStartTagPlaceholderName(nodeName, attrs, isVoid);
context.placeholderToContent[startPhName] = {
text: node.startSourceSpan.toString(),
sourceSpan: node.startSourceSpan
};
let closePhName = '';
if (!isVoid) {
closePhName = context.placeholderRegistry.getCloseTagPlaceholderName(nodeName);
context.placeholderToContent[closePhName] = {
text: `</${nodeName}>`,
sourceSpan: node.endSourceSpan ?? node.sourceSpan
};
}
const i18nNode = new TagPlaceholder(nodeName, attrs, startPhName, closePhName, children, isVoid, node.sourceSpan, node.startSourceSpan, node.endSourceSpan);
return context.visitNodeFn(node, i18nNode);
}
_visitTextWithInterpolation(tokens, sourceSpan, context, previousI18n) {
const nodes = [];
let hasInterpolation = false;
for (const token of tokens) {
switch (token.type) {
case 8:
case 17:
hasInterpolation = true;
const [startMarker, expression, endMarker] = token.parts;
const baseName = extractPlaceholderName(expression) || 'INTERPOLATION';
const phName = context.placeholderRegistry.getPlaceholderName(baseName, expression);
if (this._preserveExpressionWhitespace) {
context.placeholderToContent[phName] = {
text: token.parts.join(''),
sourceSpan: token.sourceSpan
};
nodes.push(new Placeholder(expression, phName, token.sourceSpan));
} else {
const normalized = this.normalizeExpression(token);
context.placeholderToContent[phName] = {
text: `${startMarker}${normalized}${endMarker}`,
sourceSpan: token.sourceSpan
};
nodes.push(new Placeholder(normalized, phName, token.sourceSpan));
}
break;
default:
if (token.parts[0].length > 0 || this._retainEmptyTokens) {
const previous = nodes[nodes.length - 1];
if (previous instanceof Text$2) {
previous.value += token.parts[0];
previous.sourceSpan = new ParseSourceSpan(previous.sourceSpan.start, token.sourceSpan.end, previous.sourceSpan.fullStart, previous.sourceSpan.details);
} else {
nodes.push(new Text$2(token.parts[0], token.sourceSpan));
}
} else {
if (this._retainEmptyTokens) {
nodes.push(new Text$2(token.parts[0], token.sourceSpan));
}
}
break;
}
}
if (hasInterpolation) {
reusePreviousSourceSpans(nodes, previousI18n);
return new Container(nodes, sourceSpan);
} else {
return nodes[0];
}
}
normalizeExpression(token) {
const expression = token.parts[1];
const expr = this._expressionParser.parseBinding(expression, token.sourceSpan, token.sourceSpan.start.offset);
return serialize(expr);
}
}
function reusePreviousSourceSpans(nodes, previousI18n) {
if (previousI18n instanceof Message) {
assertSingleContainerMessage(previousI18n);
previousI18n = previousI18n.nodes[0];
}
if (previousI18n instanceof Container) {
assertEquivalentNodes(previousI18n.children, nodes);
for (let i = 0; i < nodes.length; i++) {
nodes[i].sourceSpan = previousI18n.children[i].sourceSpan;
}
}
}
function assertSingleContainerMessage(message) {
const nodes = message.nodes;
if (nodes.length !== 1 || !(nodes[0] instanceof Container)) {
throw new Error('Unexpected previous i18n message - expected it to consist of only a single `Container` node.');
}
}
function assertEquivalentNodes(previousNodes, nodes) {
if (previousNodes.length !== nodes.length) {
throw new Error(`
The number of i18n message children changed between first and second pass.
First pass (${previousNodes.length} tokens):
${previousNodes.map(node => `"${node.sourceSpan.toString()}"`).join('\n')}
Second pass (${nodes.length} tokens):
${nodes.map(node => `"${node.sourceSpan.toString()}"`).join('\n')}
`.trim());
}
if (previousNodes.some((node, i) => nodes[i].constructor !== node.constructor)) {
throw new Error('The types of the i18n message children changed between first and second pass.');
}
}
const _CUSTOM_PH_EXP = /\/\/[\s\S]*i18n[\s\S]*\([\s\S]*ph[\s\S]*=[\s\S]*("|')([\s\S]*?)\1[\s\S]*\)/g;
function extractPlaceholderName(input) {
return input.split(_CUSTOM_PH_EXP)[2];
}
const TRUSTED_TYPES_SINKS = new Set(['iframe|srcdoc', '*|innerhtml', '*|outerhtml', 'embed|src', 'object|codebase', 'object|data']);
function isTrustedTypesSink(tagName, propName) {
tagName = tagName.toLowerCase();
propName = propName.toLowerCase();
return TRUSTED_TYPES_SINKS.has(tagName + '|' + propName) || TRUSTED_TYPES_SINKS.has('*|' + propName);
}
const setI18nRefs = originalNodeMap => {
return (trimmedNode, i18nNode) => {
const originalNode = originalNodeMap.get(trimmedNode) ?? trimmedNode;
if (originalNode instanceof NodeWithI18n) {
if (i18nNode instanceof IcuPlaceholder && originalNode.i18n instanceof Message) {
i18nNode.previousMessage = originalNode.i18n;
}
originalNode.i18n = i18nNode;
}
return i18nNode;
};
};
class I18nMetaVisitor {
keepI18nAttrs;
enableI18nLegacyMessageIdFormat;
preserveSignificantWhitespace;
retainEmptyTokens;
hasI18nMeta = false;
_errors = [];
constructor(keepI18nAttrs = false, enableI18nLegacyMessageIdFormat = false, preserveSignificantWhitespace = true, retainEmptyTokens = !preserveSignificantWhitespace) {
this.keepI18nAttrs = keepI18nAttrs;
this.enableI18nLegacyMessageIdFormat = enableI18nLegacyMessageIdFormat;
this.preserveSignificantWhitespace = preserveSignificantWhitespace;
this.retainEmptyTokens = retainEmptyTokens;
}
_generateI18nMessage(nodes, meta = '', visitNodeFn) {
const {
meaning,
description,
customId
} = this._parseMetadata(meta);
const createI18nMessage = createI18nMessageFactory(this.retainEmptyTokens, this.preserveSignificantWhitespace);
const message = createI18nMessage(nodes, meaning, description, customId, visitNodeFn);
this._setMessageId(message, meta);
this._setLegacyIds(message, meta);
return message;
}
visitAllWithErrors(nodes) {
const result = nodes.map(node => node.visit(this, null));
return new ParseTreeResult(result, this._errors);
}
visitElement(element) {
this._visitElementLike(element);
return element;
}
visitComponent(component, context) {
this._visitElementLike(component);
return component;
}
visitExpansion(expansion, currentMessage) {
let message;
const meta = expansion.i18n;
this.hasI18nMeta = true;
if (meta instanceof IcuPlaceholder) {
const name = meta.name;
message = this._generateI18nMessage([expansion], meta);
const icu = icuFromI18nMessage(message);
icu.name = name;
if (currentMessage !== null) {
currentMessage.placeholderToMessage[name] = message;
}
} else {
message = this._generateI18nMessage([expansion], currentMessage || meta);
}
expansion.i18n = message;
return expansion;
}
visitText(text) {
return text;
}
visitAttribute(attribute) {
return attribute;
}
visitComment(comment) {
return comment;
}
visitExpansionCase(expansionCase) {
return expansionCase;
}
visitBlock(block, context) {
visitAll(this, block.children, context);
return block;
}
visitBlockParameter(parameter, context) {
return parameter;
}
visitLetDeclaration(decl, context) {
return decl;
}
visitDirective(directive, context) {
return directive;
}
_visitElementLike(node) {
let message = undefined;
if (hasI18nAttrs(node)) {
this.hasI18nMeta = true;
const attrs = [];
const attrsMeta = {};
for (const attr of node.attrs) {
if (attr.name === I18N_ATTR) {
const i18n = node.i18n || attr.value;
const originalNodeMap = new Map();
const trimmedNodes = this.preserveSignificantWhitespace ? node.children : visitAllWithSiblings(new WhitespaceVisitor(false, originalNodeMap), node.children);
message = this._generateI18nMessage(trimmedNodes, i18n, setI18nRefs(originalNodeMap));
if (message.nodes.length === 0) {
message = undefined;
}
node.i18n = message;
} else if (attr.name.startsWith(I18N_ATTR_PREFIX)) {
const name = attr.name.slice(I18N_ATTR_PREFIX.length);
let isTrustedType;
if (node instanceof Component) {
isTrustedType = node.tagName === null ? false : isTrustedTypesSink(node.tagName, name);
} else {
isTrustedType = isTrustedTypesSink(node.name, name);
}
if (isTrustedType) {
this._reportError(attr, `Translating attribute '${name}' is disallowed for security reasons.`);
} else {
attrsMeta[name] = attr.value;
}
} else {
attrs.push(attr);
}
}
if (Object.keys(attrsMeta).length) {
for (const attr of attrs) {
const meta = attrsMeta[attr.name];
if (meta !== undefined && attr.value) {
attr.i18n = this._generateI18nMessage([attr], attr.i18n || meta);
}
}
}
if (!this.keepI18nAttrs) {
node.attrs = attrs;
}
}
visitAll(this, node.children, message);
}
_parseMetadata(meta) {
return typeof meta === 'string' ? parseI18nMeta(meta) : meta instanceof Message ? meta : {};
}
_setMessageId(message, meta) {
if (!message.id) {
message.id = meta instanceof Message && meta.id || decimalDigest(message);
}
}
_setLegacyIds(message, meta) {
if (this.enableI18nLegacyMessageIdFormat) {
message.legacyIds = [computeDigest(message), computeDecimalDigest(message)];
} else if (typeof meta !== 'string') {
const previousMessage = meta instanceof Message ? meta : meta instanceof IcuPlaceholder ? meta.previousMessage : undefined;
message.legacyIds = previousMessage ? previousMessage.legacyIds : [];
}
}
_reportError(node, msg) {
this._errors.push(new ParseError(node.sourceSpan, msg));
}
}
const I18N_MEANING_SEPARATOR = '|';
const I18N_ID_SEPARATOR = '@@';
function parseI18nMeta(meta = '') {
let customId;
let meaning;
let description;
meta = meta.trim();
if (meta) {
const idIndex = meta.indexOf(I18N_ID_SEPARATOR);
const descIndex = meta.indexOf(I18N_MEANING_SEPARATOR);
let meaningAndDesc;
[meaningAndDesc, customId] = idIndex > -1 ? [meta.slice(0, idIndex), meta.slice(idIndex + 2)] : [meta, ''];
[meaning, description] = descIndex > -1 ? [meaningAndDesc.slice(0, descIndex), meaningAndDesc.slice(descIndex + 1)] : ['', meaningAndDesc];
}
return {
customId,
meaning,
description
};
}
function i18nMetaToJSDoc(meta) {
const tags = [];
if (meta.description) {
tags.push({
tagName: "desc",
text: meta.description
});
} else {
tags.push({
tagName: "suppress",
text: '{msgDescriptions}'
});
}
if (meta.meaning) {
tags.push({
tagName: "meaning",
text: meta.meaning
});
}
return jsDocComment(tags);
}
const GOOG_GET_MSG = 'goog.getMsg';
function createGoogleGetMsgStatements(variable$1, message, closureVar, placeholderValues) {
const messageString = serializeI18nMessageForGetMsg(message);
const args = [literal(messageString)];
if (Object.keys(placeholderValues).length) {
args.push(mapLiteral(formatI18nPlaceholderNamesInMap(placeholderValues, true), true));
args.push(mapLiteral({
original_code: literalMap(Object.keys(placeholderValues).map(param => ({
key: formatI18nPlaceholderName(param),
quoted: true,
value: message.placeholders[param] ? literal(message.placeholders[param].sourceSpan.toString()) : literal(message.placeholderToMessage[param].nodes.map(node => node.sourceSpan.toString()).join(''))
})))
}));
}
const googGetMsgStmt = new DeclareVarStmt(closureVar.name, variable(GOOG_GET_MSG).callFn(args), INFERRED_TYPE, StmtModifier.Final);
googGetMsgStmt.addLeadingComment(i18nMetaToJSDoc(message));
const i18nAssignmentStmt = new ExpressionStatement(variable$1.set(closureVar));
return [googGetMsgStmt, i18nAssignmentStmt];
}
class GetMsgSerializerVisitor {
formatPh(value) {
return `{$${formatI18nPlaceholderName(value)}}`;
}
visitText(text) {
return text.value;
}
visitContainer(container) {
return container.children.map(child => child.visit(this)).join('');
}
visitIcu(icu) {
return serializeIcuNode(icu);
}
visitTagPlaceholder(ph) {
return ph.isVoid ? this.formatPh(ph.startName) : `${this.formatPh(ph.startName)}${ph.children.map(child => child.visit(this)).join('')}${this.formatPh(ph.closeName)}`;
}
visitPlaceholder(ph) {
return this.formatPh(ph.name);
}
visitBlockPlaceholder(ph) {
return `${this.formatPh(ph.startName)}${ph.children.map(child => child.visit(this)).join('')}${this.formatPh(ph.closeName)}`;
}
visitIcuPlaceholder(ph, context) {
return this.formatPh(ph.name);
}
}
const serializerVisitor = new GetMsgSerializerVisitor();
function serializeI18nMessageForGetMsg(message) {
return message.nodes.map(node => node.visit(serializerVisitor, null)).join('');
}
function createLocalizeStatements(variable, message, params) {
const {
messageParts,
placeHolders
} = serializeI18nMessageForLocalize(message);
const sourceSpan = getSourceSpan(message);
const expressions = placeHolders.map(ph => params[ph.text]);
const localizedString$1 = localizedString(message, messageParts, placeHolders, expressions, sourceSpan);
const variableInitialization = variable.set(localizedString$1);
return [new ExpressionStatement(variableInitialization)];
}
class LocalizeSerializerVisitor {
placeholderToMessage;
pieces;
constructor(placeholderToMessage, pieces) {
this.placeholderToMessage = placeholderToMessage;
this.pieces = pieces;
}
visitText(text) {
if (this.pieces[this.pieces.length - 1] instanceof LiteralPiece) {
this.pieces[this.pieces.length - 1].text += text.value;
} else {
const sourceSpan = new ParseSourceSpan(text.sourceSpan.fullStart, text.sourceSpan.end, text.sourceSpan.fullStart, text.sourceSpan.details);
this.pieces.push(new LiteralPiece(text.value, sourceSpan));
}
}
visitContainer(container) {
container.children.forEach(child => child.visit(this));
}
visitIcu(icu) {
this.pieces.push(new LiteralPiece(serializeIcuNode(icu), icu.sourceSpan));
}
visitTagPlaceholder(ph) {
this.pieces.push(this.createPlaceholderPiece(ph.startName, ph.startSourceSpan ?? ph.sourceSpan));
if (!ph.isVoid) {
ph.children.forEach(child => child.visit(this));
this.pieces.push(this.createPlaceholderPiece(ph.closeName, ph.endSourceSpan ?? ph.sourceSpan));
}
}
visitPlaceholder(ph) {
this.pieces.push(this.createPlaceholderPiece(ph.name, ph.sourceSpan));
}
visitBlockPlaceholder(ph) {
this.pieces.push(this.createPlaceholderPiece(ph.startName, ph.startSourceSpan ?? ph.sourceSpan));
ph.children.forEach(child => child.visit(this));
this.pieces.push(this.createPlaceholderPiece(ph.closeName, ph.endSourceSpan ?? ph.sourceSpan));
}
visitIcuPlaceholder(ph) {
this.pieces.push(this.createPlaceholderPiece(ph.name, ph.sourceSpan, this.placeholderToMessage[ph.name]));
}
createPlaceholderPiece(name, sourceSpan, associatedMessage) {
return new PlaceholderPiece(formatI18nPlaceholderName(name, false), sourceSpan, associatedMessage);
}
}
function serializeI18nMessageForLocalize(message) {
const pieces = [];
const serializerVisitor = new LocalizeSerializerVisitor(message.placeholderToMessage, pieces);
message.nodes.forEach(node => node.visit(serializerVisitor));
return processMessagePieces(pieces);
}
function getSourceSpan(message) {
const startNode = message.nodes[0];
const endNode = message.nodes[message.nodes.length - 1];
return new ParseSourceSpan(startNode.sourceSpan.fullStart, endNode.sourceSpan.end, startNode.sourceSpan.fullStart, startNode.sourceSpan.details);
}
function processMessagePieces(pieces) {
const messageParts = [];
const placeHolders = [];
if (pieces[0] instanceof PlaceholderPiece) {
messageParts.push(createEmptyMessagePart(pieces[0].sourceSpan.start));
}
for (let i = 0; i < pieces.length; i++) {
const part = pieces[i];
if (part instanceof LiteralPiece) {
messageParts.push(part);
} else {
placeHolders.push(part);
if (pieces[i - 1] instanceof PlaceholderPiece) {
messageParts.push(createEmptyMessagePart(pieces[i - 1].sourceSpan.end));
}
}
}
if (pieces[pieces.length - 1] instanceof PlaceholderPiece) {
messageParts.push(createEmptyMessagePart(pieces[pieces.length - 1].sourceSpan.end));
}
return {
messageParts,
placeHolders
};
}
function createEmptyMessagePart(location) {
return new LiteralPiece('', new ParseSourceSpan(location, location));
}
const NG_I18N_CLOSURE_MODE = 'ngI18nClosureMode';
const TRANSLATION_VAR_PREFIX = 'i18n_';
const I18N_ICU_MAPPING_PREFIX = 'I18N_EXP_';
const ESCAPE = '\uFFFD';
const CLOSURE_TRANSLATION_VAR_PREFIX = 'MSG_';
function getTranslationConstPrefix(extra) {
return `${CLOSURE_TRANSLATION_VAR_PREFIX}${extra}`.toUpperCase();
}
function declareI18nVariable(variable) {
return new DeclareVarStmt(variable.name, undefined, INFERRED_TYPE, undefined, variable.sourceSpan);
}
function collectI18nConsts(job) {
const fileBasedI18nSuffix = job.relativeContextFilePath.replace(/[^A-Za-z0-9]/g, '_').toUpperCase() + '_';
const extractedAttributesByI18nContext = new Map();
const i18nAttributesByElement = new Map();
const i18nExpressionsByElement = new Map();
const messages = new Map();
for (const unit of job.units) {
for (const op of unit.ops()) {
if (op.kind === OpKind.ExtractedAttribute && op.i18nContext !== null) {
const attributes = extractedAttributesByI18nContext.get(op.i18nContext) ?? [];
attributes.push(op);
extractedAttributesByI18nContext.set(op.i18nContext, attributes);
} else if (op.kind === OpKind.I18nAttributes) {
i18nAttributesByElement.set(op.target, op);
} else if (op.kind === OpKind.I18nExpression && op.usage === I18nExpressionFor.I18nAttribute) {
const expressions = i18nExpressionsByElement.get(op.target) ?? [];
expressions.push(op);
i18nExpressionsByElement.set(op.target, expressions);
} else if (op.kind === OpKind.I18nMessage) {
messages.set(op.xref, op);
}
}
}
const i18nValuesByContext = new Map();
const messageConstIndices = new Map();
for (const unit of job.units) {
for (const op of unit.create) {
if (op.kind === OpKind.I18nMessage) {
if (op.messagePlaceholder === null) {
const {
mainVar,
statements
} = collectMessage(job, fileBasedI18nSuffix, messages, op);
if (op.i18nBlock !== null) {
const i18nConst = job.addConst(mainVar, statements);
messageConstIndices.set(op.i18nBlock, i18nConst);
} else {
job.constsInitializers.push(...statements);
i18nValuesByContext.set(op.i18nContext, mainVar);
const attributesForMessage = extractedAttributesByI18nContext.get(op.i18nContext);
if (attributesForMessage !== undefined) {
for (const attr of attributesForMessage) {
attr.expression = mainVar.clone();
}
}
}
}
OpList.remove(op);
}
}
}
for (const unit of job.units) {
for (const elem of unit.create) {
if (isElementOrContainerOp(elem)) {
const i18nAttributes = i18nAttributesByElement.get(elem.xref);
if (i18nAttributes === undefined) {
continue;
}
let i18nExpressions = i18nExpressionsByElement.get(elem.xref);
if (i18nExpressions === undefined) {
throw new Error('AssertionError: Could not find any i18n expressions associated with an I18nAttributes instruction');
}
const seenPropertyNames = new Set();
i18nExpressions = i18nExpressions.filter(i18nExpr => {
const seen = seenPropertyNames.has(i18nExpr.name);
seenPropertyNames.add(i18nExpr.name);
return !seen;
});
const i18nAttributeConfig = i18nExpressions.flatMap(i18nExpr => {
const i18nExprValue = i18nValuesByContext.get(i18nExpr.context);
if (i18nExprValue === undefined) {
throw new Error("AssertionError: Could not find i18n expression's value");
}
return [literal(i18nExpr.name), i18nExprValue];
});
i18nAttributes.i18nAttributesConfig = job.addConst(new LiteralArrayExpr(i18nAttributeConfig));
}
}
}
for (const unit of job.units) {
for (const op of unit.create) {
if (op.kind === OpKind.I18nStart) {
const msgIndex = messageConstIndices.get(op.root);
if (msgIndex === undefined) {
throw new Error('AssertionError: Could not find corresponding i18n block index for an i18n message op; was an i18n message incorrectly assumed to correspond to an attribute?');
}
op.messageIndex = msgIndex;
}
}
}
}
function collectMessage(job, fileBasedI18nSuffix, messages, messageOp) {
const statements = [];
const subMessagePlaceholders = new Map();
for (const subMessageId of messageOp.subMessages) {
const subMessage = messages.get(subMessageId);
const {
mainVar: subMessageVar,
statements: subMessageStatements
} = collectMessage(job, fileBasedI18nSuffix, messages, subMessage);
statements.push(...subMessageStatements);
const subMessages = subMessagePlaceholders.get(subMessage.messagePlaceholder) ?? [];
subMessages.push(subMessageVar);
subMessagePlaceholders.set(subMessage.messagePlaceholder, subMessages);
}
addSubMessageParams(messageOp, subMessagePlaceholders);
messageOp.params = new Map([...messageOp.params.entries()].sort());
const mainVar = variable(job.pool.uniqueName(TRANSLATION_VAR_PREFIX));
const closureVar = i18nGenerateClosureVar(job.pool, messageOp.message.id, fileBasedI18nSuffix, job.i18nUseExternalIds);
let transformFn = undefined;
if (messageOp.needsPostprocessing || messageOp.postprocessingParams.size > 0) {
const postprocessingParams = Object.fromEntries([...messageOp.postprocessingParams.entries()].sort());
const formattedPostprocessingParams = formatI18nPlaceholderNamesInMap(postprocessingParams, false);
const extraTransformFnParams = [];
if (messageOp.postprocessingParams.size > 0) {
extraTransformFnParams.push(mapLiteral(formattedPostprocessingParams, true));
}
transformFn = expr => importExpr(Identifiers.i18nPostprocess).callFn([expr, ...extraTransformFnParams]);
}
statements.push(...getTranslationDeclStmts(messageOp.message, mainVar, closureVar, messageOp.params, transformFn));
return {
mainVar,
statements
};
}
function addSubMessageParams(messageOp, subMessagePlaceholders) {
for (const [placeholder, subMessages] of subMessagePlaceholders) {
if (subMessages.length === 1) {
messageOp.params.set(placeholder, subMessages[0]);
} else {
messageOp.params.set(placeholder, literal(`${ESCAPE}${I18N_ICU_MAPPING_PREFIX}${placeholder}${ESCAPE}`));
messageOp.postprocessingParams.set(placeholder, literalArr(subMessages));
}
}
}
function getTranslationDeclStmts(message, variable, closureVar, params, transformFn) {
const paramsObject = Object.fromEntries(params);
const statements = [declareI18nVariable(variable), ifStmt(createClosureModeGuard(), createGoogleGetMsgStatements(variable, message, closureVar, paramsObject), createLocalizeStatements(variable, message, formatI18nPlaceholderNamesInMap(paramsObject, false)))];
if (transformFn) {
statements.push(new ExpressionStatement(variable.set(transformFn(variable))));
}
return statements;
}
function createClosureModeGuard() {
return typeofExpr(variable(NG_I18N_CLOSURE_MODE)).notIdentical(literal('undefined', STRING_TYPE)).and(variable(NG_I18N_CLOSURE_MODE));
}
function i18nGenerateClosureVar(pool, messageId, fileBasedI18nSuffix, useExternalIds) {
let name;
const suffix = fileBasedI18nSuffix;
if (useExternalIds) {
const prefix = getTranslationConstPrefix(`EXTERNAL_`);
const uniqueSuffix = pool.uniqueName(suffix);
name = `${prefix}${sanitizeIdentifier(messageId)}$$${uniqueSuffix}`;
} else {
const prefix = getTranslationConstPrefix(suffix);
name = pool.uniqueName(prefix);
}
return variable(name);
}
function convertI18nText(job) {
for (const unit of job.units) {
let currentI18n = null;
let currentIcu = null;
const textNodeI18nBlocks = new Map();
const textNodeIcus = new Map();
const icuPlaceholderByText = new Map();
for (const op of unit.create) {
switch (op.kind) {
case OpKind.I18nStart:
if (op.context === null) {
throw Error('I18n op should have its context set.');
}
currentI18n = op;
break;
case OpKind.I18nEnd:
currentI18n = null;
break;
case OpKind.IcuStart:
if (op.context === null) {
throw Error('Icu op should have its context set.');
}
currentIcu = op;
break;
case OpKind.IcuEnd:
currentIcu = null;
break;
case OpKind.Text:
if (currentI18n !== null) {
textNodeI18nBlocks.set(op.xref, currentI18n);
textNodeIcus.set(op.xref, currentIcu);
if (op.icuPlaceholder !== null) {
const icuPlaceholderOp = createIcuPlaceholderOp(job.allocateXrefId(), op.icuPlaceholder, [op.initialValue]);
OpList.replace(op, icuPlaceholderOp);
icuPlaceholderByText.set(op.xref, icuPlaceholderOp);
} else {
OpList.remove(op);
}
}
break;
}
}
for (const op of unit.update) {
switch (op.kind) {
case OpKind.InterpolateText:
if (!textNodeI18nBlocks.has(op.target)) {
continue;
}
const i18nOp = textNodeI18nBlocks.get(op.target);
const icuOp = textNodeIcus.get(op.target);
const icuPlaceholder = icuPlaceholderByText.get(op.target);
const contextId = icuOp ? icuOp.context : i18nOp.context;
const resolutionTime = icuOp ? I18nParamResolutionTime.Postproccessing : I18nParamResolutionTime.Creation;
const ops = [];
for (let i = 0; i < op.interpolation.expressions.length; i++) {
const expr = op.interpolation.expressions[i];
ops.push(createI18nExpressionOp(contextId, i18nOp.xref, i18nOp.xref, i18nOp.handle, expr, icuPlaceholder?.xref ?? null, op.interpolation.i18nPlaceholders[i] ?? null, resolutionTime, I18nExpressionFor.I18nText, '', expr.sourceSpan ?? op.sourceSpan));
}
OpList.replaceWithMany(op, ops);
if (icuPlaceholder !== undefined) {
icuPlaceholder.strings = op.interpolation.strings;
}
break;
}
}
}
}
function liftLocalRefs(job) {
for (const unit of job.units) {
for (const op of unit.create) {
switch (op.kind) {
case OpKind.ElementStart:
case OpKind.ConditionalCreate:
case OpKind.ConditionalBranchCreate:
case OpKind.Template:
if (!Array.isArray(op.localRefs)) {
throw new Error(`AssertionError: expected localRefs to be an array still`);
}
op.numSlotsUsed += op.localRefs.length;
if (op.localRefs.length > 0) {
const localRefs = serializeLocalRefs(op.localRefs);
op.localRefs = job.addConst(localRefs);
} else {
op.localRefs = null;
}
break;
}
}
}
}
function serializeLocalRefs(refs) {
const constRefs = [];
for (const ref of refs) {
constRefs.push(literal(ref.name), literal(ref.target));
}
return literalArr(constRefs);
}
function emitNamespaceChanges(job) {
for (const unit of job.units) {
let activeNamespace = Namespace.HTML;
for (const op of unit.create) {
if (op.kind !== OpKind.ElementStart) {
continue;
}
if (op.namespace !== activeNamespace) {
OpList.insertBefore(createNamespaceOp(op.namespace), op);
activeNamespace = op.namespace;
}
}
}
}
function parse(value) {
const styles = [];
let i = 0;
let parenDepth = 0;
let quote = 0;
let valueStart = 0;
let propStart = 0;
let currentProp = null;
while (i < value.length) {
const token = value.charCodeAt(i++);
switch (token) {
case 40:
parenDepth++;
break;
case 41:
parenDepth--;
break;
case 39:
if (quote === 0) {
quote = 39;
} else if (quote === 39 && value.charCodeAt(i - 1) !== 92) {
quote = 0;
}
break;
case 34:
if (quote === 0) {
quote = 34;
} else if (quote === 34 && value.charCodeAt(i - 1) !== 92) {
quote = 0;
}
break;
case 58:
if (!currentProp && parenDepth === 0 && quote === 0) {
currentProp = hyphenate(value.substring(propStart, i - 1).trim());
valueStart = i;
}
break;
case 59:
if (currentProp && valueStart > 0 && parenDepth === 0 && quote === 0) {
const styleVal = value.substring(valueStart, i - 1).trim();
styles.push(currentProp, styleVal);
propStart = i;
valueStart = 0;
currentProp = null;
}
break;
}
}
if (currentProp && valueStart) {
const styleVal = value.slice(valueStart).trim();
styles.push(currentProp, styleVal);
}
return styles;
}
function hyphenate(value) {
return value.replace(/[a-z][A-Z]/g, v => {
return v.charAt(0) + '-' + v.charAt(1);
}).toLowerCase();
}
function parseExtractedStyles(job) {
const elements = new Map();
for (const unit of job.units) {
for (const op of unit.create) {
if (isElementOrContainerOp(op)) {
elements.set(op.xref, op);
}
}
}
for (const unit of job.units) {
for (const op of unit.create) {
if (op.kind === OpKind.ExtractedAttribute && op.bindingKind === BindingKind.Attribute && isStringLiteral(op.expression)) {
const target = elements.get(op.target);
if (target !== undefined && (target.kind === OpKind.Template || target.kind === OpKind.ConditionalCreate || target.kind === OpKind.ConditionalBranchCreate) && target.templateKind === TemplateKind.Structural) {
continue;
}
if (op.name === 'style') {
const parsedStyles = parse(op.expression.value);
for (let i = 0; i < parsedStyles.length - 1; i += 2) {
OpList.insertBefore(createExtractedAttributeOp(op.target, BindingKind.StyleProperty, null, parsedStyles[i], literal(parsedStyles[i + 1]), null, null, SecurityContext.STYLE), op);
}
OpList.remove(op);
} else if (op.name === 'class') {
const parsedClasses = op.expression.value.trim().split(/\s+/g);
for (const parsedClass of parsedClasses) {
OpList.insertBefore(createExtractedAttributeOp(op.target, BindingKind.ClassName, null, parsedClass, null, null, null, SecurityContext.NONE), op);
}
OpList.remove(op);
}
}
}
}
}
function nameFunctionsAndVariables(job) {
addNamesToView(job.root, job.componentName, {
index: 0
}, job.compatibility === CompatibilityMode.TemplateDefinitionBuilder);
}
function addNamesToView(unit, baseName, state, compatibility) {
if (unit.fnName === null) {
unit.fnName = unit.job.pool.uniqueName(sanitizeIdentifier(`${baseName}_${unit.job.fnSuffix}`), false);
}
const varNames = new Map();
for (const op of unit.ops()) {
switch (op.kind) {
case OpKind.Property:
case OpKind.DomProperty:
if (op.bindingKind === BindingKind.LegacyAnimation) {
op.name = '@' + op.name;
}
break;
case OpKind.Animation:
if (op.handlerFnName === null) {
const animationKind = op.name.replace('.', '');
op.handlerFnName = `${unit.fnName}_${animationKind}_cb`;
op.handlerFnName = sanitizeIdentifier(op.handlerFnName);
}
break;
case OpKind.AnimationListener:
if (op.handlerFnName !== null) {
break;
}
if (!op.hostListener && op.targetSlot.slot === null) {
throw new Error(`Expected a slot to be assigned`);
}
const animationKind = op.name.replace('.', '');
if (op.hostListener) {
op.handlerFnName = `${baseName}_${animationKind}_HostBindingHandler`;
} else {
op.handlerFnName = `${unit.fnName}_${op.tag.replace('-', '_')}_${animationKind}_${op.targetSlot.slot}_listener`;
}
op.handlerFnName = sanitizeIdentifier(op.handlerFnName);
break;
case OpKind.Listener:
if (op.handlerFnName !== null) {
break;
}
if (!op.hostListener && op.targetSlot.slot === null) {
throw new Error(`Expected a slot to be assigned`);
}
let animation = '';
if (op.isLegacyAnimationListener) {
op.name = `@${op.name}.${op.legacyAnimationPhase}`;
animation = 'animation';
}
if (op.hostListener) {
op.handlerFnName = `${baseName}_${animation}${op.name}_HostBindingHandler`;
} else {
op.handlerFnName = `${unit.fnName}_${op.tag.replace('-', '_')}_${animation}${op.name}_${op.targetSlot.slot}_listener`;
}
op.handlerFnName = sanitizeIdentifier(op.handlerFnName);
break;
case OpKind.TwoWayListener:
if (op.handlerFnName !== null) {
break;
}
if (op.targetSlot.slot === null) {
throw new Error(`Expected a slot to be assigned`);
}
op.handlerFnName = sanitizeIdentifier(`${unit.fnName}_${op.tag.replace('-', '_')}_${op.name}_${op.targetSlot.slot}_listener`);
break;
case OpKind.Variable:
varNames.set(op.xref, getVariableName(unit, op.variable, state));
break;
case OpKind.RepeaterCreate:
if (!(unit instanceof ViewCompilationUnit)) {
throw new Error(`AssertionError: must be compiling a component`);
}
if (op.handle.slot === null) {
throw new Error(`Expected slot to be assigned`);
}
if (op.emptyView !== null) {
const emptyView = unit.job.views.get(op.emptyView);
addNamesToView(emptyView, `${baseName}_${op.functionNameSuffix}Empty_${op.handle.slot + 2}`, state, compatibility);
}
addNamesToView(unit.job.views.get(op.xref), `${baseName}_${op.functionNameSuffix}_${op.handle.slot + 1}`, state, compatibility);
break;
case OpKind.Projection:
if (!(unit instanceof ViewCompilationUnit)) {
throw new Error(`AssertionError: must be compiling a component`);
}
if (op.handle.slot === null) {
throw new Error(`Expected slot to be assigned`);
}
if (op.fallbackView !== null) {
const fallbackView = unit.job.views.get(op.fallbackView);
addNamesToView(fallbackView, `${baseName}_ProjectionFallback_${op.handle.slot}`, state, compatibility);
}
break;
case OpKind.ConditionalCreate:
case OpKind.ConditionalBranchCreate:
case OpKind.Template:
if (!(unit instanceof ViewCompilationUnit)) {
throw new Error(`AssertionError: must be compiling a component`);
}
const childView = unit.job.views.get(op.xref);
if (op.handle.slot === null) {
throw new Error(`Expected slot to be assigned`);
}
const suffix = op.functionNameSuffix.length === 0 ? '' : `_${op.functionNameSuffix}`;
addNamesToView(childView, `${baseName}${suffix}_${op.handle.slot}`, state, compatibility);
break;
case OpKind.StyleProp:
op.name = normalizeStylePropName(op.name);
if (compatibility) {
op.name = stripImportant(op.name);
}
break;
case OpKind.ClassProp:
if (compatibility) {
op.name = stripImportant(op.name);
}
break;
}
}
for (const op of unit.ops()) {
visitExpressionsInOp(op, expr => {
if (!(expr instanceof ReadVariableExpr) || expr.name !== null) {
return;
}
if (!varNames.has(expr.xref)) {
throw new Error(`Variable ${expr.xref} not yet named`);
}
expr.name = varNames.get(expr.xref);
});
}
}
function getVariableName(unit, variable, state) {
if (variable.name === null) {
switch (variable.kind) {
case SemanticVariableKind.Context:
variable.name = `ctx_r${state.index++}`;
break;
case SemanticVariableKind.Identifier:
if (unit.job.compatibility === CompatibilityMode.TemplateDefinitionBuilder) {
const compatPrefix = variable.identifier === 'ctx' ? 'i' : '';
variable.name = `${variable.identifier}_${compatPrefix}r${++state.index}`;
} else {
variable.name = `${variable.identifier}_i${state.index++}`;
}
break;
default:
variable.name = `_r${++state.index}`;
break;
}
}
return variable.name;
}
function normalizeStylePropName(name) {
return name.startsWith('--') ? name : hyphenate(name);
}
function stripImportant(name) {
const importantIndex = name.indexOf('!important');
if (importantIndex > -1) {
return name.substring(0, importantIndex);
}
return name;
}
function mergeNextContextExpressions(job) {
for (const unit of job.units) {
for (const op of unit.create) {
if (op.kind === OpKind.Listener || op.kind === OpKind.Animation || op.kind === OpKind.AnimationListener || op.kind === OpKind.TwoWayListener) {
mergeNextContextsInOps(op.handlerOps);
}
}
mergeNextContextsInOps(unit.update);
}
}
function mergeNextContextsInOps(ops) {
for (const op of ops) {
if (op.kind !== OpKind.Statement || !(op.statement instanceof ExpressionStatement) || !(op.statement.expr instanceof NextContextExpr)) {
continue;
}
const mergeSteps = op.statement.expr.steps;
let tryToMerge = true;
for (let candidate = op.next; candidate.kind !== OpKind.ListEnd && tryToMerge; candidate = candidate.next) {
visitExpressionsInOp(candidate, (expr, flags) => {
if (!isIrExpression(expr)) {
return expr;
}
if (!tryToMerge) {
return;
}
if (flags & VisitorContextFlag.InChildOperation) {
return;
}
switch (expr.kind) {
case ExpressionKind.NextContext:
expr.steps += mergeSteps;
OpList.remove(op);
tryToMerge = false;
break;
case ExpressionKind.GetCurrentView:
case ExpressionKind.Reference:
case ExpressionKind.ContextLetReference:
tryToMerge = false;
break;
}
return;
});
}
}
}
const CONTAINER_TAG = 'ng-container';
function generateNgContainerOps(job) {
for (const unit of job.units) {
const updatedElementXrefs = new Set();
for (const op of unit.create) {
if (op.kind === OpKind.ElementStart && op.tag === CONTAINER_TAG) {
op.kind = OpKind.ContainerStart;
updatedElementXrefs.add(op.xref);
}
if (op.kind === OpKind.ElementEnd && updatedElementXrefs.has(op.xref)) {
op.kind = OpKind.ContainerEnd;
}
}
}
}
function lookupElement(elements, xref) {
const el = elements.get(xref);
if (el === undefined) {
throw new Error('All attributes should have an element-like target.');
}
return el;
}
function disableBindings$1(job) {
const elements = new Map();
for (const view of job.units) {
for (const op of view.create) {
if (!isElementOrContainerOp(op)) {
continue;
}
elements.set(op.xref, op);
}
}
for (const unit of job.units) {
for (const op of unit.create) {
if ((op.kind === OpKind.ElementStart || op.kind === OpKind.ContainerStart) && op.nonBindable) {
OpList.insertAfter(createDisableBindingsOp(op.xref), op);
}
if ((op.kind === OpKind.ElementEnd || op.kind === OpKind.ContainerEnd) && lookupElement(elements, op.xref).nonBindable) {
OpList.insertBefore(createEnableBindingsOp(op.xref), op);
}
}
}
}
function kindTest(kind) {
return op => op.kind === kind;
}
function kindWithInterpolationTest(kind, interpolation) {
return op => {
return op.kind === kind && interpolation === op.expression instanceof Interpolation;
};
}
function basicListenerKindTest(op) {
return op.kind === OpKind.Listener && !(op.hostListener && op.isLegacyAnimationListener) || op.kind === OpKind.TwoWayListener || op.kind === OpKind.Animation || op.kind === OpKind.AnimationListener;
}
function nonInterpolationPropertyKindTest(op) {
return (op.kind === OpKind.Property || op.kind === OpKind.TwoWayProperty) && !(op.expression instanceof Interpolation);
}
const CREATE_ORDERING = [{
test: op => op.kind === OpKind.Listener && op.hostListener && op.isLegacyAnimationListener
}, {
test: basicListenerKindTest
}];
const UPDATE_ORDERING = [{
test: kindTest(OpKind.StyleMap),
transform: keepLast
}, {
test: kindTest(OpKind.ClassMap),
transform: keepLast
}, {
test: kindTest(OpKind.StyleProp)
}, {
test: kindTest(OpKind.ClassProp)
}, {
test: kindWithInterpolationTest(OpKind.Attribute, true)
}, {
test: kindWithInterpolationTest(OpKind.Property, true)
}, {
test: nonInterpolationPropertyKindTest
}, {
test: kindWithInterpolationTest(OpKind.Attribute, false)
}, {
test: kindTest(OpKind.Control)
}];
const UPDATE_HOST_ORDERING = [{
test: kindWithInterpolationTest(OpKind.DomProperty, true)
}, {
test: kindWithInterpolationTest(OpKind.DomProperty, false)
}, {
test: kindTest(OpKind.Attribute)
}, {
test: kindTest(OpKind.StyleMap),
transform: keepLast
}, {
test: kindTest(OpKind.ClassMap),
transform: keepLast
}, {
test: kindTest(OpKind.StyleProp)
}, {
test: kindTest(OpKind.ClassProp)
}];
const handledOpKinds = new Set([OpKind.Listener, OpKind.TwoWayListener, OpKind.AnimationListener, OpKind.StyleMap, OpKind.ClassMap, OpKind.StyleProp, OpKind.ClassProp, OpKind.Property, OpKind.TwoWayProperty, OpKind.DomProperty, OpKind.Attribute, OpKind.Animation, OpKind.Control]);
function orderOps(job) {
for (const unit of job.units) {
orderWithin(unit.create, CREATE_ORDERING);
const ordering = unit.job.kind === CompilationJobKind.Host ? UPDATE_HOST_ORDERING : UPDATE_ORDERING;
orderWithin(unit.update, ordering);
}
}
function orderWithin(opList, ordering) {
let opsToOrder = [];
let firstTargetInGroup = null;
for (const op of opList) {
const currentTarget = hasDependsOnSlotContextTrait(op) ? op.target : null;
if (!handledOpKinds.has(op.kind) || currentTarget !== firstTargetInGroup && firstTargetInGroup !== null && currentTarget !== null) {
OpList.insertBefore(reorder(opsToOrder, ordering), op);
opsToOrder = [];
firstTargetInGroup = null;
}
if (handledOpKinds.has(op.kind)) {
opsToOrder.push(op);
OpList.remove(op);
firstTargetInGroup = currentTarget ?? firstTargetInGroup;
}
}
opList.push(reorder(opsToOrder, ordering));
}
function reorder(ops, ordering) {
const groups = Array.from(ordering, () => new Array());
for (const op of ops) {
const groupIndex = ordering.findIndex(o => o.test(op));
groups[groupIndex].push(op);
}
return groups.flatMap((group, i) => {
const transform = ordering[i].transform;
return transform ? transform(group) : group;
});
}
function keepLast(ops) {
return ops.slice(ops.length - 1);
}
function removeContentSelectors(job) {
for (const unit of job.units) {
const elements = createOpXrefMap(unit);
for (const op of unit.ops()) {
switch (op.kind) {
case OpKind.Binding:
const target = lookupInXrefMap(elements, op.target);
if (isSelectAttribute(op.name) && target.kind === OpKind.Projection) {
OpList.remove(op);
}
break;
}
}
}
}
function isSelectAttribute(name) {
return name.toLowerCase() === 'select';
}
function lookupInXrefMap(map, xref) {
const el = map.get(xref);
if (el === undefined) {
throw new Error('All attributes should have an slottable target.');
}
return el;
}
function createPipes(job) {
for (const unit of job.units) {
processPipeBindingsInView(unit);
}
}
function processPipeBindingsInView(unit) {
for (const updateOp of unit.update) {
visitExpressionsInOp(updateOp, (expr, flags) => {
if (!isIrExpression(expr)) {
return;
}
if (expr.kind !== ExpressionKind.PipeBinding) {
return;
}
if (flags & VisitorContextFlag.InChildOperation) {
throw new Error(`AssertionError: pipe bindings should not appear in child expressions`);
}
if (unit.job.compatibility) {
const slotHandle = updateOp.target;
if (slotHandle == undefined) {
throw new Error(`AssertionError: expected slot handle to be assigned for pipe creation`);
}
addPipeToCreationBlock(unit, updateOp.target, expr);
} else {
unit.create.push(createPipeOp(expr.target, expr.targetSlot, expr.name));
}
});
}
}
function addPipeToCreationBlock(unit, afterTargetXref, binding) {
for (let op = unit.create.head.next; op.kind !== OpKind.ListEnd; op = op.next) {
if (!hasConsumesSlotTrait(op)) {
continue;
}
if (op.xref !== afterTargetXref) {
continue;
}
while (op.next.kind === OpKind.Pipe) {
op = op.next;
}
const pipe = createPipeOp(binding.target, binding.targetSlot, binding.name);
OpList.insertBefore(pipe, op.next);
return;
}
throw new Error(`AssertionError: unable to find insertion point for pipe ${binding.name}`);
}
function createVariadicPipes(job) {
for (const unit of job.units) {
for (const op of unit.update) {
transformExpressionsInOp(op, expr => {
if (!(expr instanceof PipeBindingExpr)) {
return expr;
}
if (expr.args.length <= 4) {
return expr;
}
return new PipeBindingVariadicExpr(expr.target, expr.targetSlot, expr.name, literalArr(expr.args), expr.args.length);
}, VisitorContextFlag.None);
}
}
}
function propagateI18nBlocks(job) {
propagateI18nBlocksToTemplates(job.root, 0);
}
function propagateI18nBlocksToTemplates(unit, subTemplateIndex) {
let i18nBlock = null;
for (const op of unit.create) {
switch (op.kind) {
case OpKind.I18nStart:
op.subTemplateIndex = subTemplateIndex === 0 ? null : subTemplateIndex;
i18nBlock = op;
break;
case OpKind.I18nEnd:
if (i18nBlock.subTemplateIndex === null) {
subTemplateIndex = 0;
}
i18nBlock = null;
break;
case OpKind.ConditionalCreate:
case OpKind.ConditionalBranchCreate:
case OpKind.Template:
subTemplateIndex = propagateI18nBlocksForView(unit.job.views.get(op.xref), i18nBlock, op.i18nPlaceholder, subTemplateIndex);
break;
case OpKind.RepeaterCreate:
const forView = unit.job.views.get(op.xref);
subTemplateIndex = propagateI18nBlocksForView(forView, i18nBlock, op.i18nPlaceholder, subTemplateIndex);
if (op.emptyView !== null) {
subTemplateIndex = propagateI18nBlocksForView(unit.job.views.get(op.emptyView), i18nBlock, op.emptyI18nPlaceholder, subTemplateIndex);
}
break;
case OpKind.Projection:
if (op.fallbackView !== null) {
subTemplateIndex = propagateI18nBlocksForView(unit.job.views.get(op.fallbackView), i18nBlock, op.fallbackViewI18nPlaceholder, subTemplateIndex);
}
break;
}
}
return subTemplateIndex;
}
function propagateI18nBlocksForView(view, i18nBlock, i18nPlaceholder, subTemplateIndex) {
if (i18nPlaceholder !== undefined) {
if (i18nBlock === null) {
throw Error('Expected template with i18n placeholder to be in an i18n block.');
}
subTemplateIndex++;
wrapTemplateWithI18n(view, i18nBlock);
}
return propagateI18nBlocksToTemplates(view, subTemplateIndex);
}
function wrapTemplateWithI18n(unit, parentI18n) {
if (unit.create.head.next?.kind !== OpKind.I18nStart) {
const id = unit.job.allocateXrefId();
OpList.insertAfter(createI18nStartOp(id, parentI18n.message, parentI18n.root, null), unit.create.head);
OpList.insertBefore(createI18nEndOp(id, null), unit.create.tail);
}
}
function extractPureFunctions(job) {
for (const view of job.units) {
for (const op of view.ops()) {
visitExpressionsInOp(op, expr => {
if (!(expr instanceof PureFunctionExpr) || expr.body === null) {
return;
}
const constantDef = new PureFunctionConstant(expr.args.length);
expr.fn = job.pool.getSharedConstant(constantDef, expr.body);
expr.body = null;
});
}
}
}
class PureFunctionConstant extends GenericKeyFn {
numArgs;
constructor(numArgs) {
super();
this.numArgs = numArgs;
}
keyOf(expr) {
if (expr instanceof PureFunctionParameterExpr) {
return `param(${expr.index})`;
} else {
return super.keyOf(expr);
}
}
toSharedConstantDeclaration(declName, keyExpr) {
const fnParams = [];
for (let idx = 0; idx < this.numArgs; idx++) {
fnParams.push(new FnParam('a' + idx));
}
const returnExpr = transformExpressionsInExpression(keyExpr, expr => {
if (!(expr instanceof PureFunctionParameterExpr)) {
return expr;
}
return variable('a' + expr.index);
}, VisitorContextFlag.None);
return new DeclareVarStmt(declName, new ArrowFunctionExpr(fnParams, returnExpr), undefined, StmtModifier.Final);
}
}
function generatePureLiteralStructures(job) {
for (const unit of job.units) {
for (const op of unit.update) {
transformExpressionsInOp(op, (expr, flags) => {
if (flags & VisitorContextFlag.InChildOperation) {
return expr;
}
if (expr instanceof LiteralArrayExpr) {
return transformLiteralArray(expr);
} else if (expr instanceof LiteralMapExpr) {
return transformLiteralMap(expr);
}
return expr;
}, VisitorContextFlag.None);
}
}
}
function transformLiteralArray(expr) {
const derivedEntries = [];
const nonConstantArgs = [];
for (const entry of expr.entries) {
if (entry instanceof SpreadElementExpr) {
if (entry.expression.isConstant()) {
derivedEntries.push(entry);
} else {
const idx = nonConstantArgs.length;
nonConstantArgs.push(entry.expression);
derivedEntries.push(new SpreadElementExpr(new PureFunctionParameterExpr(idx)));
}
continue;
}
if (entry.isConstant()) {
derivedEntries.push(entry);
} else {
const idx = nonConstantArgs.length;
nonConstantArgs.push(entry);
derivedEntries.push(new PureFunctionParameterExpr(idx));
}
}
return new PureFunctionExpr(literalArr(derivedEntries), nonConstantArgs);
}
function transformLiteralMap(expr) {
let derivedEntries = [];
const nonConstantArgs = [];
for (const entry of expr.entries) {
if (entry instanceof LiteralMapSpreadAssignment) {
if (entry.expression.isConstant()) {
derivedEntries.push(entry);
} else {
const idx = nonConstantArgs.length;
nonConstantArgs.push(entry.expression);
derivedEntries.push(new LiteralMapSpreadAssignment(new PureFunctionParameterExpr(idx)));
}
continue;
}
if (entry.value.isConstant()) {
derivedEntries.push(entry);
} else {
const idx = nonConstantArgs.length;
nonConstantArgs.push(entry.value);
derivedEntries.push(new LiteralMapPropertyAssignment(entry.key, new PureFunctionParameterExpr(idx), entry.quoted));
}
}
return new PureFunctionExpr(new LiteralMapExpr(derivedEntries), nonConstantArgs);
}
function optimizeRegularExpressions(job) {
for (const view of job.units) {
for (const op of view.ops()) {
transformExpressionsInOp(op, expr => {
if (expr instanceof RegularExpressionLiteralExpr && (expr.flags === null || !expr.flags.includes('g'))) {
return job.pool.getSharedConstant(new RegularExpressionConstant(), expr);
}
return expr;
}, VisitorContextFlag.None);
}
}
}
class RegularExpressionConstant extends GenericKeyFn {
toSharedConstantDeclaration(declName, keyExpr) {
return new DeclareVarStmt(declName, keyExpr, undefined, StmtModifier.Final);
}
}
function element(slot, tag, constIndex, localRefIndex, sourceSpan) {
return elementOrContainerBase(Identifiers.element, slot, tag, constIndex, localRefIndex, sourceSpan);
}
function elementStart(slot, tag, constIndex, localRefIndex, sourceSpan) {
return elementOrContainerBase(Identifiers.elementStart, slot, tag, constIndex, localRefIndex, sourceSpan);
}
function elementOrContainerBase(instruction, slot, tag, constIndex, localRefIndex, sourceSpan) {
const args = [literal(slot)];
if (tag !== null) {
args.push(literal(tag));
}
if (localRefIndex !== null) {
args.push(literal(constIndex), literal(localRefIndex));
} else if (constIndex !== null) {
args.push(literal(constIndex));
}
return call(instruction, args, sourceSpan);
}
function templateBase(instruction, slot, templateFnRef, decls, vars, tag, constIndex, localRefs, sourceSpan) {
const args = [literal(slot), templateFnRef, literal(decls), literal(vars), literal(tag), literal(constIndex)];
if (localRefs !== null) {
args.push(literal(localRefs));
args.push(importExpr(Identifiers.templateRefExtractor));
}
while (args[args.length - 1].isEquivalent(NULL_EXPR)) {
args.pop();
}
return call(instruction, args, sourceSpan);
}
function propertyBase(instruction, name, expression, sanitizer, sourceSpan) {
const args = [literal(name)];
if (expression instanceof Interpolation) {
args.push(interpolationToExpression(expression, sourceSpan));
} else {
args.push(expression);
}
if (sanitizer !== null) {
args.push(sanitizer);
}
return call(instruction, args, sourceSpan);
}
function elementEnd(sourceSpan) {
return call(Identifiers.elementEnd, [], sourceSpan);
}
function elementContainerStart(slot, constIndex, localRefIndex, sourceSpan) {
return elementOrContainerBase(Identifiers.elementContainerStart, slot, null, constIndex, localRefIndex, sourceSpan);
}
function elementContainer(slot, constIndex, localRefIndex, sourceSpan) {
return elementOrContainerBase(Identifiers.elementContainer, slot, null, constIndex, localRefIndex, sourceSpan);
}
function elementContainerEnd() {
return call(Identifiers.elementContainerEnd, [], null);
}
function template(slot, templateFnRef, decls, vars, tag, constIndex, localRefs, sourceSpan) {
return templateBase(Identifiers.templateCreate, slot, templateFnRef, decls, vars, tag, constIndex, localRefs, sourceSpan);
}
function disableBindings() {
return call(Identifiers.disableBindings, [], null);
}
function enableBindings() {
return call(Identifiers.enableBindings, [], null);
}
function listener(name, handlerFn, eventTargetResolver, syntheticHost, sourceSpan) {
const args = [literal(name), handlerFn];
if (eventTargetResolver !== null) {
args.push(importExpr(eventTargetResolver));
}
return call(syntheticHost ? Identifiers.syntheticHostListener : Identifiers.listener, args, sourceSpan);
}
function twoWayBindingSet(target, value) {
return importExpr(Identifiers.twoWayBindingSet).callFn([target, value]);
}
function twoWayListener(name, handlerFn, sourceSpan) {
return call(Identifiers.twoWayListener, [literal(name), handlerFn], sourceSpan);
}
function pipe(slot, name) {
return call(Identifiers.pipe, [literal(slot), literal(name)], null);
}
function namespaceHTML() {
return call(Identifiers.namespaceHTML, [], null);
}
function namespaceSVG() {
return call(Identifiers.namespaceSVG, [], null);
}
function namespaceMath() {
return call(Identifiers.namespaceMathML, [], null);
}
function advance(delta, sourceSpan) {
return call(Identifiers.advance, delta > 1 ? [literal(delta)] : [], sourceSpan);
}
function reference(slot) {
return importExpr(Identifiers.reference).callFn([literal(slot)]);
}
function nextContext(steps) {
return importExpr(Identifiers.nextContext).callFn(steps === 1 ? [] : [literal(steps)]);
}
function getCurrentView() {
return importExpr(Identifiers.getCurrentView).callFn([]);
}
function restoreView(savedView) {
return importExpr(Identifiers.restoreView).callFn([savedView]);
}
function resetView(returnValue) {
return importExpr(Identifiers.resetView).callFn([returnValue]);
}
function text(slot, initialValue, sourceSpan) {
const args = [literal(slot, null)];
if (initialValue !== '') {
args.push(literal(initialValue));
}
return call(Identifiers.text, args, sourceSpan);
}
function defer(selfSlot, primarySlot, dependencyResolverFn, loadingSlot, placeholderSlot, errorSlot, loadingConfig, placeholderConfig, enableTimerScheduling, sourceSpan, flags) {
const args = [literal(selfSlot), literal(primarySlot), dependencyResolverFn ?? literal(null), literal(loadingSlot), literal(placeholderSlot), literal(errorSlot), loadingConfig ?? literal(null), placeholderConfig ?? literal(null), enableTimerScheduling ? importExpr(Identifiers.deferEnableTimerScheduling) : literal(null), literal(flags)];
let expr;
while ((expr = args[args.length - 1]) !== null && expr instanceof LiteralExpr && expr.value === null) {
args.pop();
}
return call(Identifiers.defer, args, sourceSpan);
}
const deferTriggerToR3TriggerInstructionsMap = new Map([[DeferTriggerKind.Idle, {
["none"]: Identifiers.deferOnIdle,
["prefetch"]: Identifiers.deferPrefetchOnIdle,
["hydrate"]: Identifiers.deferHydrateOnIdle
}], [DeferTriggerKind.Immediate, {
["none"]: Identifiers.deferOnImmediate,
["prefetch"]: Identifiers.deferPrefetchOnImmediate,
["hydrate"]: Identifiers.deferHydrateOnImmediate
}], [DeferTriggerKind.Timer, {
["none"]: Identifiers.deferOnTimer,
["prefetch"]: Identifiers.deferPrefetchOnTimer,
["hydrate"]: Identifiers.deferHydrateOnTimer
}], [DeferTriggerKind.Hover, {
["none"]: Identifiers.deferOnHover,
["prefetch"]: Identifiers.deferPrefetchOnHover,
["hydrate"]: Identifiers.deferHydrateOnHover
}], [DeferTriggerKind.Interaction, {
["none"]: Identifiers.deferOnInteraction,
["prefetch"]: Identifiers.deferPrefetchOnInteraction,
["hydrate"]: Identifiers.deferHydrateOnInteraction
}], [DeferTriggerKind.Viewport, {
["none"]: Identifiers.deferOnViewport,
["prefetch"]: Identifiers.deferPrefetchOnViewport,
["hydrate"]: Identifiers.deferHydrateOnViewport
}], [DeferTriggerKind.Never, {
["none"]: Identifiers.deferHydrateNever,
["prefetch"]: Identifiers.deferHydrateNever,
["hydrate"]: Identifiers.deferHydrateNever
}]]);
function deferOn(trigger, args, modifier, sourceSpan) {
const instructionToCall = deferTriggerToR3TriggerInstructionsMap.get(trigger)?.[modifier];
if (instructionToCall === undefined) {
throw new Error(`Unable to determine instruction for trigger ${trigger}`);
}
return call(instructionToCall, args, sourceSpan);
}
function projectionDef(def) {
return call(Identifiers.projectionDef, def ? [def] : [], null);
}
function projection(slot, projectionSlotIndex, attributes, fallbackFnName, fallbackDecls, fallbackVars, sourceSpan) {
const args = [literal(slot)];
if (projectionSlotIndex !== 0 || attributes !== null || fallbackFnName !== null) {
args.push(literal(projectionSlotIndex));
if (attributes !== null) {
args.push(attributes);
}
if (fallbackFnName !== null) {
if (attributes === null) {
args.push(literal(null));
}
args.push(variable(fallbackFnName), literal(fallbackDecls), literal(fallbackVars));
}
}
return call(Identifiers.projection, args, sourceSpan);
}
function i18nStart(slot, constIndex, subTemplateIndex, sourceSpan) {
const args = [literal(slot), literal(constIndex)];
if (subTemplateIndex !== null) {
args.push(literal(subTemplateIndex));
}
return call(Identifiers.i18nStart, args, sourceSpan);
}
function conditionalCreate(slot, templateFnRef, decls, vars, tag, constIndex, localRefs, sourceSpan) {
const args = [literal(slot), templateFnRef, literal(decls), literal(vars), literal(tag), literal(constIndex)];
if (localRefs !== null) {
args.push(literal(localRefs));
args.push(importExpr(Identifiers.templateRefExtractor));
}
while (args[args.length - 1].isEquivalent(NULL_EXPR)) {
args.pop();
}
return call(Identifiers.conditionalCreate, args, sourceSpan);
}
function conditionalBranchCreate(slot, templateFnRef, decls, vars, tag, constIndex, localRefs, sourceSpan) {
const args = [literal(slot), templateFnRef, literal(decls), literal(vars), literal(tag), literal(constIndex)];
if (localRefs !== null) {
args.push(literal(localRefs));
args.push(importExpr(Identifiers.templateRefExtractor));
}
while (args[args.length - 1].isEquivalent(NULL_EXPR)) {
args.pop();
}
return call(Identifiers.conditionalBranchCreate, args, sourceSpan);
}
function repeaterCreate(slot, viewFnName, decls, vars, tag, constIndex, trackByFn, trackByUsesComponentInstance, emptyViewFnName, emptyDecls, emptyVars, emptyTag, emptyConstIndex, sourceSpan) {
const args = [literal(slot), variable(viewFnName), literal(decls), literal(vars), literal(tag), literal(constIndex), trackByFn];
if (trackByUsesComponentInstance || emptyViewFnName !== null) {
args.push(literal(trackByUsesComponentInstance));
if (emptyViewFnName !== null) {
args.push(variable(emptyViewFnName), literal(emptyDecls), literal(emptyVars));
if (emptyTag !== null || emptyConstIndex !== null) {
args.push(literal(emptyTag));
}
if (emptyConstIndex !== null) {
args.push(literal(emptyConstIndex));
}
}
}
return call(Identifiers.repeaterCreate, args, sourceSpan);
}
function repeater(collection, sourceSpan) {
return call(Identifiers.repeater, [collection], sourceSpan);
}
function deferWhen(modifier, expr, sourceSpan) {
if (modifier === "prefetch") {
return call(Identifiers.deferPrefetchWhen, [expr], sourceSpan);
} else if (modifier === "hydrate") {
return call(Identifiers.deferHydrateWhen, [expr], sourceSpan);
}
return call(Identifiers.deferWhen, [expr], sourceSpan);
}
function declareLet(slot, sourceSpan) {
return call(Identifiers.declareLet, [literal(slot)], sourceSpan);
}
function storeLet(value, sourceSpan) {
return importExpr(Identifiers.storeLet).callFn([value], sourceSpan);
}
function readContextLet(slot) {
return importExpr(Identifiers.readContextLet).callFn([literal(slot)]);
}
function i18n(slot, constIndex, subTemplateIndex, sourceSpan) {
const args = [literal(slot), literal(constIndex)];
if (subTemplateIndex) {
args.push(literal(subTemplateIndex));
}
return call(Identifiers.i18n, args, sourceSpan);
}
function i18nEnd(endSourceSpan) {
return call(Identifiers.i18nEnd, [], endSourceSpan);
}
function i18nAttributes(slot, i18nAttributesConfig) {
const args = [literal(slot), literal(i18nAttributesConfig)];
return call(Identifiers.i18nAttributes, args, null);
}
function ariaProperty(name, expression, sourceSpan) {
return propertyBase(Identifiers.ariaProperty, name, expression, null, sourceSpan);
}
function property(name, expression, sanitizer, sourceSpan) {
return propertyBase(Identifiers.property, name, expression, sanitizer, sourceSpan);
}
function control(name, expression, sanitizer, sourceSpan) {
const args = [];
if (expression instanceof Interpolation) {
args.push(interpolationToExpression(expression, sourceSpan));
} else {
args.push(expression);
}
args.push(literal(name));
if (sanitizer !== null) {
args.push(sanitizer);
}
return call(Identifiers.control, args, sourceSpan);
}
function controlCreate(sourceSpan) {
return call(Identifiers.controlCreate, [], sourceSpan);
}
function twoWayProperty(name, expression, sanitizer, sourceSpan) {
const args = [literal(name), expression];
if (sanitizer !== null) {
args.push(sanitizer);
}
return call(Identifiers.twoWayProperty, args, sourceSpan);
}
function attribute(name, expression, sanitizer, namespace, sourceSpan) {
const args = [literal(name)];
if (expression instanceof Interpolation) {
args.push(interpolationToExpression(expression, sourceSpan));
} else {
args.push(expression);
}
if (sanitizer !== null || namespace !== null) {
args.push(sanitizer ?? literal(null));
}
if (namespace !== null) {
args.push(literal(namespace));
}
return call(Identifiers.attribute, args, null);
}
function styleProp(name, expression, unit, sourceSpan) {
const args = [literal(name)];
if (expression instanceof Interpolation) {
args.push(interpolationToExpression(expression, sourceSpan));
} else {
args.push(expression);
}
if (unit !== null) {
args.push(literal(unit));
}
return call(Identifiers.styleProp, args, sourceSpan);
}
function classProp(name, expression, sourceSpan) {
return call(Identifiers.classProp, [literal(name), expression], sourceSpan);
}
function styleMap(expression, sourceSpan) {
const value = expression instanceof Interpolation ? interpolationToExpression(expression, sourceSpan) : expression;
return call(Identifiers.styleMap, [value], sourceSpan);
}
function classMap(expression, sourceSpan) {
const value = expression instanceof Interpolation ? interpolationToExpression(expression, sourceSpan) : expression;
return call(Identifiers.classMap, [value], sourceSpan);
}
function domElement(slot, tag, constIndex, localRefIndex, sourceSpan) {
return elementOrContainerBase(Identifiers.domElement, slot, tag, constIndex, localRefIndex, sourceSpan);
}
function domElementStart(slot, tag, constIndex, localRefIndex, sourceSpan) {
return elementOrContainerBase(Identifiers.domElementStart, slot, tag, constIndex, localRefIndex, sourceSpan);
}
function domElementEnd(sourceSpan) {
return call(Identifiers.domElementEnd, [], sourceSpan);
}
function domElementContainerStart(slot, constIndex, localRefIndex, sourceSpan) {
return elementOrContainerBase(Identifiers.domElementContainerStart, slot, null, constIndex, localRefIndex, sourceSpan);
}
function domElementContainer(slot, constIndex, localRefIndex, sourceSpan) {
return elementOrContainerBase(Identifiers.domElementContainer, slot, null, constIndex, localRefIndex, sourceSpan);
}
function domElementContainerEnd() {
return call(Identifiers.domElementContainerEnd, [], null);
}
function domListener(name, handlerFn, eventTargetResolver, sourceSpan) {
const args = [literal(name), handlerFn];
if (eventTargetResolver !== null) {
args.push(importExpr(eventTargetResolver));
}
return call(Identifiers.domListener, args, sourceSpan);
}
function domTemplate(slot, templateFnRef, decls, vars, tag, constIndex, localRefs, sourceSpan) {
return templateBase(Identifiers.domTemplate, slot, templateFnRef, decls, vars, tag, constIndex, localRefs, sourceSpan);
}
const PIPE_BINDINGS = [Identifiers.pipeBind1, Identifiers.pipeBind2, Identifiers.pipeBind3, Identifiers.pipeBind4];
function pipeBind(slot, varOffset, args) {
if (args.length < 1 || args.length > PIPE_BINDINGS.length) {
throw new Error(`pipeBind() argument count out of bounds`);
}
const instruction = PIPE_BINDINGS[args.length - 1];
return importExpr(instruction).callFn([literal(slot), literal(varOffset), ...args]);
}
function pipeBindV(slot, varOffset, args) {
return importExpr(Identifiers.pipeBindV).callFn([literal(slot), literal(varOffset), args]);
}
function textInterpolate(strings, expressions, sourceSpan) {
const interpolationArgs = collateInterpolationArgs(strings, expressions);
return callVariadicInstruction(TEXT_INTERPOLATE_CONFIG, [], interpolationArgs, sourceSpan);
}
function i18nExp(expr, sourceSpan) {
return call(Identifiers.i18nExp, [expr], sourceSpan);
}
function i18nApply(slot, sourceSpan) {
return call(Identifiers.i18nApply, [literal(slot)], sourceSpan);
}
function domProperty(name, expression, sanitizer, sourceSpan) {
return propertyBase(Identifiers.domProperty, name, expression, sanitizer, sourceSpan);
}
function animation(animationKind, handlerFn, sanitizer, sourceSpan) {
const args = [handlerFn];
if (sanitizer !== null) {
args.push(sanitizer);
}
const identifier = animationKind === "enter" ? Identifiers.animationEnter : Identifiers.animationLeave;
return call(identifier, args, sourceSpan);
}
function animationString(animationKind, expression, sanitizer, sourceSpan) {
const value = expression instanceof Interpolation ? interpolationToExpression(expression, sourceSpan) : expression;
const args = [value];
if (sanitizer !== null) {
args.push(sanitizer);
}
const identifier = animationKind === "enter" ? Identifiers.animationEnter : Identifiers.animationLeave;
return call(identifier, args, sourceSpan);
}
function animationListener(animationKind, handlerFn, eventTargetResolver, sourceSpan) {
const args = [handlerFn];
const identifier = animationKind === "enter" ? Identifiers.animationEnterListener : Identifiers.animationLeaveListener;
return call(identifier, args, sourceSpan);
}
function syntheticHostProperty(name, expression, sourceSpan) {
return call(Identifiers.syntheticHostProperty, [literal(name), expression], sourceSpan);
}
function pureFunction(varOffset, fn, args) {
return callVariadicInstructionExpr(PURE_FUNCTION_CONFIG, [literal(varOffset), fn], args, null);
}
function attachSourceLocation(templatePath, locations) {
return call(Identifiers.attachSourceLocations, [literal(templatePath), locations], null);
}
function collateInterpolationArgs(strings, expressions) {
if (strings.length < 1 || expressions.length !== strings.length - 1) {
throw new Error(`AssertionError: expected specific shape of args for strings/expressions in interpolation`);
}
const interpolationArgs = [];
if (expressions.length === 1 && strings[0] === '' && strings[1] === '') {
interpolationArgs.push(expressions[0]);
} else {
let idx;
for (idx = 0; idx < expressions.length; idx++) {
interpolationArgs.push(literal(strings[idx]), expressions[idx]);
}
interpolationArgs.push(literal(strings[idx]));
}
return interpolationArgs;
}
function interpolationToExpression(interpolation, sourceSpan) {
const interpolationArgs = collateInterpolationArgs(interpolation.strings, interpolation.expressions);
return callVariadicInstructionExpr(VALUE_INTERPOLATE_CONFIG, [], interpolationArgs, sourceSpan);
}
function call(instruction, args, sourceSpan) {
const expr = importExpr(instruction).callFn(args, sourceSpan);
return createStatementOp(new ExpressionStatement(expr, sourceSpan));
}
function conditional(condition, contextValue, sourceSpan) {
const args = [condition];
if (contextValue !== null) {
args.push(contextValue);
}
return call(Identifiers.conditional, args, sourceSpan);
}
const TEXT_INTERPOLATE_CONFIG = {
constant: [Identifiers.textInterpolate, Identifiers.textInterpolate1, Identifiers.textInterpolate2, Identifiers.textInterpolate3, Identifiers.textInterpolate4, Identifiers.textInterpolate5, Identifiers.textInterpolate6, Identifiers.textInterpolate7, Identifiers.textInterpolate8],
variable: Identifiers.textInterpolateV,
mapping: n => {
if (n % 2 === 0) {
throw new Error(`Expected odd number of arguments`);
}
return (n - 1) / 2;
}
};
const VALUE_INTERPOLATE_CONFIG = {
constant: [Identifiers.interpolate, Identifiers.interpolate1, Identifiers.interpolate2, Identifiers.interpolate3, Identifiers.interpolate4, Identifiers.interpolate5, Identifiers.interpolate6, Identifiers.interpolate7, Identifiers.interpolate8],
variable: Identifiers.interpolateV,
mapping: n => {
if (n % 2 === 0) {
throw new Error(`Expected odd number of arguments`);
}
return (n - 1) / 2;
}
};
const PURE_FUNCTION_CONFIG = {
constant: [Identifiers.pureFunction0, Identifiers.pureFunction1, Identifiers.pureFunction2, Identifiers.pureFunction3, Identifiers.pureFunction4, Identifiers.pureFunction5, Identifiers.pureFunction6, Identifiers.pureFunction7, Identifiers.pureFunction8],
variable: Identifiers.pureFunctionV,
mapping: n => n
};
function callVariadicInstructionExpr(config, baseArgs, interpolationArgs, sourceSpan) {
const n = config.mapping(interpolationArgs.length);
const lastInterpolationArg = interpolationArgs.at(-1);
if (interpolationArgs.length > 1 && lastInterpolationArg instanceof LiteralExpr && lastInterpolationArg.value === '') {
interpolationArgs.pop();
}
if (n < config.constant.length) {
return importExpr(config.constant[n]).callFn([...baseArgs, ...interpolationArgs], sourceSpan);
} else if (config.variable !== null) {
return importExpr(config.variable).callFn([...baseArgs, literalArr(interpolationArgs)], sourceSpan);
} else {
throw new Error(`AssertionError: unable to call variadic function`);
}
}
function callVariadicInstruction(config, baseArgs, interpolationArgs, sourceSpan) {
return createStatementOp(callVariadicInstructionExpr(config, baseArgs, interpolationArgs, sourceSpan).toStmt());
}
const GLOBAL_TARGET_RESOLVERS = new Map([['window', Identifiers.resolveWindow], ['document', Identifiers.resolveDocument], ['body', Identifiers.resolveBody]]);
const DOM_PROPERTY_REMAPPING = new Map([['class', 'className'], ['for', 'htmlFor'], ['formaction', 'formAction'], ['innerHtml', 'innerHTML'], ['readonly', 'readOnly'], ['tabindex', 'tabIndex']]);
function reify(job) {
for (const unit of job.units) {
reifyCreateOperations(unit, unit.create);
reifyUpdateOperations(unit, unit.update);
}
}
function reifyCreateOperations(unit, ops) {
for (const op of ops) {
transformExpressionsInOp(op, reifyIrExpression, VisitorContextFlag.None);
switch (op.kind) {
case OpKind.Text:
OpList.replace(op, text(op.handle.slot, op.initialValue, op.sourceSpan));
break;
case OpKind.ElementStart:
OpList.replace(op, unit.job.mode === TemplateCompilationMode.DomOnly ? domElementStart(op.handle.slot, op.tag, op.attributes, op.localRefs, op.startSourceSpan) : elementStart(op.handle.slot, op.tag, op.attributes, op.localRefs, op.startSourceSpan));
break;
case OpKind.Element:
OpList.replace(op, unit.job.mode === TemplateCompilationMode.DomOnly ? domElement(op.handle.slot, op.tag, op.attributes, op.localRefs, op.wholeSourceSpan) : element(op.handle.slot, op.tag, op.attributes, op.localRefs, op.wholeSourceSpan));
break;
case OpKind.ElementEnd:
OpList.replace(op, unit.job.mode === TemplateCompilationMode.DomOnly ? domElementEnd(op.sourceSpan) : elementEnd(op.sourceSpan));
break;
case OpKind.ContainerStart:
OpList.replace(op, unit.job.mode === TemplateCompilationMode.DomOnly ? domElementContainerStart(op.handle.slot, op.attributes, op.localRefs, op.startSourceSpan) : elementContainerStart(op.handle.slot, op.attributes, op.localRefs, op.startSourceSpan));
break;
case OpKind.Container:
OpList.replace(op, unit.job.mode === TemplateCompilationMode.DomOnly ? domElementContainer(op.handle.slot, op.attributes, op.localRefs, op.wholeSourceSpan) : elementContainer(op.handle.slot, op.attributes, op.localRefs, op.wholeSourceSpan));
break;
case OpKind.ContainerEnd:
OpList.replace(op, unit.job.mode === TemplateCompilationMode.DomOnly ? domElementContainerEnd() : elementContainerEnd());
break;
case OpKind.I18nStart:
OpList.replace(op, i18nStart(op.handle.slot, op.messageIndex, op.subTemplateIndex, op.sourceSpan));
break;
case OpKind.I18nEnd:
OpList.replace(op, i18nEnd(op.sourceSpan));
break;
case OpKind.I18n:
OpList.replace(op, i18n(op.handle.slot, op.messageIndex, op.subTemplateIndex, op.sourceSpan));
break;
case OpKind.I18nAttributes:
if (op.i18nAttributesConfig === null) {
throw new Error(`AssertionError: i18nAttributesConfig was not set`);
}
OpList.replace(op, i18nAttributes(op.handle.slot, op.i18nAttributesConfig));
break;
case OpKind.Template:
if (!(unit instanceof ViewCompilationUnit)) {
throw new Error(`AssertionError: must be compiling a component`);
}
if (Array.isArray(op.localRefs)) {
throw new Error(`AssertionError: local refs array should have been extracted into a constant`);
}
const childView = unit.job.views.get(op.xref);
OpList.replace(op, op.templateKind === TemplateKind.Block || unit.job.mode === TemplateCompilationMode.DomOnly ? domTemplate(op.handle.slot, variable(childView.fnName), childView.decls, childView.vars, op.tag, op.attributes, op.localRefs, op.startSourceSpan) : template(op.handle.slot, variable(childView.fnName), childView.decls, childView.vars, op.tag, op.attributes, op.localRefs, op.startSourceSpan));
break;
case OpKind.DisableBindings:
OpList.replace(op, disableBindings());
break;
case OpKind.EnableBindings:
OpList.replace(op, enableBindings());
break;
case OpKind.Pipe:
OpList.replace(op, pipe(op.handle.slot, op.name));
break;
case OpKind.DeclareLet:
OpList.replace(op, declareLet(op.handle.slot, op.sourceSpan));
break;
case OpKind.AnimationString:
OpList.replace(op, animationString(op.animationKind, op.expression, op.sanitizer, op.sourceSpan));
break;
case OpKind.Animation:
const animationCallbackFn = reifyListenerHandler(unit, op.handlerFnName, op.handlerOps, false);
OpList.replace(op, animation(op.animationKind, animationCallbackFn, op.sanitizer, op.sourceSpan));
break;
case OpKind.AnimationListener:
const animationListenerFn = reifyListenerHandler(unit, op.handlerFnName, op.handlerOps, op.consumesDollarEvent);
OpList.replace(op, animationListener(op.animationKind, animationListenerFn, null, op.sourceSpan));
break;
case OpKind.Listener:
const listenerFn = reifyListenerHandler(unit, op.handlerFnName, op.handlerOps, op.consumesDollarEvent);
const eventTargetResolver = op.eventTarget ? GLOBAL_TARGET_RESOLVERS.get(op.eventTarget) : null;
if (eventTargetResolver === undefined) {
throw new Error(`Unexpected global target '${op.eventTarget}' defined for '${op.name}' event. Supported list of global targets: window,document,body.`);
}
OpList.replace(op, unit.job.mode === TemplateCompilationMode.DomOnly && !op.hostListener && !op.isLegacyAnimationListener ? domListener(op.name, listenerFn, eventTargetResolver, op.sourceSpan) : listener(op.name, listenerFn, eventTargetResolver, op.hostListener && op.isLegacyAnimationListener, op.sourceSpan));
break;
case OpKind.TwoWayListener:
OpList.replace(op, twoWayListener(op.name, reifyListenerHandler(unit, op.handlerFnName, op.handlerOps, true), op.sourceSpan));
break;
case OpKind.Variable:
if (op.variable.name === null) {
throw new Error(`AssertionError: unnamed variable ${op.xref}`);
}
OpList.replace(op, createStatementOp(new DeclareVarStmt(op.variable.name, op.initializer, undefined, StmtModifier.Final)));
break;
case OpKind.Namespace:
switch (op.active) {
case Namespace.HTML:
OpList.replace(op, namespaceHTML());
break;
case Namespace.SVG:
OpList.replace(op, namespaceSVG());
break;
case Namespace.Math:
OpList.replace(op, namespaceMath());
break;
}
break;
case OpKind.Defer:
const timerScheduling = !!op.loadingMinimumTime || !!op.loadingAfterTime || !!op.placeholderMinimumTime;
OpList.replace(op, defer(op.handle.slot, op.mainSlot.slot, op.resolverFn, op.loadingSlot?.slot ?? null, op.placeholderSlot?.slot ?? null, op.errorSlot?.slot ?? null, op.loadingConfig, op.placeholderConfig, timerScheduling, op.sourceSpan, op.flags));
break;
case OpKind.DeferOn:
let args = [];
switch (op.trigger.kind) {
case DeferTriggerKind.Never:
case DeferTriggerKind.Idle:
case DeferTriggerKind.Immediate:
break;
case DeferTriggerKind.Timer:
args = [literal(op.trigger.delay)];
break;
case DeferTriggerKind.Viewport:
if (op.modifier === "hydrate") {
args = op.trigger.options ? [op.trigger.options] : [];
} else {
args = [literal(op.trigger.targetSlot?.slot ?? null)];
if (op.trigger.targetSlotViewSteps !== 0) {
args.push(literal(op.trigger.targetSlotViewSteps));
} else if (op.trigger.options) {
args.push(literal(null));
}
if (op.trigger.options) {
args.push(op.trigger.options);
}
}
break;
case DeferTriggerKind.Interaction:
case DeferTriggerKind.Hover:
if (op.modifier === "hydrate") {
args = [];
} else {
args = [literal(op.trigger.targetSlot?.slot ?? null)];
if (op.trigger.targetSlotViewSteps !== 0) {
args.push(literal(op.trigger.targetSlotViewSteps));
}
}
break;
default:
throw new Error(`AssertionError: Unsupported reification of defer trigger kind ${op.trigger.kind}`);
}
OpList.replace(op, deferOn(op.trigger.kind, args, op.modifier, op.sourceSpan));
break;
case OpKind.ProjectionDef:
OpList.replace(op, projectionDef(op.def));
break;
case OpKind.Projection:
if (op.handle.slot === null) {
throw new Error('No slot was assigned for project instruction');
}
let fallbackViewFnName = null;
let fallbackDecls = null;
let fallbackVars = null;
if (op.fallbackView !== null) {
if (!(unit instanceof ViewCompilationUnit)) {
throw new Error(`AssertionError: must be compiling a component`);
}
const fallbackView = unit.job.views.get(op.fallbackView);
if (fallbackView === undefined) {
throw new Error('AssertionError: projection had fallback view xref, but fallback view was not found');
}
if (fallbackView.fnName === null || fallbackView.decls === null || fallbackView.vars === null) {
throw new Error(`AssertionError: expected projection fallback view to have been named and counted`);
}
fallbackViewFnName = fallbackView.fnName;
fallbackDecls = fallbackView.decls;
fallbackVars = fallbackView.vars;
}
OpList.replace(op, projection(op.handle.slot, op.projectionSlotIndex, op.attributes, fallbackViewFnName, fallbackDecls, fallbackVars, op.sourceSpan));
break;
case OpKind.ConditionalCreate:
if (!(unit instanceof ViewCompilationUnit)) {
throw new Error(`AssertionError: must be compiling a component`);
}
if (Array.isArray(op.localRefs)) {
throw new Error(`AssertionError: local refs array should have been extracted into a constant`);
}
const conditionalCreateChildView = unit.job.views.get(op.xref);
OpList.replace(op, conditionalCreate(op.handle.slot, variable(conditionalCreateChildView.fnName), conditionalCreateChildView.decls, conditionalCreateChildView.vars, op.tag, op.attributes, op.localRefs, op.startSourceSpan));
break;
case OpKind.ConditionalBranchCreate:
if (!(unit instanceof ViewCompilationUnit)) {
throw new Error(`AssertionError: must be compiling a component`);
}
if (Array.isArray(op.localRefs)) {
throw new Error(`AssertionError: local refs array should have been extracted into a constant`);
}
const conditionalBranchCreateChildView = unit.job.views.get(op.xref);
OpList.replace(op, conditionalBranchCreate(op.handle.slot, variable(conditionalBranchCreateChildView.fnName), conditionalBranchCreateChildView.decls, conditionalBranchCreateChildView.vars, op.tag, op.attributes, op.localRefs, op.startSourceSpan));
break;
case OpKind.RepeaterCreate:
if (op.handle.slot === null) {
throw new Error('No slot was assigned for repeater instruction');
}
if (!(unit instanceof ViewCompilationUnit)) {
throw new Error(`AssertionError: must be compiling a component`);
}
const repeaterView = unit.job.views.get(op.xref);
if (repeaterView.fnName === null) {
throw new Error(`AssertionError: expected repeater primary view to have been named`);
}
let emptyViewFnName = null;
let emptyDecls = null;
let emptyVars = null;
if (op.emptyView !== null) {
const emptyView = unit.job.views.get(op.emptyView);
if (emptyView === undefined) {
throw new Error('AssertionError: repeater had empty view xref, but empty view was not found');
}
if (emptyView.fnName === null || emptyView.decls === null || emptyView.vars === null) {
throw new Error(`AssertionError: expected repeater empty view to have been named and counted`);
}
emptyViewFnName = emptyView.fnName;
emptyDecls = emptyView.decls;
emptyVars = emptyView.vars;
}
OpList.replace(op, repeaterCreate(op.handle.slot, repeaterView.fnName, op.decls, op.vars, op.tag, op.attributes, reifyTrackBy(unit, op), op.usesComponentInstance, emptyViewFnName, emptyDecls, emptyVars, op.emptyTag, op.emptyAttributes, op.wholeSourceSpan));
break;
case OpKind.SourceLocation:
const locationsLiteral = literalArr(op.locations.map(({
targetSlot,
offset,
line,
column
}) => {
if (targetSlot.slot === null) {
throw new Error('No slot was assigned for source location');
}
return literalArr([literal(targetSlot.slot), literal(offset), literal(line), literal(column)]);
}));
OpList.replace(op, attachSourceLocation(op.templatePath, locationsLiteral));
break;
case OpKind.ControlCreate:
OpList.replace(op, controlCreate(op.sourceSpan));
break;
case OpKind.Statement:
break;
default:
throw new Error(`AssertionError: Unsupported reification of create op ${OpKind[op.kind]}`);
}
}
}
function reifyUpdateOperations(unit, ops) {
for (const op of ops) {
transformExpressionsInOp(op, reifyIrExpression, VisitorContextFlag.None);
switch (op.kind) {
case OpKind.Advance:
OpList.replace(op, advance(op.delta, op.sourceSpan));
break;
case OpKind.Property:
OpList.replace(op, unit.job.mode === TemplateCompilationMode.DomOnly && op.bindingKind !== BindingKind.LegacyAnimation && op.bindingKind !== BindingKind.Animation ? reifyDomProperty(op) : reifyProperty(op));
break;
case OpKind.Control:
OpList.replace(op, reifyControl(op));
break;
case OpKind.TwoWayProperty:
OpList.replace(op, twoWayProperty(op.name, op.expression, op.sanitizer, op.sourceSpan));
break;
case OpKind.StyleProp:
OpList.replace(op, styleProp(op.name, op.expression, op.unit, op.sourceSpan));
break;
case OpKind.ClassProp:
OpList.replace(op, classProp(op.name, op.expression, op.sourceSpan));
break;
case OpKind.StyleMap:
OpList.replace(op, styleMap(op.expression, op.sourceSpan));
break;
case OpKind.ClassMap:
OpList.replace(op, classMap(op.expression, op.sourceSpan));
break;
case OpKind.I18nExpression:
OpList.replace(op, i18nExp(op.expression, op.sourceSpan));
break;
case OpKind.I18nApply:
OpList.replace(op, i18nApply(op.handle.slot, op.sourceSpan));
break;
case OpKind.InterpolateText:
OpList.replace(op, textInterpolate(op.interpolation.strings, op.interpolation.expressions, op.sourceSpan));
break;
case OpKind.Attribute:
OpList.replace(op, attribute(op.name, op.expression, op.sanitizer, op.namespace, op.sourceSpan));
break;
case OpKind.DomProperty:
if (op.expression instanceof Interpolation) {
throw new Error('not yet handled');
} else {
if (op.bindingKind === BindingKind.LegacyAnimation || op.bindingKind === BindingKind.Animation) {
OpList.replace(op, syntheticHostProperty(op.name, op.expression, op.sourceSpan));
} else {
OpList.replace(op, reifyDomProperty(op));
}
}
break;
case OpKind.Variable:
if (op.variable.name === null) {
throw new Error(`AssertionError: unnamed variable ${op.xref}`);
}
OpList.replace(op, createStatementOp(new DeclareVarStmt(op.variable.name, op.initializer, undefined, StmtModifier.Final)));
break;
case OpKind.Conditional:
if (op.processed === null) {
throw new Error(`Conditional test was not set.`);
}
OpList.replace(op, conditional(op.processed, op.contextValue, op.sourceSpan));
break;
case OpKind.Repeater:
OpList.replace(op, repeater(op.collection, op.sourceSpan));
break;
case OpKind.DeferWhen:
OpList.replace(op, deferWhen(op.modifier, op.expr, op.sourceSpan));
break;
case OpKind.StoreLet:
throw new Error(`AssertionError: unexpected storeLet ${op.declaredName}`);
case OpKind.Statement:
break;
default:
throw new Error(`AssertionError: Unsupported reification of update op ${OpKind[op.kind]}`);
}
}
}
function reifyDomProperty(op) {
return domProperty(DOM_PROPERTY_REMAPPING.get(op.name) ?? op.name, op.expression, op.sanitizer, op.sourceSpan);
}
function reifyProperty(op) {
return isAriaAttribute(op.name) ? ariaProperty(op.name, op.expression, op.sourceSpan) : property(op.name, op.expression, op.sanitizer, op.sourceSpan);
}
function reifyControl(op) {
return control(op.name, op.expression, op.sanitizer, op.sourceSpan);
}
function reifyIrExpression(expr) {
if (!isIrExpression(expr)) {
return expr;
}
switch (expr.kind) {
case ExpressionKind.NextContext:
return nextContext(expr.steps);
case ExpressionKind.Reference:
return reference(expr.targetSlot.slot + 1 + expr.offset);
case ExpressionKind.LexicalRead:
throw new Error(`AssertionError: unresolved LexicalRead of ${expr.name}`);
case ExpressionKind.TwoWayBindingSet:
throw new Error(`AssertionError: unresolved TwoWayBindingSet`);
case ExpressionKind.RestoreView:
if (typeof expr.view === 'number') {
throw new Error(`AssertionError: unresolved RestoreView`);
}
return restoreView(expr.view);
case ExpressionKind.ResetView:
return resetView(expr.expr);
case ExpressionKind.GetCurrentView:
return getCurrentView();
case ExpressionKind.ReadVariable:
if (expr.name === null) {
throw new Error(`Read of unnamed variable ${expr.xref}`);
}
return variable(expr.name);
case ExpressionKind.ReadTemporaryExpr:
if (expr.name === null) {
throw new Error(`Read of unnamed temporary ${expr.xref}`);
}
return variable(expr.name);
case ExpressionKind.AssignTemporaryExpr:
if (expr.name === null) {
throw new Error(`Assign of unnamed temporary ${expr.xref}`);
}
return variable(expr.name).set(expr.expr);
case ExpressionKind.PureFunctionExpr:
if (expr.fn === null) {
throw new Error(`AssertionError: expected PureFunctions to have been extracted`);
}
return pureFunction(expr.varOffset, expr.fn, expr.args);
case ExpressionKind.PureFunctionParameterExpr:
throw new Error(`AssertionError: expected PureFunctionParameterExpr to have been extracted`);
case ExpressionKind.PipeBinding:
return pipeBind(expr.targetSlot.slot, expr.varOffset, expr.args);
case ExpressionKind.PipeBindingVariadic:
return pipeBindV(expr.targetSlot.slot, expr.varOffset, expr.args);
case ExpressionKind.SlotLiteralExpr:
return literal(expr.slot.slot);
case ExpressionKind.ContextLetReference:
return readContextLet(expr.targetSlot.slot);
case ExpressionKind.StoreLet:
return storeLet(expr.value, expr.sourceSpan);
case ExpressionKind.TrackContext:
return variable('this');
default:
throw new Error(`AssertionError: Unsupported reification of ir.Expression kind: ${ExpressionKind[expr.kind]}`);
}
}
function reifyListenerHandler(unit, name, handlerOps, consumesDollarEvent) {
reifyUpdateOperations(unit, handlerOps);
const handlerStmts = [];
for (const op of handlerOps) {
if (op.kind !== OpKind.Statement) {
throw new Error(`AssertionError: expected reified statements, but found op ${OpKind[op.kind]}`);
}
handlerStmts.push(op.statement);
}
const params = [];
if (consumesDollarEvent) {
params.push(new FnParam('$event'));
}
return fn(params, handlerStmts, undefined, undefined, name);
}
function reifyTrackBy(unit, op) {
if (op.trackByFn !== null) {
return op.trackByFn;
}
const params = [new FnParam('$index'), new FnParam('$item')];
let fn$1;
if (op.trackByOps === null) {
fn$1 = op.usesComponentInstance ? fn(params, [new ReturnStatement(op.track)]) : arrowFn(params, op.track);
} else {
reifyUpdateOperations(unit, op.trackByOps);
const statements = [];
for (const trackOp of op.trackByOps) {
if (trackOp.kind !== OpKind.Statement) {
throw new Error(`AssertionError: expected reified statements, but found op ${OpKind[trackOp.kind]}`);
}
statements.push(trackOp.statement);
}
fn$1 = op.usesComponentInstance || statements.length !== 1 || !(statements[0] instanceof ReturnStatement) ? fn(params, statements) : arrowFn(params, statements[0].value);
}
op.trackByFn = unit.job.pool.getSharedFunctionReference(fn$1, '_forTrack');
return op.trackByFn;
}
function removeEmptyBindings(job) {
for (const unit of job.units) {
for (const op of unit.update) {
switch (op.kind) {
case OpKind.Attribute:
case OpKind.Binding:
case OpKind.ClassProp:
case OpKind.ClassMap:
case OpKind.Property:
case OpKind.StyleProp:
case OpKind.StyleMap:
if (op.expression instanceof EmptyExpr) {
OpList.remove(op);
}
break;
}
}
}
}
function removeI18nContexts(job) {
for (const unit of job.units) {
for (const op of unit.create) {
switch (op.kind) {
case OpKind.I18nContext:
OpList.remove(op);
break;
case OpKind.I18nStart:
op.context = null;
break;
}
}
}
}
function removeIllegalLetReferences(job) {
for (const unit of job.units) {
for (const op of unit.update) {
if (op.kind !== OpKind.Variable || op.variable.kind !== SemanticVariableKind.Identifier || !(op.initializer instanceof StoreLetExpr)) {
continue;
}
const name = op.variable.identifier;
let current = op;
while (current && current.kind !== OpKind.ListEnd) {
transformExpressionsInOp(current, expr => expr instanceof LexicalReadExpr && expr.name === name ? literal(undefined) : expr, VisitorContextFlag.None);
current = current.prev;
}
}
}
}
function removeUnusedI18nAttributesOps(job) {
for (const unit of job.units) {
const ownersWithI18nExpressions = new Set();
for (const op of unit.update) {
switch (op.kind) {
case OpKind.I18nExpression:
ownersWithI18nExpressions.add(op.i18nOwner);
}
}
for (const op of unit.create) {
switch (op.kind) {
case OpKind.I18nAttributes:
if (ownersWithI18nExpressions.has(op.xref)) {
continue;
}
OpList.remove(op);
}
}
}
}
function resolveContexts(job) {
for (const unit of job.units) {
processLexicalScope$1(unit, unit.create);
processLexicalScope$1(unit, unit.update);
}
}
function processLexicalScope$1(view, ops) {
const scope = new Map();
scope.set(view.xref, variable('ctx'));
for (const op of ops) {
switch (op.kind) {
case OpKind.Variable:
switch (op.variable.kind) {
case SemanticVariableKind.Context:
scope.set(op.variable.view, new ReadVariableExpr(op.xref));
break;
}
break;
case OpKind.Animation:
case OpKind.AnimationListener:
case OpKind.Listener:
case OpKind.TwoWayListener:
processLexicalScope$1(view, op.handlerOps);
break;
case OpKind.RepeaterCreate:
if (op.trackByOps !== null) {
processLexicalScope$1(view, op.trackByOps);
}
break;
}
}
if (view === view.job.root) {
scope.set(view.xref, variable('ctx'));
}
for (const op of ops) {
transformExpressionsInOp(op, expr => {
if (expr instanceof ContextExpr) {
if (!scope.has(expr.view)) {
throw new Error(`No context found for reference to view ${expr.view} from view ${view.xref}`);
}
return scope.get(expr.view);
} else {
return expr;
}
}, VisitorContextFlag.None);
}
}
function resolveDeferDepsFns(job) {
for (const unit of job.units) {
for (const op of unit.create) {
if (op.kind === OpKind.Defer) {
if (op.resolverFn !== null) {
continue;
}
if (op.ownResolverFn !== null) {
if (op.handle.slot === null) {
throw new Error('AssertionError: slot must be assigned before extracting defer deps functions');
}
const fullPathName = unit.fnName?.replace('_Template', '');
op.resolverFn = job.pool.getSharedFunctionReference(op.ownResolverFn, `${fullPathName}_Defer_${op.handle.slot}_DepsFn`, false);
}
}
}
}
}
function resolveDollarEvent(job) {
for (const unit of job.units) {
transformDollarEvent(unit.create);
transformDollarEvent(unit.update);
}
}
function transformDollarEvent(ops) {
for (const op of ops) {
if (op.kind === OpKind.Listener || op.kind === OpKind.TwoWayListener || op.kind === OpKind.AnimationListener) {
transformExpressionsInOp(op, expr => {
if (expr instanceof LexicalReadExpr && expr.name === '$event') {
if (op.kind === OpKind.Listener || op.kind === OpKind.AnimationListener) {
op.consumesDollarEvent = true;
}
return new ReadVarExpr(expr.name);
}
return expr;
}, VisitorContextFlag.InChildOperation);
}
}
}
function resolveI18nElementPlaceholders(job) {
const i18nContexts = new Map();
const elements = new Map();
for (const unit of job.units) {
for (const op of unit.create) {
switch (op.kind) {
case OpKind.I18nContext:
i18nContexts.set(op.xref, op);
break;
case OpKind.ElementStart:
elements.set(op.xref, op);
break;
}
}
}
resolvePlaceholdersForView(job, job.root, i18nContexts, elements);
}
function resolvePlaceholdersForView(job, unit, i18nContexts, elements, pendingStructuralDirective) {
let currentOps = null;
let pendingStructuralDirectiveCloses = new Map();
for (const op of unit.create) {
switch (op.kind) {
case OpKind.I18nStart:
if (!op.context) {
throw Error('Could not find i18n context for i18n op');
}
currentOps = {
i18nBlock: op,
i18nContext: i18nContexts.get(op.context)
};
break;
case OpKind.I18nEnd:
currentOps = null;
break;
case OpKind.ElementStart:
if (op.i18nPlaceholder !== undefined) {
if (currentOps === null) {
throw Error('i18n tag placeholder should only occur inside an i18n block');
}
recordElementStart(op, currentOps.i18nContext, currentOps.i18nBlock, pendingStructuralDirective);
if (pendingStructuralDirective && op.i18nPlaceholder.closeName) {
pendingStructuralDirectiveCloses.set(op.xref, pendingStructuralDirective);
}
pendingStructuralDirective = undefined;
}
break;
case OpKind.ElementEnd:
const startOp = elements.get(op.xref);
if (startOp && startOp.i18nPlaceholder !== undefined) {
if (currentOps === null) {
throw Error('AssertionError: i18n tag placeholder should only occur inside an i18n block');
}
recordElementClose(startOp, currentOps.i18nContext, currentOps.i18nBlock, pendingStructuralDirectiveCloses.get(op.xref));
pendingStructuralDirectiveCloses.delete(op.xref);
}
break;
case OpKind.Projection:
if (op.i18nPlaceholder !== undefined) {
if (currentOps === null) {
throw Error('i18n tag placeholder should only occur inside an i18n block');
}
recordElementStart(op, currentOps.i18nContext, currentOps.i18nBlock, pendingStructuralDirective);
recordElementClose(op, currentOps.i18nContext, currentOps.i18nBlock, pendingStructuralDirective);
pendingStructuralDirective = undefined;
}
if (op.fallbackView !== null) {
const view = job.views.get(op.fallbackView);
if (op.fallbackViewI18nPlaceholder === undefined) {
resolvePlaceholdersForView(job, view, i18nContexts, elements);
} else {
if (currentOps === null) {
throw Error('i18n tag placeholder should only occur inside an i18n block');
}
recordTemplateStart(job, view, op.handle.slot, op.fallbackViewI18nPlaceholder, currentOps.i18nContext, currentOps.i18nBlock, pendingStructuralDirective);
resolvePlaceholdersForView(job, view, i18nContexts, elements);
recordTemplateClose(job, view, op.handle.slot, op.fallbackViewI18nPlaceholder, currentOps.i18nContext, currentOps.i18nBlock, pendingStructuralDirective);
pendingStructuralDirective = undefined;
}
}
break;
case OpKind.ConditionalCreate:
case OpKind.ConditionalBranchCreate:
case OpKind.Template:
const view = job.views.get(op.xref);
if (op.i18nPlaceholder === undefined) {
resolvePlaceholdersForView(job, view, i18nContexts, elements);
} else {
if (currentOps === null) {
throw Error('i18n tag placeholder should only occur inside an i18n block');
}
if (op.templateKind === TemplateKind.Structural) {
resolvePlaceholdersForView(job, view, i18nContexts, elements, op);
} else {
recordTemplateStart(job, view, op.handle.slot, op.i18nPlaceholder, currentOps.i18nContext, currentOps.i18nBlock, pendingStructuralDirective);
resolvePlaceholdersForView(job, view, i18nContexts, elements);
recordTemplateClose(job, view, op.handle.slot, op.i18nPlaceholder, currentOps.i18nContext, currentOps.i18nBlock, pendingStructuralDirective);
pendingStructuralDirective = undefined;
}
}
break;
case OpKind.RepeaterCreate:
if (pendingStructuralDirective !== undefined) {
throw Error('AssertionError: Unexpected structural directive associated with @for block');
}
const forSlot = op.handle.slot + 1;
const forView = job.views.get(op.xref);
if (op.i18nPlaceholder === undefined) {
resolvePlaceholdersForView(job, forView, i18nContexts, elements);
} else {
if (currentOps === null) {
throw Error('i18n tag placeholder should only occur inside an i18n block');
}
recordTemplateStart(job, forView, forSlot, op.i18nPlaceholder, currentOps.i18nContext, currentOps.i18nBlock, pendingStructuralDirective);
resolvePlaceholdersForView(job, forView, i18nContexts, elements);
recordTemplateClose(job, forView, forSlot, op.i18nPlaceholder, currentOps.i18nContext, currentOps.i18nBlock, pendingStructuralDirective);
pendingStructuralDirective = undefined;
}
if (op.emptyView !== null) {
const emptySlot = op.handle.slot + 2;
const emptyView = job.views.get(op.emptyView);
if (op.emptyI18nPlaceholder === undefined) {
resolvePlaceholdersForView(job, emptyView, i18nContexts, elements);
} else {
if (currentOps === null) {
throw Error('i18n tag placeholder should only occur inside an i18n block');
}
recordTemplateStart(job, emptyView, emptySlot, op.emptyI18nPlaceholder, currentOps.i18nContext, currentOps.i18nBlock, pendingStructuralDirective);
resolvePlaceholdersForView(job, emptyView, i18nContexts, elements);
recordTemplateClose(job, emptyView, emptySlot, op.emptyI18nPlaceholder, currentOps.i18nContext, currentOps.i18nBlock, pendingStructuralDirective);
pendingStructuralDirective = undefined;
}
}
break;
}
}
}
function recordElementStart(op, i18nContext, i18nBlock, structuralDirective) {
const {
startName,
closeName
} = op.i18nPlaceholder;
let flags = I18nParamValueFlags.ElementTag | I18nParamValueFlags.OpenTag;
let value = op.handle.slot;
if (structuralDirective !== undefined) {
flags |= I18nParamValueFlags.TemplateTag;
value = {
element: value,
template: structuralDirective.handle.slot
};
}
if (!closeName) {
flags |= I18nParamValueFlags.CloseTag;
}
addParam(i18nContext.params, startName, value, i18nBlock.subTemplateIndex, flags);
}
function recordElementClose(op, i18nContext, i18nBlock, structuralDirective) {
const {
closeName
} = op.i18nPlaceholder;
if (closeName) {
let flags = I18nParamValueFlags.ElementTag | I18nParamValueFlags.CloseTag;
let value = op.handle.slot;
if (structuralDirective !== undefined) {
flags |= I18nParamValueFlags.TemplateTag;
value = {
element: value,
template: structuralDirective.handle.slot
};
}
addParam(i18nContext.params, closeName, value, i18nBlock.subTemplateIndex, flags);
}
}
function recordTemplateStart(job, view, slot, i18nPlaceholder, i18nContext, i18nBlock, structuralDirective) {
let {
startName,
closeName
} = i18nPlaceholder;
let flags = I18nParamValueFlags.TemplateTag | I18nParamValueFlags.OpenTag;
if (!closeName) {
flags |= I18nParamValueFlags.CloseTag;
}
if (structuralDirective !== undefined) {
addParam(i18nContext.params, startName, structuralDirective.handle.slot, i18nBlock.subTemplateIndex, flags);
}
addParam(i18nContext.params, startName, slot, getSubTemplateIndexForTemplateTag(job, i18nBlock, view), flags);
}
function recordTemplateClose(job, view, slot, i18nPlaceholder, i18nContext, i18nBlock, structuralDirective) {
const {
closeName
} = i18nPlaceholder;
const flags = I18nParamValueFlags.TemplateTag | I18nParamValueFlags.CloseTag;
if (closeName) {
addParam(i18nContext.params, closeName, slot, getSubTemplateIndexForTemplateTag(job, i18nBlock, view), flags);
if (structuralDirective !== undefined) {
addParam(i18nContext.params, closeName, structuralDirective.handle.slot, i18nBlock.subTemplateIndex, flags);
}
}
}
function getSubTemplateIndexForTemplateTag(job, i18nOp, view) {
for (const childOp of view.create) {
if (childOp.kind === OpKind.I18nStart) {
return childOp.subTemplateIndex;
}
}
return i18nOp.subTemplateIndex;
}
function addParam(params, placeholder, value, subTemplateIndex, flags) {
const values = params.get(placeholder) ?? [];
values.push({
value,
subTemplateIndex,
flags
});
params.set(placeholder, values);
}
function resolveI18nExpressionPlaceholders(job) {
const subTemplateIndices = new Map();
const i18nContexts = new Map();
const icuPlaceholders = new Map();
for (const unit of job.units) {
for (const op of unit.create) {
switch (op.kind) {
case OpKind.I18nStart:
subTemplateIndices.set(op.xref, op.subTemplateIndex);
break;
case OpKind.I18nContext:
i18nContexts.set(op.xref, op);
break;
case OpKind.IcuPlaceholder:
icuPlaceholders.set(op.xref, op);
break;
}
}
}
const expressionIndices = new Map();
const referenceIndex = op => op.usage === I18nExpressionFor.I18nText ? op.i18nOwner : op.context;
for (const unit of job.units) {
for (const op of unit.update) {
if (op.kind === OpKind.I18nExpression) {
const index = expressionIndices.get(referenceIndex(op)) || 0;
const subTemplateIndex = subTemplateIndices.get(op.i18nOwner) ?? null;
const value = {
value: index,
subTemplateIndex: subTemplateIndex,
flags: I18nParamValueFlags.ExpressionIndex
};
updatePlaceholder(op, value, i18nContexts, icuPlaceholders);
expressionIndices.set(referenceIndex(op), index + 1);
}
}
}
}
function updatePlaceholder(op, value, i18nContexts, icuPlaceholders) {
if (op.i18nPlaceholder !== null) {
const i18nContext = i18nContexts.get(op.context);
const params = op.resolutionTime === I18nParamResolutionTime.Creation ? i18nContext.params : i18nContext.postprocessingParams;
const values = params.get(op.i18nPlaceholder) || [];
values.push(value);
params.set(op.i18nPlaceholder, values);
}
if (op.icuPlaceholder !== null) {
const icuPlaceholderOp = icuPlaceholders.get(op.icuPlaceholder);
icuPlaceholderOp?.expressionPlaceholders.push(value);
}
}
function resolveNames(job) {
for (const unit of job.units) {
processLexicalScope(unit, unit.create, null);
processLexicalScope(unit, unit.update, null);
}
}
function processLexicalScope(unit, ops, savedView) {
const scope = new Map();
const localDefinitions = new Map();
for (const op of ops) {
switch (op.kind) {
case OpKind.Variable:
switch (op.variable.kind) {
case SemanticVariableKind.Identifier:
if (op.variable.local) {
if (localDefinitions.has(op.variable.identifier)) {
continue;
}
localDefinitions.set(op.variable.identifier, op.xref);
} else if (scope.has(op.variable.identifier)) {
continue;
}
scope.set(op.variable.identifier, op.xref);
break;
case SemanticVariableKind.Alias:
if (scope.has(op.variable.identifier)) {
continue;
}
scope.set(op.variable.identifier, op.xref);
break;
case SemanticVariableKind.SavedView:
savedView = {
view: op.variable.view,
variable: op.xref
};
break;
}
break;
case OpKind.Animation:
case OpKind.AnimationListener:
case OpKind.Listener:
case OpKind.TwoWayListener:
processLexicalScope(unit, op.handlerOps, savedView);
break;
case OpKind.RepeaterCreate:
if (op.trackByOps !== null) {
processLexicalScope(unit, op.trackByOps, savedView);
}
break;
}
}
for (const op of ops) {
if (op.kind == OpKind.Listener || op.kind === OpKind.TwoWayListener || op.kind === OpKind.Animation || op.kind === OpKind.AnimationListener) {
continue;
}
transformExpressionsInOp(op, expr => {
if (expr instanceof LexicalReadExpr) {
if (localDefinitions.has(expr.name)) {
return new ReadVariableExpr(localDefinitions.get(expr.name));
} else if (scope.has(expr.name)) {
return new ReadVariableExpr(scope.get(expr.name));
} else {
return new ReadPropExpr(new ContextExpr(unit.job.root.xref), expr.name);
}
} else if (expr instanceof RestoreViewExpr && typeof expr.view === 'number') {
if (savedView === null || savedView.view !== expr.view) {
throw new Error(`AssertionError: no saved view ${expr.view} from view ${unit.xref}`);
}
expr.view = new ReadVariableExpr(savedView.variable);
return expr;
} else {
return expr;
}
}, VisitorContextFlag.None);
}
for (const op of ops) {
visitExpressionsInOp(op, expr => {
if (expr instanceof LexicalReadExpr) {
throw new Error(`AssertionError: no lexical reads should remain, but found read of ${expr.name}`);
}
});
}
}
const sanitizerFns = new Map([[SecurityContext.HTML, Identifiers.sanitizeHtml], [SecurityContext.RESOURCE_URL, Identifiers.sanitizeResourceUrl], [SecurityContext.SCRIPT, Identifiers.sanitizeScript], [SecurityContext.STYLE, Identifiers.sanitizeStyle], [SecurityContext.URL, Identifiers.sanitizeUrl], [SecurityContext.ATTRIBUTE_NO_BINDING, Identifiers.validateAttribute]]);
const trustedValueFns = new Map([[SecurityContext.HTML, Identifiers.trustConstantHtml], [SecurityContext.RESOURCE_URL, Identifiers.trustConstantResourceUrl]]);
function resolveSanitizers(job) {
for (const unit of job.units) {
if (job.kind !== CompilationJobKind.Host) {
for (const op of unit.create) {
if (op.kind === OpKind.ExtractedAttribute) {
const trustedValueFn = trustedValueFns.get(getOnlySecurityContext(op.securityContext)) ?? null;
op.trustedValueFn = trustedValueFn !== null ? importExpr(trustedValueFn) : null;
}
}
}
for (const op of unit.update) {
switch (op.kind) {
case OpKind.Property:
case OpKind.Attribute:
case OpKind.DomProperty:
let sanitizerFn = null;
if (Array.isArray(op.securityContext) && op.securityContext.length === 2 && op.securityContext.includes(SecurityContext.URL) && op.securityContext.includes(SecurityContext.RESOURCE_URL)) {
sanitizerFn = Identifiers.sanitizeUrlOrResourceUrl;
} else {
sanitizerFn = sanitizerFns.get(getOnlySecurityContext(op.securityContext)) ?? null;
}
op.sanitizer = sanitizerFn !== null ? importExpr(sanitizerFn) : null;
break;
}
}
}
}
function getOnlySecurityContext(securityContext) {
if (Array.isArray(securityContext)) {
if (securityContext.length > 1) {
throw Error(`AssertionError: Ambiguous security context`);
}
return securityContext[0] || SecurityContext.NONE;
}
return securityContext;
}
function saveAndRestoreView(job) {
for (const unit of job.units) {
unit.create.prepend([createVariableOp(unit.job.allocateXrefId(), {
kind: SemanticVariableKind.SavedView,
name: null,
view: unit.xref
}, new GetCurrentViewExpr(), VariableFlags.None)]);
for (const op of unit.create) {
if (op.kind !== OpKind.Listener && op.kind !== OpKind.TwoWayListener && op.kind !== OpKind.Animation && op.kind !== OpKind.AnimationListener) {
continue;
}
let needsRestoreView = unit !== job.root;
if (!needsRestoreView) {
for (const handlerOp of op.handlerOps) {
visitExpressionsInOp(handlerOp, expr => {
if (expr instanceof ReferenceExpr || expr instanceof ContextLetReferenceExpr) {
needsRestoreView = true;
}
});
}
}
if (needsRestoreView) {
addSaveRestoreViewOperationToListener(unit, op);
}
}
}
}
function addSaveRestoreViewOperationToListener(unit, op) {
op.handlerOps.prepend([createVariableOp(unit.job.allocateXrefId(), {
kind: SemanticVariableKind.Context,
name: null,
view: unit.xref
}, new RestoreViewExpr(unit.xref), VariableFlags.None)]);
for (const handlerOp of op.handlerOps) {
if (handlerOp.kind === OpKind.Statement && handlerOp.statement instanceof ReturnStatement) {
handlerOp.statement.value = new ResetViewExpr(handlerOp.statement.value);
}
}
}
function allocateSlots(job) {
const slotMap = new Map();
for (const unit of job.units) {
let slotCount = 0;
for (const op of unit.create) {
if (!hasConsumesSlotTrait(op)) {
continue;
}
op.handle.slot = slotCount;
slotMap.set(op.xref, op.handle.slot);
slotCount += op.numSlotsUsed;
}
unit.decls = slotCount;
}
for (const unit of job.units) {
for (const op of unit.ops()) {
if (op.kind === OpKind.Template || op.kind === OpKind.ConditionalCreate || op.kind === OpKind.ConditionalBranchCreate || op.kind === OpKind.RepeaterCreate) {
const childView = job.views.get(op.xref);
op.decls = childView.decls;
}
}
}
}
function optimizeStoreLet(job) {
const letUsedExternally = new Set();
const declareLetOps = new Map();
for (const unit of job.units) {
for (const op of unit.ops()) {
if (op.kind === OpKind.DeclareLet) {
declareLetOps.set(op.xref, op);
}
visitExpressionsInOp(op, expr => {
if (expr instanceof ContextLetReferenceExpr) {
letUsedExternally.add(expr.target);
}
});
}
}
for (const unit of job.units) {
for (const op of unit.update) {
transformExpressionsInOp(op, expr => {
if (expr instanceof StoreLetExpr && !letUsedExternally.has(expr.target)) {
if (!hasPipe(expr)) {
OpList.remove(declareLetOps.get(expr.target));
}
return expr.value;
}
return expr;
}, VisitorContextFlag.None);
}
}
}
function hasPipe(root) {
let result = false;
transformExpressionsInExpression(root, expr => {
if (expr instanceof PipeBindingExpr || expr instanceof PipeBindingVariadicExpr) {
result = true;
}
return expr;
}, VisitorContextFlag.None);
return result;
}
function stripNonrequiredParentheses(job) {
const requiredParens = new Set();
for (const unit of job.units) {
for (const op of unit.ops()) {
visitExpressionsInOp(op, expr => {
if (expr instanceof BinaryOperatorExpr) {
switch (expr.operator) {
case BinaryOperator.Exponentiation:
checkExponentiationParens(expr, requiredParens);
break;
case BinaryOperator.NullishCoalesce:
checkNullishCoalescingParens(expr, requiredParens);
break;
case BinaryOperator.And:
case BinaryOperator.Or:
checkAndOrParens(expr, requiredParens);
}
}
});
}
}
for (const unit of job.units) {
for (const op of unit.ops()) {
transformExpressionsInOp(op, expr => {
if (expr instanceof ParenthesizedExpr) {
return requiredParens.has(expr) ? expr : expr.expr;
}
return expr;
}, VisitorContextFlag.None);
}
}
}
function checkExponentiationParens(expr, requiredParens) {
if (expr.lhs instanceof ParenthesizedExpr && expr.lhs.expr instanceof UnaryOperatorExpr) {
requiredParens.add(expr.lhs);
}
}
function checkNullishCoalescingParens(expr, requiredParens) {
if (expr.lhs instanceof ParenthesizedExpr && (isLogicalAndOr(expr.lhs.expr) || expr.lhs.expr instanceof ConditionalExpr)) {
requiredParens.add(expr.lhs);
}
if (expr.rhs instanceof ParenthesizedExpr && (isLogicalAndOr(expr.rhs.expr) || expr.rhs.expr instanceof ConditionalExpr)) {
requiredParens.add(expr.rhs);
}
}
function checkAndOrParens(expr, requiredParens) {
if (expr.lhs instanceof ParenthesizedExpr && expr.lhs.expr instanceof BinaryOperatorExpr && expr.lhs.expr.operator === BinaryOperator.NullishCoalesce) {
requiredParens.add(expr.lhs);
}
}
function isLogicalAndOr(expr) {
return expr instanceof BinaryOperatorExpr && (expr.operator === BinaryOperator.And || expr.operator === BinaryOperator.Or);
}
function specializeStyleBindings(job) {
for (const unit of job.units) {
for (const op of unit.update) {
if (op.kind !== OpKind.Binding) {
continue;
}
switch (op.bindingKind) {
case BindingKind.ClassName:
if (op.expression instanceof Interpolation) {
throw new Error(`Unexpected interpolation in ClassName binding`);
}
OpList.replace(op, createClassPropOp(op.target, op.name, op.expression, op.sourceSpan));
break;
case BindingKind.StyleProperty:
OpList.replace(op, createStylePropOp(op.target, op.name, op.expression, op.unit, op.sourceSpan));
break;
case BindingKind.Property:
case BindingKind.Template:
if (op.name === 'style') {
OpList.replace(op, createStyleMapOp(op.target, op.expression, op.sourceSpan));
} else if (op.name === 'class') {
OpList.replace(op, createClassMapOp(op.target, op.expression, op.sourceSpan));
}
break;
}
}
}
}
function generateTemporaryVariables(job) {
for (const unit of job.units) {
unit.create.prepend(generateTemporaries(unit.create));
unit.update.prepend(generateTemporaries(unit.update));
}
}
function generateTemporaries(ops) {
let opCount = 0;
let generatedStatements = [];
for (const op of ops) {
const finalReads = new Map();
visitExpressionsInOp(op, (expr, flag) => {
if (flag & VisitorContextFlag.InChildOperation) {
return;
}
if (expr instanceof ReadTemporaryExpr) {
finalReads.set(expr.xref, expr);
}
});
let count = 0;
const assigned = new Set();
const released = new Set();
const defs = new Map();
visitExpressionsInOp(op, (expr, flag) => {
if (flag & VisitorContextFlag.InChildOperation) {
return;
}
if (expr instanceof AssignTemporaryExpr) {
if (!assigned.has(expr.xref)) {
assigned.add(expr.xref);
defs.set(expr.xref, `tmp_${opCount}_${count++}`);
}
assignName(defs, expr);
} else if (expr instanceof ReadTemporaryExpr) {
if (finalReads.get(expr.xref) === expr) {
released.add(expr.xref);
count--;
}
assignName(defs, expr);
}
});
generatedStatements.push(...Array.from(new Set(defs.values())).map(name => createStatementOp(new DeclareVarStmt(name))));
opCount++;
if (op.kind === OpKind.Listener || op.kind === OpKind.Animation || op.kind === OpKind.AnimationListener || op.kind === OpKind.TwoWayListener) {
op.handlerOps.prepend(generateTemporaries(op.handlerOps));
} else if (op.kind === OpKind.RepeaterCreate && op.trackByOps !== null) {
op.trackByOps.prepend(generateTemporaries(op.trackByOps));
}
}
return generatedStatements;
}
function assignName(names, expr) {
const name = names.get(expr.xref);
if (name === undefined) {
throw new Error(`Found xref with unassigned name: ${expr.xref}`);
}
expr.name = name;
}
function optimizeTrackFns(job) {
for (const unit of job.units) {
for (const op of unit.create) {
if (op.kind !== OpKind.RepeaterCreate) {
continue;
}
if (op.track instanceof ReadVarExpr && op.track.name === '$index') {
op.trackByFn = importExpr(Identifiers.repeaterTrackByIndex);
} else if (op.track instanceof ReadVarExpr && op.track.name === '$item') {
op.trackByFn = importExpr(Identifiers.repeaterTrackByIdentity);
} else if (isTrackByFunctionCall(job.root.xref, op.track)) {
op.usesComponentInstance = true;
if (op.track.receiver.receiver.view === unit.xref) {
op.trackByFn = op.track.receiver;
} else {
op.trackByFn = importExpr(Identifiers.componentInstance).callFn([]).prop(op.track.receiver.name);
op.track = op.trackByFn;
}
} else {
op.track = transformExpressionsInExpression(op.track, expr => {
if (expr instanceof PipeBindingExpr || expr instanceof PipeBindingVariadicExpr) {
throw new Error(`Illegal State: Pipes are not allowed in this context`);
} else if (expr instanceof ContextExpr) {
op.usesComponentInstance = true;
return new TrackContextExpr(expr.view);
}
return expr;
}, VisitorContextFlag.None);
const trackOpList = new OpList();
trackOpList.push(createStatementOp(new ReturnStatement(op.track, op.track.sourceSpan)));
op.trackByOps = trackOpList;
}
}
}
}
function isTrackByFunctionCall(rootView, expr) {
if (!(expr instanceof InvokeFunctionExpr) || expr.args.length === 0 || expr.args.length > 2) {
return false;
}
if (!(expr.receiver instanceof ReadPropExpr && expr.receiver.receiver instanceof ContextExpr) || expr.receiver.receiver.view !== rootView) {
return false;
}
const [arg0, arg1] = expr.args;
if (!(arg0 instanceof ReadVarExpr) || arg0.name !== '$index') {
return false;
} else if (expr.args.length === 1) {
return true;
}
if (!(arg1 instanceof ReadVarExpr) || arg1.name !== '$item') {
return false;
}
return true;
}
function generateTrackVariables(job) {
for (const unit of job.units) {
for (const op of unit.create) {
if (op.kind !== OpKind.RepeaterCreate) {
continue;
}
op.track = transformExpressionsInExpression(op.track, expr => {
if (expr instanceof LexicalReadExpr) {
if (op.varNames.$index.has(expr.name)) {
return variable('$index');
} else if (expr.name === op.varNames.$implicit) {
return variable('$item');
}
}
return expr;
}, VisitorContextFlag.None);
}
}
}
function transformTwoWayBindingSet(job) {
for (const unit of job.units) {
for (const op of unit.create) {
if (op.kind === OpKind.TwoWayListener) {
transformExpressionsInOp(op, expr => {
if (!(expr instanceof TwoWayBindingSetExpr)) {
return expr;
}
const {
target,
value
} = expr;
if (target instanceof ReadPropExpr || target instanceof ReadKeyExpr) {
return twoWayBindingSet(target, value).or(target.set(value));
}
if (target instanceof ReadVariableExpr) {
return twoWayBindingSet(target, value);
}
throw new Error(`Unsupported expression in two-way action binding.`);
}, VisitorContextFlag.InChildOperation);
}
}
}
}
function countVariables(job) {
for (const unit of job.units) {
let varCount = 0;
for (const op of unit.ops()) {
if (hasConsumesVarsTrait(op)) {
varCount += varsUsedByOp(op);
}
}
for (const op of unit.ops()) {
visitExpressionsInOp(op, expr => {
if (!isIrExpression(expr)) {
return;
}
if (job.compatibility === CompatibilityMode.TemplateDefinitionBuilder && expr instanceof PureFunctionExpr) {
return;
}
if (hasUsesVarOffsetTrait(expr)) {
expr.varOffset = varCount;
}
if (hasConsumesVarsTrait(expr)) {
varCount += varsUsedByIrExpression(expr);
}
});
}
if (job.compatibility === CompatibilityMode.TemplateDefinitionBuilder) {
for (const op of unit.ops()) {
visitExpressionsInOp(op, expr => {
if (!isIrExpression(expr) || !(expr instanceof PureFunctionExpr)) {
return;
}
if (hasUsesVarOffsetTrait(expr)) {
expr.varOffset = varCount;
}
if (hasConsumesVarsTrait(expr)) {
varCount += varsUsedByIrExpression(expr);
}
});
}
}
unit.vars = varCount;
}
if (job instanceof ComponentCompilationJob) {
for (const unit of job.units) {
for (const op of unit.create) {
if (op.kind !== OpKind.Template && op.kind !== OpKind.RepeaterCreate && op.kind !== OpKind.ConditionalCreate && op.kind !== OpKind.ConditionalBranchCreate) {
continue;
}
const childView = job.views.get(op.xref);
op.vars = childView.vars;
}
}
}
}
function varsUsedByOp(op) {
let slots;
switch (op.kind) {
case OpKind.Attribute:
slots = 1;
if (op.expression instanceof Interpolation && !isSingletonInterpolation(op.expression)) {
slots += op.expression.expressions.length;
}
return slots;
case OpKind.Property:
case OpKind.DomProperty:
slots = 1;
if (op.expression instanceof Interpolation) {
slots += op.expression.expressions.length;
}
return slots;
case OpKind.Control:
return 2;
case OpKind.TwoWayProperty:
return 1;
case OpKind.StyleProp:
case OpKind.ClassProp:
case OpKind.StyleMap:
case OpKind.ClassMap:
slots = 2;
if (op.expression instanceof Interpolation) {
slots += op.expression.expressions.length;
}
return slots;
case OpKind.InterpolateText:
return op.interpolation.expressions.length;
case OpKind.I18nExpression:
case OpKind.Conditional:
case OpKind.DeferWhen:
case OpKind.StoreLet:
return 1;
case OpKind.RepeaterCreate:
return op.emptyView ? 1 : 0;
default:
throw new Error(`Unhandled op: ${OpKind[op.kind]}`);
}
}
function varsUsedByIrExpression(expr) {
switch (expr.kind) {
case ExpressionKind.PureFunctionExpr:
return 1 + expr.args.length;
case ExpressionKind.PipeBinding:
return 1 + expr.args.length;
case ExpressionKind.PipeBindingVariadic:
return 1 + expr.numArgs;
case ExpressionKind.StoreLet:
return 1;
default:
throw new Error(`AssertionError: unhandled ConsumesVarsTrait expression ${expr.constructor.name}`);
}
}
function isSingletonInterpolation(expr) {
if (expr.expressions.length !== 1 || expr.strings.length !== 2) {
return false;
}
if (expr.strings[0] !== '' || expr.strings[1] !== '') {
return false;
}
return true;
}
function optimizeVariables(job) {
for (const unit of job.units) {
inlineAlwaysInlineVariables(unit.create);
inlineAlwaysInlineVariables(unit.update);
for (const op of unit.create) {
if (op.kind === OpKind.Listener || op.kind === OpKind.Animation || op.kind === OpKind.AnimationListener || op.kind === OpKind.TwoWayListener) {
inlineAlwaysInlineVariables(op.handlerOps);
} else if (op.kind === OpKind.RepeaterCreate && op.trackByOps !== null) {
inlineAlwaysInlineVariables(op.trackByOps);
}
}
optimizeVariablesInOpList(unit.create, job.compatibility);
optimizeVariablesInOpList(unit.update, job.compatibility);
for (const op of unit.create) {
if (op.kind === OpKind.Listener || op.kind === OpKind.Animation || op.kind === OpKind.AnimationListener || op.kind === OpKind.TwoWayListener) {
optimizeVariablesInOpList(op.handlerOps, job.compatibility);
} else if (op.kind === OpKind.RepeaterCreate && op.trackByOps !== null) {
optimizeVariablesInOpList(op.trackByOps, job.compatibility);
}
}
}
}
var Fence;
(function (Fence) {
Fence[Fence["None"] = 0] = "None";
Fence[Fence["ViewContextRead"] = 1] = "ViewContextRead";
Fence[Fence["ViewContextWrite"] = 2] = "ViewContextWrite";
Fence[Fence["SideEffectful"] = 4] = "SideEffectful";
})(Fence || (Fence = {}));
function inlineAlwaysInlineVariables(ops) {
const vars = new Map();
for (const op of ops) {
if (op.kind === OpKind.Variable && op.flags & VariableFlags.AlwaysInline) {
visitExpressionsInOp(op, expr => {
if (isIrExpression(expr) && fencesForIrExpression(expr) !== Fence.None) {
throw new Error(`AssertionError: A context-sensitive variable was marked AlwaysInline`);
}
});
vars.set(op.xref, op);
}
transformExpressionsInOp(op, expr => {
if (expr instanceof ReadVariableExpr && vars.has(expr.xref)) {
const varOp = vars.get(expr.xref);
return varOp.initializer.clone();
}
return expr;
}, VisitorContextFlag.None);
}
for (const op of vars.values()) {
OpList.remove(op);
}
}
function optimizeVariablesInOpList(ops, compatibility) {
const varDecls = new Map();
const varUsages = new Map();
const varRemoteUsages = new Set();
const opMap = new Map();
for (const op of ops) {
if (op.kind === OpKind.Variable) {
if (varDecls.has(op.xref) || varUsages.has(op.xref)) {
throw new Error(`Should not see two declarations of the same variable: ${op.xref}`);
}
varDecls.set(op.xref, op);
varUsages.set(op.xref, 0);
}
opMap.set(op, collectOpInfo(op));
countVariableUsages(op, varUsages, varRemoteUsages);
}
let contextIsUsed = false;
for (const op of ops.reversed()) {
const opInfo = opMap.get(op);
if (op.kind === OpKind.Variable && varUsages.get(op.xref) === 0) {
if (contextIsUsed && opInfo.fences & Fence.ViewContextWrite || opInfo.fences & Fence.SideEffectful) {
const stmtOp = createStatementOp(op.initializer.toStmt());
opMap.set(stmtOp, opInfo);
OpList.replace(op, stmtOp);
} else {
uncountVariableUsages(op, varUsages);
OpList.remove(op);
}
opMap.delete(op);
varDecls.delete(op.xref);
varUsages.delete(op.xref);
continue;
}
if (opInfo.fences & Fence.ViewContextRead) {
contextIsUsed = true;
}
}
const toInline = [];
for (const [id, count] of varUsages) {
const decl = varDecls.get(id);
const isAlwaysInline = !!(decl.flags & VariableFlags.AlwaysInline);
if (count !== 1 || isAlwaysInline) {
continue;
}
if (varRemoteUsages.has(id)) {
continue;
}
toInline.push(id);
}
let candidate;
while (candidate = toInline.pop()) {
const decl = varDecls.get(candidate);
const varInfo = opMap.get(decl);
const isAlwaysInline = !!(decl.flags & VariableFlags.AlwaysInline);
if (isAlwaysInline) {
throw new Error(`AssertionError: Found an 'AlwaysInline' variable after the always inlining pass.`);
}
for (let targetOp = decl.next; targetOp.kind !== OpKind.ListEnd; targetOp = targetOp.next) {
const opInfo = opMap.get(targetOp);
if (opInfo.variablesUsed.has(candidate)) {
if (compatibility === CompatibilityMode.TemplateDefinitionBuilder && !allowConservativeInlining(decl, targetOp)) {
break;
}
if (tryInlineVariableInitializer(candidate, decl.initializer, targetOp, varInfo.fences)) {
opInfo.variablesUsed.delete(candidate);
for (const id of varInfo.variablesUsed) {
opInfo.variablesUsed.add(id);
}
opInfo.fences |= varInfo.fences;
varDecls.delete(candidate);
varUsages.delete(candidate);
opMap.delete(decl);
OpList.remove(decl);
}
break;
}
if (!safeToInlinePastFences(opInfo.fences, varInfo.fences)) {
break;
}
}
}
}
function fencesForIrExpression(expr) {
switch (expr.kind) {
case ExpressionKind.NextContext:
return Fence.ViewContextRead | Fence.ViewContextWrite;
case ExpressionKind.RestoreView:
return Fence.ViewContextRead | Fence.ViewContextWrite | Fence.SideEffectful;
case ExpressionKind.StoreLet:
return Fence.SideEffectful;
case ExpressionKind.Reference:
case ExpressionKind.ContextLetReference:
return Fence.ViewContextRead;
default:
return Fence.None;
}
}
function collectOpInfo(op) {
let fences = Fence.None;
const variablesUsed = new Set();
visitExpressionsInOp(op, expr => {
if (!isIrExpression(expr)) {
return;
}
switch (expr.kind) {
case ExpressionKind.ReadVariable:
variablesUsed.add(expr.xref);
break;
default:
fences |= fencesForIrExpression(expr);
}
});
return {
fences,
variablesUsed
};
}
function countVariableUsages(op, varUsages, varRemoteUsage) {
visitExpressionsInOp(op, (expr, flags) => {
if (!isIrExpression(expr)) {
return;
}
if (expr.kind !== ExpressionKind.ReadVariable) {
return;
}
const count = varUsages.get(expr.xref);
if (count === undefined) {
return;
}
varUsages.set(expr.xref, count + 1);
if (flags & VisitorContextFlag.InChildOperation) {
varRemoteUsage.add(expr.xref);
}
});
}
function uncountVariableUsages(op, varUsages) {
visitExpressionsInOp(op, expr => {
if (!isIrExpression(expr)) {
return;
}
if (expr.kind !== ExpressionKind.ReadVariable) {
return;
}
const count = varUsages.get(expr.xref);
if (count === undefined) {
return;
} else if (count === 0) {
throw new Error(`Inaccurate variable count: ${expr.xref} - found another read but count is already 0`);
}
varUsages.set(expr.xref, count - 1);
});
}
function safeToInlinePastFences(fences, declFences) {
if (fences & Fence.ViewContextWrite) {
if (declFences & Fence.ViewContextRead) {
return false;
}
} else if (fences & Fence.ViewContextRead) {
if (declFences & Fence.ViewContextWrite) {
return false;
}
}
return true;
}
function tryInlineVariableInitializer(id, initializer, target, declFences) {
let inlined = false;
let inliningAllowed = true;
transformExpressionsInOp(target, (expr, flags) => {
if (!isIrExpression(expr)) {
return expr;
}
if (inlined || !inliningAllowed) {
return expr;
} else if (flags & VisitorContextFlag.InChildOperation && declFences & Fence.ViewContextRead) {
return expr;
}
switch (expr.kind) {
case ExpressionKind.ReadVariable:
if (expr.xref === id) {
inlined = true;
return initializer;
}
break;
default:
const exprFences = fencesForIrExpression(expr);
inliningAllowed = inliningAllowed && safeToInlinePastFences(exprFences, declFences);
break;
}
return expr;
}, VisitorContextFlag.None);
return inlined;
}
function allowConservativeInlining(decl, target) {
switch (decl.variable.kind) {
case SemanticVariableKind.Identifier:
if (decl.initializer instanceof ReadVarExpr && decl.initializer.name === 'ctx') {
return true;
}
return false;
case SemanticVariableKind.Context:
return target.kind === OpKind.Variable;
default:
return true;
}
}
function wrapI18nIcus(job) {
for (const unit of job.units) {
let currentI18nOp = null;
let addedI18nId = null;
for (const op of unit.create) {
switch (op.kind) {
case OpKind.I18nStart:
currentI18nOp = op;
break;
case OpKind.I18nEnd:
currentI18nOp = null;
break;
case OpKind.IcuStart:
if (currentI18nOp === null) {
addedI18nId = job.allocateXrefId();
OpList.insertBefore(createI18nStartOp(addedI18nId, op.message, undefined, null), op);
}
break;
case OpKind.IcuEnd:
if (addedI18nId !== null) {
OpList.insertAfter(createI18nEndOp(addedI18nId, null), op);
addedI18nId = null;
}
break;
}
}
}
}
/**
*
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
const phases = [{
kind: CompilationJobKind.Tmpl,
fn: removeContentSelectors
}, {
kind: CompilationJobKind.Both,
fn: optimizeRegularExpressions
}, {
kind: CompilationJobKind.Host,
fn: parseHostStyleProperties
}, {
kind: CompilationJobKind.Tmpl,
fn: emitNamespaceChanges
}, {
kind: CompilationJobKind.Tmpl,
fn: propagateI18nBlocks
}, {
kind: CompilationJobKind.Tmpl,
fn: wrapI18nIcus
}, {
kind: CompilationJobKind.Both,
fn: deduplicateTextBindings
}, {
kind: CompilationJobKind.Both,
fn: specializeStyleBindings
}, {
kind: CompilationJobKind.Both,
fn: specializeBindings
}, {
kind: CompilationJobKind.Both,
fn: convertAnimations
}, {
kind: CompilationJobKind.Both,
fn: extractAttributes
}, {
kind: CompilationJobKind.Tmpl,
fn: createI18nContexts
}, {
kind: CompilationJobKind.Both,
fn: parseExtractedStyles
}, {
kind: CompilationJobKind.Tmpl,
fn: removeEmptyBindings
}, {
kind: CompilationJobKind.Both,
fn: collapseSingletonInterpolations
}, {
kind: CompilationJobKind.Both,
fn: orderOps
}, {
kind: CompilationJobKind.Tmpl,
fn: generateConditionalExpressions
}, {
kind: CompilationJobKind.Tmpl,
fn: createPipes
}, {
kind: CompilationJobKind.Tmpl,
fn: configureDeferInstructions
}, {
kind: CompilationJobKind.Tmpl,
fn: createVariadicPipes
}, {
kind: CompilationJobKind.Both,
fn: generatePureLiteralStructures
}, {
kind: CompilationJobKind.Tmpl,
fn: generateProjectionDefs
}, {
kind: CompilationJobKind.Tmpl,
fn: generateLocalLetReferences
}, {
kind: CompilationJobKind.Tmpl,
fn: generateVariables
}, {
kind: CompilationJobKind.Tmpl,
fn: saveAndRestoreView
}, {
kind: CompilationJobKind.Both,
fn: deleteAnyCasts
}, {
kind: CompilationJobKind.Both,
fn: resolveDollarEvent
}, {
kind: CompilationJobKind.Tmpl,
fn: generateTrackVariables
}, {
kind: CompilationJobKind.Tmpl,
fn: removeIllegalLetReferences
}, {
kind: CompilationJobKind.Both,
fn: resolveNames
}, {
kind: CompilationJobKind.Tmpl,
fn: resolveDeferTargetNames
}, {
kind: CompilationJobKind.Tmpl,
fn: transformTwoWayBindingSet
}, {
kind: CompilationJobKind.Tmpl,
fn: optimizeTrackFns
}, {
kind: CompilationJobKind.Both,
fn: resolveContexts
}, {
kind: CompilationJobKind.Both,
fn: resolveSanitizers
}, {
kind: CompilationJobKind.Tmpl,
fn: liftLocalRefs
}, {
kind: CompilationJobKind.Both,
fn: expandSafeReads
}, {
kind: CompilationJobKind.Both,
fn: stripNonrequiredParentheses
}, {
kind: CompilationJobKind.Both,
fn: generateTemporaryVariables
}, {
kind: CompilationJobKind.Both,
fn: optimizeVariables
}, {
kind: CompilationJobKind.Both,
fn: optimizeStoreLet
}, {
kind: CompilationJobKind.Tmpl,
fn: convertI18nText
}, {
kind: CompilationJobKind.Tmpl,
fn: convertI18nBindings
}, {
kind: CompilationJobKind.Tmpl,
fn: removeUnusedI18nAttributesOps
}, {
kind: CompilationJobKind.Tmpl,
fn: assignI18nSlotDependencies
}, {
kind: CompilationJobKind.Tmpl,
fn: applyI18nExpressions
}, {
kind: CompilationJobKind.Tmpl,
fn: allocateSlots
}, {
kind: CompilationJobKind.Tmpl,
fn: resolveI18nElementPlaceholders
}, {
kind: CompilationJobKind.Tmpl,
fn: resolveI18nExpressionPlaceholders
}, {
kind: CompilationJobKind.Tmpl,
fn: extractI18nMessages
}, {
kind: CompilationJobKind.Tmpl,
fn: collectI18nConsts
}, {
kind: CompilationJobKind.Tmpl,
fn: collectConstExpressions
}, {
kind: CompilationJobKind.Both,
fn: collectElementConsts
}, {
kind: CompilationJobKind.Tmpl,
fn: removeI18nContexts
}, {
kind: CompilationJobKind.Both,
fn: countVariables
}, {
kind: CompilationJobKind.Tmpl,
fn: generateAdvance
}, {
kind: CompilationJobKind.Both,
fn: nameFunctionsAndVariables
}, {
kind: CompilationJobKind.Tmpl,
fn: resolveDeferDepsFns
}, {
kind: CompilationJobKind.Tmpl,
fn: mergeNextContextExpressions
}, {
kind: CompilationJobKind.Tmpl,
fn: generateNgContainerOps
}, {
kind: CompilationJobKind.Tmpl,
fn: collapseEmptyInstructions
}, {
kind: CompilationJobKind.Tmpl,
fn: attachSourceLocations
}, {
kind: CompilationJobKind.Tmpl,
fn: disableBindings$1
}, {
kind: CompilationJobKind.Both,
fn: extractPureFunctions
}, {
kind: CompilationJobKind.Both,
fn: reify
}, {
kind: CompilationJobKind.Both,
fn: chain
}];
function transform(job, kind) {
for (const phase of phases) {
if (phase.kind === kind || phase.kind === CompilationJobKind.Both) {
phase.fn(job);
}
}
}
function emitTemplateFn(tpl, pool) {
const rootFn = emitView(tpl.root);
emitChildViews(tpl.root, pool);
return rootFn;
}
function emitChildViews(parent, pool) {
for (const unit of parent.job.units) {
if (unit.parent !== parent.xref) {
continue;
}
emitChildViews(unit, pool);
const viewFn = emitView(unit);
pool.statements.push(viewFn.toDeclStmt(viewFn.name));
}
}
function emitView(view) {
if (view.fnName === null) {
throw new Error(`AssertionError: view ${view.xref} is unnamed`);
}
const createStatements = [];
for (const op of view.create) {
if (op.kind !== OpKind.Statement) {
throw new Error(`AssertionError: expected all create ops to have been compiled, but got ${OpKind[op.kind]}`);
}
createStatements.push(op.statement);
}
const updateStatements = [];
for (const op of view.update) {
if (op.kind !== OpKind.Statement) {
throw new Error(`AssertionError: expected all update ops to have been compiled, but got ${OpKind[op.kind]}`);
}
updateStatements.push(op.statement);
}
const createCond = maybeGenerateRfBlock(1, createStatements);
const updateCond = maybeGenerateRfBlock(2, updateStatements);
return fn([new FnParam('rf'), new FnParam('ctx')], [...createCond, ...updateCond], undefined, undefined, view.fnName);
}
function maybeGenerateRfBlock(flag, statements) {
if (statements.length === 0) {
return [];
}
return [ifStmt(new BinaryOperatorExpr(BinaryOperator.BitwiseAnd, variable('rf'), literal(flag)), statements)];
}
function emitHostBindingFunction(job) {
if (job.root.fnName === null) {
throw new Error(`AssertionError: host binding function is unnamed`);
}
const createStatements = [];
for (const op of job.root.create) {
if (op.kind !== OpKind.Statement) {
throw new Error(`AssertionError: expected all create ops to have been compiled, but got ${OpKind[op.kind]}`);
}
createStatements.push(op.statement);
}
const updateStatements = [];
for (const op of job.root.update) {
if (op.kind !== OpKind.Statement) {
throw new Error(`AssertionError: expected all update ops to have been compiled, but got ${OpKind[op.kind]}`);
}
updateStatements.push(op.statement);
}
if (createStatements.length === 0 && updateStatements.length === 0) {
return null;
}
const createCond = maybeGenerateRfBlock(1, createStatements);
const updateCond = maybeGenerateRfBlock(2, updateStatements);
return fn([new FnParam('rf'), new FnParam('ctx')], [...createCond, ...updateCond], undefined, undefined, job.root.fnName);
}
const compatibilityMode = CompatibilityMode.TemplateDefinitionBuilder;
const domSchema = new DomElementSchemaRegistry();
const NG_TEMPLATE_TAG_NAME = 'ng-template';
const ANIMATE_PREFIX$1 = 'animate.';
function isI18nRootNode(meta) {
return meta instanceof Message;
}
function isSingleI18nIcu(meta) {
return isI18nRootNode(meta) && meta.nodes.length === 1 && meta.nodes[0] instanceof Icu;
}
function ingestComponent(componentName, template, constantPool, compilationMode, relativeContextFilePath, i18nUseExternalIds, deferMeta, allDeferrableDepsFn, relativeTemplatePath, enableDebugLocations) {
const job = new ComponentCompilationJob(componentName, constantPool, compatibilityMode, compilationMode, relativeContextFilePath, i18nUseExternalIds, deferMeta, allDeferrableDepsFn, relativeTemplatePath, enableDebugLocations);
ingestNodes(job.root, template);
return job;
}
function ingestHostBinding(input, bindingParser, constantPool) {
const job = new HostBindingCompilationJob(input.componentName, constantPool, compatibilityMode, TemplateCompilationMode.DomOnly);
for (const property of input.properties ?? []) {
let bindingKind = BindingKind.Property;
if (property.name.startsWith('attr.')) {
property.name = property.name.substring('attr.'.length);
bindingKind = BindingKind.Attribute;
}
if (property.isLegacyAnimation) {
bindingKind = BindingKind.LegacyAnimation;
}
if (property.isAnimation) {
bindingKind = BindingKind.Animation;
}
const securityContexts = bindingParser.calcPossibleSecurityContexts(input.componentSelector, property.name, bindingKind === BindingKind.Attribute).filter(context => context !== SecurityContext.NONE);
ingestDomProperty(job, property, bindingKind, securityContexts);
}
for (const [name, expr] of Object.entries(input.attributes) ?? []) {
const securityContexts = bindingParser.calcPossibleSecurityContexts(input.componentSelector, name, true).filter(context => context !== SecurityContext.NONE);
ingestHostAttribute(job, name, expr, securityContexts);
}
for (const event of input.events ?? []) {
ingestHostEvent(job, event);
}
return job;
}
function ingestDomProperty(job, property, bindingKind, securityContexts) {
let expression;
const ast = property.expression.ast;
if (ast instanceof Interpolation$1) {
expression = new Interpolation(ast.strings, ast.expressions.map(expr => convertAst(expr, job, property.sourceSpan)), []);
} else {
expression = convertAst(ast, job, property.sourceSpan);
}
job.root.update.push(createBindingOp(job.root.xref, bindingKind, property.name, expression, null, securityContexts, false, false, null, null, property.sourceSpan));
}
function ingestHostAttribute(job, name, value, securityContexts) {
const attrBinding = createBindingOp(job.root.xref, BindingKind.Attribute, name, value, null, securityContexts, true, false, null, null, value.sourceSpan);
job.root.update.push(attrBinding);
}
function ingestHostEvent(job, event) {
let eventBinding;
if (event.type === ParsedEventType.Animation) {
eventBinding = createAnimationListenerOp(job.root.xref, new SlotHandle(), event.name, null, makeListenerHandlerOps(job.root, event.handler, event.handlerSpan), event.name.endsWith('enter') ? "enter" : "leave", event.targetOrPhase, true, event.sourceSpan);
} else {
const [phase, target] = event.type !== ParsedEventType.LegacyAnimation ? [null, event.targetOrPhase] : [event.targetOrPhase, null];
eventBinding = createListenerOp(job.root.xref, new SlotHandle(), event.name, null, makeListenerHandlerOps(job.root, event.handler, event.handlerSpan), phase, target, true, event.sourceSpan);
}
job.root.create.push(eventBinding);
}
function ingestNodes(unit, template) {
for (const node of template) {
if (node instanceof Element$1) {
ingestElement(unit, node);
} else if (node instanceof Template) {
ingestTemplate(unit, node);
} else if (node instanceof Content) {
ingestContent(unit, node);
} else if (node instanceof Text$3) {
ingestText(unit, node, null);
} else if (node instanceof BoundText) {
ingestBoundText(unit, node, null);
} else if (node instanceof IfBlock) {
ingestIfBlock(unit, node);
} else if (node instanceof SwitchBlock) {
ingestSwitchBlock(unit, node);
} else if (node instanceof DeferredBlock) {
ingestDeferBlock(unit, node);
} else if (node instanceof Icu$1) {
ingestIcu(unit, node);
} else if (node instanceof ForLoopBlock) {
ingestForBlock(unit, node);
} else if (node instanceof LetDeclaration$1) {
ingestLetDeclaration(unit, node);
} else if (node instanceof Component$1) ; else {
throw new Error(`Unsupported template node: ${node.constructor.name}`);
}
}
}
function ingestElement(unit, element) {
if (element.i18n !== undefined && !(element.i18n instanceof Message || element.i18n instanceof TagPlaceholder)) {
throw Error(`Unhandled i18n metadata type for element: ${element.i18n.constructor.name}`);
}
const id = unit.job.allocateXrefId();
const [namespaceKey, elementName] = splitNsName(element.name);
const startOp = createElementStartOp(elementName, id, namespaceForKey(namespaceKey), element.i18n instanceof TagPlaceholder ? element.i18n : undefined, element.startSourceSpan, element.sourceSpan);
unit.create.push(startOp);
ingestElementBindings(unit, startOp, element);
ingestReferences(startOp, element);
let i18nBlockId = null;
if (element.i18n instanceof Message) {
i18nBlockId = unit.job.allocateXrefId();
unit.create.push(createI18nStartOp(i18nBlockId, element.i18n, undefined, element.startSourceSpan));
}
ingestNodes(unit, element.children);
const endOp = createElementEndOp(id, element.endSourceSpan ?? element.startSourceSpan);
unit.create.push(endOp);
const fieldInput = element.inputs.find(input => input.name === 'formField' && input.type === BindingType.Property);
if (fieldInput) {
unit.create.push(createControlCreateOp(fieldInput.sourceSpan));
}
if (i18nBlockId !== null) {
OpList.insertBefore(createI18nEndOp(i18nBlockId, element.endSourceSpan ?? element.startSourceSpan), endOp);
}
}
function ingestTemplate(unit, tmpl) {
if (tmpl.i18n !== undefined && !(tmpl.i18n instanceof Message || tmpl.i18n instanceof TagPlaceholder)) {
throw Error(`Unhandled i18n metadata type for template: ${tmpl.i18n.constructor.name}`);
}
const childView = unit.job.allocateView(unit.xref);
let tagNameWithoutNamespace = tmpl.tagName;
let namespacePrefix = '';
if (tmpl.tagName) {
[namespacePrefix, tagNameWithoutNamespace] = splitNsName(tmpl.tagName);
}
const i18nPlaceholder = tmpl.i18n instanceof TagPlaceholder ? tmpl.i18n : undefined;
const namespace = namespaceForKey(namespacePrefix);
const functionNameSuffix = tagNameWithoutNamespace === null ? '' : prefixWithNamespace(tagNameWithoutNamespace, namespace);
const templateKind = isPlainTemplate(tmpl) ? TemplateKind.NgTemplate : TemplateKind.Structural;
const templateOp = createTemplateOp(childView.xref, templateKind, tagNameWithoutNamespace, functionNameSuffix, namespace, i18nPlaceholder, tmpl.startSourceSpan, tmpl.sourceSpan);
unit.create.push(templateOp);
ingestTemplateBindings(unit, templateOp, tmpl, templateKind);
ingestReferences(templateOp, tmpl);
ingestNodes(childView, tmpl.children);
for (const {
name,
value
} of tmpl.variables) {
childView.contextVariables.set(name, value !== '' ? value : '$implicit');
}
if (templateKind === TemplateKind.NgTemplate && tmpl.i18n instanceof Message) {
const id = unit.job.allocateXrefId();
OpList.insertAfter(createI18nStartOp(id, tmpl.i18n, undefined, tmpl.startSourceSpan), childView.create.head);
OpList.insertBefore(createI18nEndOp(id, tmpl.endSourceSpan ?? tmpl.startSourceSpan), childView.create.tail);
}
}
function ingestContent(unit, content) {
if (content.i18n !== undefined && !(content.i18n instanceof TagPlaceholder)) {
throw Error(`Unhandled i18n metadata type for element: ${content.i18n.constructor.name}`);
}
let fallbackView = null;
if (content.children.some(child => !(child instanceof Comment$1) && (!(child instanceof Text$3) || child.value.trim().length > 0))) {
fallbackView = unit.job.allocateView(unit.xref);
ingestNodes(fallbackView, content.children);
}
const id = unit.job.allocateXrefId();
const op = createProjectionOp(id, content.selector, content.i18n, fallbackView?.xref ?? null, content.sourceSpan);
for (const attr of content.attributes) {
const securityContext = domSchema.securityContext(content.name, attr.name, true);
unit.update.push(createBindingOp(op.xref, BindingKind.Attribute, attr.name, literal(attr.value), null, securityContext, true, false, null, asMessage(attr.i18n), attr.sourceSpan));
}
unit.create.push(op);
}
function ingestText(unit, text, icuPlaceholder) {
unit.create.push(createTextOp(unit.job.allocateXrefId(), text.value, icuPlaceholder, text.sourceSpan));
}
function ingestBoundText(unit, text, icuPlaceholder) {
let value = text.value;
if (value instanceof ASTWithSource) {
value = value.ast;
}
if (!(value instanceof Interpolation$1)) {
throw new Error(`AssertionError: expected Interpolation for BoundText node, got ${value.constructor.name}`);
}
if (text.i18n !== undefined && !(text.i18n instanceof Container)) {
throw Error(`Unhandled i18n metadata type for text interpolation: ${text.i18n?.constructor.name}`);
}
const i18nPlaceholders = text.i18n instanceof Container ? text.i18n.children.filter(node => node instanceof Placeholder).map(placeholder => placeholder.name) : [];
if (i18nPlaceholders.length > 0 && i18nPlaceholders.length !== value.expressions.length) {
throw Error(`Unexpected number of i18n placeholders (${value.expressions.length}) for BoundText with ${value.expressions.length} expressions`);
}
const textXref = unit.job.allocateXrefId();
unit.create.push(createTextOp(textXref, '', icuPlaceholder, text.sourceSpan));
const baseSourceSpan = unit.job.compatibility ? null : text.sourceSpan;
unit.update.push(createInterpolateTextOp(textXref, new Interpolation(value.strings, value.expressions.map(expr => convertAst(expr, unit.job, baseSourceSpan)), i18nPlaceholders), text.sourceSpan));
}
function ingestIfBlock(unit, ifBlock) {
let firstXref = null;
let conditions = [];
for (let i = 0; i < ifBlock.branches.length; i++) {
const ifCase = ifBlock.branches[i];
const cView = unit.job.allocateView(unit.xref);
const tagName = ingestControlFlowInsertionPoint(unit, cView.xref, ifCase);
if (ifCase.expressionAlias !== null) {
cView.contextVariables.set(ifCase.expressionAlias.name, CTX_REF);
}
let ifCaseI18nMeta = undefined;
if (ifCase.i18n !== undefined) {
if (!(ifCase.i18n instanceof BlockPlaceholder)) {
throw Error(`Unhandled i18n metadata type for if block: ${ifCase.i18n?.constructor.name}`);
}
ifCaseI18nMeta = ifCase.i18n;
}
const createOp = i === 0 ? createConditionalCreateOp : createConditionalBranchCreateOp;
const conditionalCreateOp = createOp(cView.xref, TemplateKind.Block, tagName, 'Conditional', Namespace.HTML, ifCaseI18nMeta, ifCase.startSourceSpan, ifCase.sourceSpan);
unit.create.push(conditionalCreateOp);
if (firstXref === null) {
firstXref = cView.xref;
}
const caseExpr = ifCase.expression ? convertAst(ifCase.expression, unit.job, null) : null;
const conditionalCaseExpr = new ConditionalCaseExpr(caseExpr, conditionalCreateOp.xref, conditionalCreateOp.handle, ifCase.expressionAlias);
conditions.push(conditionalCaseExpr);
ingestNodes(cView, ifCase.children);
}
unit.update.push(createConditionalOp(firstXref, null, conditions, ifBlock.sourceSpan));
}
function ingestSwitchBlock(unit, switchBlock) {
if (switchBlock.groups.length === 0) {
return;
}
let firstXref = null;
let conditions = [];
for (let i = 0; i < switchBlock.groups.length; i++) {
const switchCaseGroup = switchBlock.groups[i];
const cView = unit.job.allocateView(unit.xref);
const tagName = ingestControlFlowInsertionPoint(unit, cView.xref, switchCaseGroup);
let switchCaseI18nMeta = undefined;
if (switchCaseGroup.i18n !== undefined) {
if (!(switchCaseGroup.i18n instanceof BlockPlaceholder)) {
throw Error(`Unhandled i18n metadata type for switch block: ${switchCaseGroup.i18n?.constructor.name}`);
}
switchCaseI18nMeta = switchCaseGroup.i18n;
}
const createOp = i === 0 ? createConditionalCreateOp : createConditionalBranchCreateOp;
const conditionalCreateOp = createOp(cView.xref, TemplateKind.Block, tagName, 'Case', Namespace.HTML, switchCaseI18nMeta, switchCaseGroup.startSourceSpan, switchCaseGroup.sourceSpan);
unit.create.push(conditionalCreateOp);
if (firstXref === null) {
firstXref = cView.xref;
}
for (const switchCase of switchCaseGroup.cases) {
const caseExpr = switchCase.expression ? convertAst(switchCase.expression, unit.job, switchBlock.startSourceSpan) : null;
const conditionalCaseExpr = new ConditionalCaseExpr(caseExpr, conditionalCreateOp.xref, conditionalCreateOp.handle);
conditions.push(conditionalCaseExpr);
}
ingestNodes(cView, switchCaseGroup.children);
}
unit.update.push(createConditionalOp(firstXref, convertAst(switchBlock.expression, unit.job, null), conditions, switchBlock.sourceSpan));
}
function ingestDeferView(unit, suffix, i18nMeta, children, sourceSpan) {
if (i18nMeta !== undefined && !(i18nMeta instanceof BlockPlaceholder)) {
throw Error('Unhandled i18n metadata type for defer block');
}
if (children === undefined) {
return null;
}
const secondaryView = unit.job.allocateView(unit.xref);
ingestNodes(secondaryView, children);
const templateOp = createTemplateOp(secondaryView.xref, TemplateKind.Block, null, `Defer${suffix}`, Namespace.HTML, i18nMeta, sourceSpan, sourceSpan);
unit.create.push(templateOp);
return templateOp;
}
function ingestDeferBlock(unit, deferBlock) {
let ownResolverFn = null;
if (unit.job.deferMeta.mode === 0) {
if (!unit.job.deferMeta.blocks.has(deferBlock)) {
throw new Error(`AssertionError: unable to find a dependency function for this deferred block`);
}
ownResolverFn = unit.job.deferMeta.blocks.get(deferBlock) ?? null;
}
const main = ingestDeferView(unit, '', deferBlock.i18n, deferBlock.children, deferBlock.sourceSpan);
const loading = ingestDeferView(unit, 'Loading', deferBlock.loading?.i18n, deferBlock.loading?.children, deferBlock.loading?.sourceSpan);
const placeholder = ingestDeferView(unit, 'Placeholder', deferBlock.placeholder?.i18n, deferBlock.placeholder?.children, deferBlock.placeholder?.sourceSpan);
const error = ingestDeferView(unit, 'Error', deferBlock.error?.i18n, deferBlock.error?.children, deferBlock.error?.sourceSpan);
const deferXref = unit.job.allocateXrefId();
const deferOp = createDeferOp(deferXref, main.xref, main.handle, ownResolverFn, unit.job.allDeferrableDepsFn, deferBlock.sourceSpan);
deferOp.placeholderView = placeholder?.xref ?? null;
deferOp.placeholderSlot = placeholder?.handle ?? null;
deferOp.loadingSlot = loading?.handle ?? null;
deferOp.errorSlot = error?.handle ?? null;
deferOp.placeholderMinimumTime = deferBlock.placeholder?.minimumTime ?? null;
deferOp.loadingMinimumTime = deferBlock.loading?.minimumTime ?? null;
deferOp.loadingAfterTime = deferBlock.loading?.afterTime ?? null;
deferOp.flags = calcDeferBlockFlags(deferBlock);
unit.create.push(deferOp);
const deferOnOps = [];
const deferWhenOps = [];
ingestDeferTriggers("hydrate", deferBlock.hydrateTriggers, deferOnOps, deferWhenOps, unit, deferXref);
ingestDeferTriggers("none", deferBlock.triggers, deferOnOps, deferWhenOps, unit, deferXref);
ingestDeferTriggers("prefetch", deferBlock.prefetchTriggers, deferOnOps, deferWhenOps, unit, deferXref);
const hasConcreteTrigger = deferOnOps.some(op => op.modifier === "none") || deferWhenOps.some(op => op.modifier === "none");
if (!hasConcreteTrigger) {
deferOnOps.push(createDeferOnOp(deferXref, {
kind: DeferTriggerKind.Idle
}, "none", null));
}
unit.create.push(deferOnOps);
unit.update.push(deferWhenOps);
}
function calcDeferBlockFlags(deferBlockDetails) {
if (Object.keys(deferBlockDetails.hydrateTriggers).length > 0) {
return 1;
}
return null;
}
function ingestDeferTriggers(modifier, triggers, onOps, whenOps, unit, deferXref) {
if (triggers.idle !== undefined) {
const deferOnOp = createDeferOnOp(deferXref, {
kind: DeferTriggerKind.Idle
}, modifier, triggers.idle.sourceSpan);
onOps.push(deferOnOp);
}
if (triggers.immediate !== undefined) {
const deferOnOp = createDeferOnOp(deferXref, {
kind: DeferTriggerKind.Immediate
}, modifier, triggers.immediate.sourceSpan);
onOps.push(deferOnOp);
}
if (triggers.timer !== undefined) {
const deferOnOp = createDeferOnOp(deferXref, {
kind: DeferTriggerKind.Timer,
delay: triggers.timer.delay
}, modifier, triggers.timer.sourceSpan);
onOps.push(deferOnOp);
}
if (triggers.hover !== undefined) {
const deferOnOp = createDeferOnOp(deferXref, {
kind: DeferTriggerKind.Hover,
targetName: triggers.hover.reference,
targetXref: null,
targetSlot: null,
targetView: null,
targetSlotViewSteps: null
}, modifier, triggers.hover.sourceSpan);
onOps.push(deferOnOp);
}
if (triggers.interaction !== undefined) {
const deferOnOp = createDeferOnOp(deferXref, {
kind: DeferTriggerKind.Interaction,
targetName: triggers.interaction.reference,
targetXref: null,
targetSlot: null,
targetView: null,
targetSlotViewSteps: null
}, modifier, triggers.interaction.sourceSpan);
onOps.push(deferOnOp);
}
if (triggers.viewport !== undefined) {
const deferOnOp = createDeferOnOp(deferXref, {
kind: DeferTriggerKind.Viewport,
targetName: triggers.viewport.reference,
targetXref: null,
targetSlot: null,
targetView: null,
targetSlotViewSteps: null,
options: triggers.viewport.options ? convertAst(triggers.viewport.options, unit.job, triggers.viewport.sourceSpan) : null
}, modifier, triggers.viewport.sourceSpan);
onOps.push(deferOnOp);
}
if (triggers.never !== undefined) {
const deferOnOp = createDeferOnOp(deferXref, {
kind: DeferTriggerKind.Never
}, modifier, triggers.never.sourceSpan);
onOps.push(deferOnOp);
}
if (triggers.when !== undefined) {
if (triggers.when.value instanceof Interpolation$1) {
throw new Error(`Unexpected interpolation in defer block when trigger`);
}
const deferOnOp = createDeferWhenOp(deferXref, convertAst(triggers.when.value, unit.job, triggers.when.sourceSpan), modifier, triggers.when.sourceSpan);
whenOps.push(deferOnOp);
}
}
function ingestIcu(unit, icu) {
if (icu.i18n instanceof Message && isSingleI18nIcu(icu.i18n)) {
const xref = unit.job.allocateXrefId();
unit.create.push(createIcuStartOp(xref, icu.i18n, icuFromI18nMessage(icu.i18n).name, null));
for (const [placeholder, text] of Object.entries({
...icu.vars,
...icu.placeholders
})) {
if (text instanceof BoundText) {
ingestBoundText(unit, text, placeholder);
} else {
ingestText(unit, text, placeholder);
}
}
unit.create.push(createIcuEndOp(xref));
} else {
throw Error(`Unhandled i18n metadata type for ICU: ${icu.i18n?.constructor.name}`);
}
}
function ingestForBlock(unit, forBlock) {
const repeaterView = unit.job.allocateView(unit.xref);
const indexName = `ɵ$index_${repeaterView.xref}`;
const countName = `ɵ$count_${repeaterView.xref}`;
const indexVarNames = new Set();
repeaterView.contextVariables.set(forBlock.item.name, forBlock.item.value);
for (const variable of forBlock.contextVariables) {
if (variable.value === '$index') {
indexVarNames.add(variable.name);
}
if (variable.name === '$index') {
repeaterView.contextVariables.set('$index', variable.value).set(indexName, variable.value);
} else if (variable.name === '$count') {
repeaterView.contextVariables.set('$count', variable.value).set(countName, variable.value);
} else {
repeaterView.aliases.add({
kind: SemanticVariableKind.Alias,
name: null,
identifier: variable.name,
expression: getComputedForLoopVariableExpression(variable, indexName, countName)
});
}
}
const sourceSpan = convertSourceSpan(forBlock.trackBy.span, forBlock.sourceSpan);
const track = convertAst(forBlock.trackBy, unit.job, sourceSpan);
ingestNodes(repeaterView, forBlock.children);
let emptyView = null;
let emptyTagName = null;
if (forBlock.empty !== null) {
emptyView = unit.job.allocateView(unit.xref);
ingestNodes(emptyView, forBlock.empty.children);
emptyTagName = ingestControlFlowInsertionPoint(unit, emptyView.xref, forBlock.empty);
}
const varNames = {
$index: indexVarNames,
$implicit: forBlock.item.name
};
if (forBlock.i18n !== undefined && !(forBlock.i18n instanceof BlockPlaceholder)) {
throw Error('AssertionError: Unhandled i18n metadata type or @for');
}
if (forBlock.empty?.i18n !== undefined && !(forBlock.empty.i18n instanceof BlockPlaceholder)) {
throw Error('AssertionError: Unhandled i18n metadata type or @empty');
}
const i18nPlaceholder = forBlock.i18n;
const emptyI18nPlaceholder = forBlock.empty?.i18n;
const tagName = ingestControlFlowInsertionPoint(unit, repeaterView.xref, forBlock);
const repeaterCreate = createRepeaterCreateOp(repeaterView.xref, emptyView?.xref ?? null, tagName, track, varNames, emptyTagName, i18nPlaceholder, emptyI18nPlaceholder, forBlock.startSourceSpan, forBlock.sourceSpan);
unit.create.push(repeaterCreate);
const expression = convertAst(forBlock.expression, unit.job, convertSourceSpan(forBlock.expression.span, forBlock.sourceSpan));
const repeater = createRepeaterOp(repeaterCreate.xref, repeaterCreate.handle, expression, forBlock.sourceSpan);
unit.update.push(repeater);
}
function getComputedForLoopVariableExpression(variable, indexName, countName) {
switch (variable.value) {
case '$index':
return new LexicalReadExpr(indexName);
case '$count':
return new LexicalReadExpr(countName);
case '$first':
return new LexicalReadExpr(indexName).identical(literal(0));
case '$last':
return new LexicalReadExpr(indexName).identical(new LexicalReadExpr(countName).minus(literal(1)));
case '$even':
return new LexicalReadExpr(indexName).modulo(literal(2)).identical(literal(0));
case '$odd':
return new LexicalReadExpr(indexName).modulo(literal(2)).notIdentical(literal(0));
default:
throw new Error(`AssertionError: unknown @for loop variable ${variable.value}`);
}
}
function ingestLetDeclaration(unit, node) {
const target = unit.job.allocateXrefId();
unit.create.push(createDeclareLetOp(target, node.name, node.sourceSpan));
unit.update.push(createStoreLetOp(target, node.name, convertAst(node.value, unit.job, node.valueSpan), node.sourceSpan));
}
function convertAst(ast, job, baseSourceSpan) {
if (ast instanceof ASTWithSource) {
return convertAst(ast.ast, job, baseSourceSpan);
} else if (ast instanceof PropertyRead) {
if (ast.receiver instanceof ImplicitReceiver) {
return new LexicalReadExpr(ast.name);
} else {
return new ReadPropExpr(convertAst(ast.receiver, job, baseSourceSpan), ast.name, null, convertSourceSpan(ast.span, baseSourceSpan));
}
} else if (ast instanceof Call) {
if (ast.receiver instanceof ImplicitReceiver) {
throw new Error(`Unexpected ImplicitReceiver`);
} else {
return new InvokeFunctionExpr(convertAst(ast.receiver, job, baseSourceSpan), ast.args.map(arg => convertAst(arg, job, baseSourceSpan)), undefined, convertSourceSpan(ast.span, baseSourceSpan));
}
} else if (ast instanceof LiteralPrimitive) {
return literal(ast.value, undefined, convertSourceSpan(ast.span, baseSourceSpan));
} else if (ast instanceof Unary) {
switch (ast.operator) {
case '+':
return new UnaryOperatorExpr(UnaryOperator.Plus, convertAst(ast.expr, job, baseSourceSpan), undefined, convertSourceSpan(ast.span, baseSourceSpan));
case '-':
return new UnaryOperatorExpr(UnaryOperator.Minus, convertAst(ast.expr, job, baseSourceSpan), undefined, convertSourceSpan(ast.span, baseSourceSpan));
default:
throw new Error(`AssertionError: unknown unary operator ${ast.operator}`);
}
} else if (ast instanceof Binary) {
const operator = BINARY_OPERATORS.get(ast.operation);
if (operator === undefined) {
throw new Error(`AssertionError: unknown binary operator ${ast.operation}`);
}
return new BinaryOperatorExpr(operator, convertAst(ast.left, job, baseSourceSpan), convertAst(ast.right, job, baseSourceSpan), undefined, convertSourceSpan(ast.span, baseSourceSpan));
} else if (ast instanceof ThisReceiver) {
return new ContextExpr(job.root.xref);
} else if (ast instanceof KeyedRead) {
return new ReadKeyExpr(convertAst(ast.receiver, job, baseSourceSpan), convertAst(ast.key, job, baseSourceSpan), undefined, convertSourceSpan(ast.span, baseSourceSpan));
} else if (ast instanceof Chain) {
throw new Error(`AssertionError: Chain in unknown context`);
} else if (ast instanceof LiteralMap) {
const entries = ast.keys.map((key, idx) => {
const value = convertAst(ast.values[idx], job, baseSourceSpan);
return key.kind === 'spread' ? new LiteralMapSpreadAssignment(value) : new LiteralMapPropertyAssignment(key.key, value, key.quoted);
});
return new LiteralMapExpr(entries, undefined, convertSourceSpan(ast.span, baseSourceSpan));
} else if (ast instanceof LiteralArray) {
return new LiteralArrayExpr(ast.expressions.map(expr => convertAst(expr, job, baseSourceSpan)));
} else if (ast instanceof Conditional) {
return new ConditionalExpr(convertAst(ast.condition, job, baseSourceSpan), convertAst(ast.trueExp, job, baseSourceSpan), convertAst(ast.falseExp, job, baseSourceSpan), undefined, convertSourceSpan(ast.span, baseSourceSpan));
} else if (ast instanceof NonNullAssert) {
return convertAst(ast.expression, job, baseSourceSpan);
} else if (ast instanceof BindingPipe) {
return new PipeBindingExpr(job.allocateXrefId(), new SlotHandle(), ast.name, [convertAst(ast.exp, job, baseSourceSpan), ...ast.args.map(arg => convertAst(arg, job, baseSourceSpan))]);
} else if (ast instanceof SafeKeyedRead) {
return new SafeKeyedReadExpr(convertAst(ast.receiver, job, baseSourceSpan), convertAst(ast.key, job, baseSourceSpan), convertSourceSpan(ast.span, baseSourceSpan));
} else if (ast instanceof SafePropertyRead) {
return new SafePropertyReadExpr(convertAst(ast.receiver, job, baseSourceSpan), ast.name);
} else if (ast instanceof SafeCall) {
return new SafeInvokeFunctionExpr(convertAst(ast.receiver, job, baseSourceSpan), ast.args.map(a => convertAst(a, job, baseSourceSpan)));
} else if (ast instanceof EmptyExpr$1) {
return new EmptyExpr(convertSourceSpan(ast.span, baseSourceSpan));
} else if (ast instanceof PrefixNot) {
return not(convertAst(ast.expression, job, baseSourceSpan), convertSourceSpan(ast.span, baseSourceSpan));
} else if (ast instanceof TypeofExpression) {
return typeofExpr(convertAst(ast.expression, job, baseSourceSpan));
} else if (ast instanceof VoidExpression) {
return new VoidExpr(convertAst(ast.expression, job, baseSourceSpan), undefined, convertSourceSpan(ast.span, baseSourceSpan));
} else if (ast instanceof TemplateLiteral) {
return convertTemplateLiteral(ast, job, baseSourceSpan);
} else if (ast instanceof TaggedTemplateLiteral) {
return new TaggedTemplateLiteralExpr(convertAst(ast.tag, job, baseSourceSpan), convertTemplateLiteral(ast.template, job, baseSourceSpan), undefined, convertSourceSpan(ast.span, baseSourceSpan));
} else if (ast instanceof ParenthesizedExpression) {
return new ParenthesizedExpr(convertAst(ast.expression, job, baseSourceSpan), undefined, convertSourceSpan(ast.span, baseSourceSpan));
} else if (ast instanceof RegularExpressionLiteral) {
return new RegularExpressionLiteralExpr(ast.body, ast.flags, baseSourceSpan);
} else if (ast instanceof SpreadElement) {
return new SpreadElementExpr(convertAst(ast.expression, job, baseSourceSpan));
} else {
throw new Error(`Unhandled expression type "${ast.constructor.name}" in file "${baseSourceSpan?.start.file.url}"`);
}
}
function convertTemplateLiteral(ast, job, baseSourceSpan) {
return new TemplateLiteralExpr(ast.elements.map(el => {
return new TemplateLiteralElementExpr(el.text, convertSourceSpan(el.span, baseSourceSpan));
}), ast.expressions.map(expr => convertAst(expr, job, baseSourceSpan)), convertSourceSpan(ast.span, baseSourceSpan));
}
function convertAstWithInterpolation(job, value, i18nMeta, sourceSpan) {
let expression;
if (value instanceof Interpolation$1) {
expression = new Interpolation(value.strings, value.expressions.map(e => convertAst(e, job, null)), Object.keys(asMessage(i18nMeta)?.placeholders ?? {}));
} else if (value instanceof AST) {
expression = convertAst(value, job, null);
} else {
expression = literal(value);
}
return expression;
}
const BINDING_KINDS = new Map([[BindingType.Property, BindingKind.Property], [BindingType.TwoWay, BindingKind.TwoWayProperty], [BindingType.Attribute, BindingKind.Attribute], [BindingType.Class, BindingKind.ClassName], [BindingType.Style, BindingKind.StyleProperty], [BindingType.LegacyAnimation, BindingKind.LegacyAnimation], [BindingType.Animation, BindingKind.Animation]]);
function isPlainTemplate(tmpl) {
return splitNsName(tmpl.tagName ?? '')[1] === NG_TEMPLATE_TAG_NAME;
}
function asMessage(i18nMeta) {
if (i18nMeta == null) {
return null;
}
if (!(i18nMeta instanceof Message)) {
throw Error(`Expected i18n meta to be a Message, but got: ${i18nMeta.constructor.name}`);
}
return i18nMeta;
}
function ingestElementBindings(unit, op, element) {
let bindings = new Array();
let i18nAttributeBindingNames = new Set();
for (const attr of element.attributes) {
const securityContext = domSchema.securityContext(element.name, attr.name, true);
bindings.push(createBindingOp(op.xref, BindingKind.Attribute, attr.name, convertAstWithInterpolation(unit.job, attr.value, attr.i18n), null, securityContext, true, false, null, asMessage(attr.i18n), attr.sourceSpan));
if (attr.i18n) {
i18nAttributeBindingNames.add(attr.name);
}
}
for (const input of element.inputs) {
if (i18nAttributeBindingNames.has(input.name)) {
console.error(`On component ${unit.job.componentName}, the binding ${input.name} is both an i18n attribute and a property. You may want to remove the property binding. This will become a compilation error in future versions of Angular.`);
}
bindings.push(createBindingOp(op.xref, BINDING_KINDS.get(input.type), input.name, convertAstWithInterpolation(unit.job, astOf(input.value), input.i18n), input.unit, input.securityContext, false, false, null, asMessage(input.i18n) ?? null, input.sourceSpan));
}
unit.create.push(bindings.filter(b => b?.kind === OpKind.ExtractedAttribute));
unit.update.push(bindings.filter(b => b?.kind === OpKind.Binding));
for (const output of element.outputs) {
if (output.type === ParsedEventType.LegacyAnimation && output.phase === null) {
throw Error('Animation listener should have a phase');
}
if (output.type === ParsedEventType.TwoWay) {
unit.create.push(createTwoWayListenerOp(op.xref, op.handle, output.name, op.tag, makeTwoWayListenerHandlerOps(unit, output.handler, output.handlerSpan), output.sourceSpan));
} else if (output.type === ParsedEventType.Animation) {
unit.create.push(createAnimationListenerOp(op.xref, op.handle, output.name, op.tag, makeListenerHandlerOps(unit, output.handler, output.handlerSpan), output.name.endsWith('enter') ? "enter" : "leave", output.target, false, output.sourceSpan));
} else {
unit.create.push(createListenerOp(op.xref, op.handle, output.name, op.tag, makeListenerHandlerOps(unit, output.handler, output.handlerSpan), output.phase, output.target, false, output.sourceSpan));
}
}
if (bindings.some(b => b?.i18nMessage) !== null) {
unit.create.push(createI18nAttributesOp(unit.job.allocateXrefId(), new SlotHandle(), op.xref));
}
}
function ingestTemplateBindings(unit, op, template, templateKind) {
let bindings = new Array();
for (const attr of template.templateAttrs) {
if (attr instanceof TextAttribute) {
const securityContext = domSchema.securityContext(NG_TEMPLATE_TAG_NAME, attr.name, true);
bindings.push(createTemplateBinding(unit, op.xref, BindingType.Attribute, attr.name, attr.value, null, securityContext, true, templateKind, asMessage(attr.i18n), attr.sourceSpan));
} else {
bindings.push(createTemplateBinding(unit, op.xref, attr.type, attr.name, astOf(attr.value), attr.unit, attr.securityContext, true, templateKind, asMessage(attr.i18n), attr.sourceSpan));
}
}
for (const attr of template.attributes) {
const securityContext = domSchema.securityContext(NG_TEMPLATE_TAG_NAME, attr.name, true);
bindings.push(createTemplateBinding(unit, op.xref, BindingType.Attribute, attr.name, attr.value, null, securityContext, false, templateKind, asMessage(attr.i18n), attr.sourceSpan));
}
for (const input of template.inputs) {
bindings.push(createTemplateBinding(unit, op.xref, input.type, input.name, astOf(input.value), input.unit, input.securityContext, false, templateKind, asMessage(input.i18n), input.sourceSpan));
}
unit.create.push(bindings.filter(b => b?.kind === OpKind.ExtractedAttribute));
unit.update.push(bindings.filter(b => b?.kind === OpKind.Binding));
for (const output of template.outputs) {
if (output.type === ParsedEventType.LegacyAnimation && output.phase === null) {
throw Error('Animation listener should have a phase');
}
if (templateKind === TemplateKind.NgTemplate) {
if (output.type === ParsedEventType.TwoWay) {
unit.create.push(createTwoWayListenerOp(op.xref, op.handle, output.name, op.tag, makeTwoWayListenerHandlerOps(unit, output.handler, output.handlerSpan), output.sourceSpan));
} else {
unit.create.push(createListenerOp(op.xref, op.handle, output.name, op.tag, makeListenerHandlerOps(unit, output.handler, output.handlerSpan), output.phase, output.target, false, output.sourceSpan));
}
}
if (templateKind === TemplateKind.Structural && output.type !== ParsedEventType.LegacyAnimation) {
const securityContext = domSchema.securityContext(NG_TEMPLATE_TAG_NAME, output.name, false);
unit.create.push(createExtractedAttributeOp(op.xref, BindingKind.Property, null, output.name, null, null, null, securityContext));
}
}
if (bindings.some(b => b?.i18nMessage) !== null) {
unit.create.push(createI18nAttributesOp(unit.job.allocateXrefId(), new SlotHandle(), op.xref));
}
}
function createTemplateBinding(view, xref, type, name, value, unit, securityContext, isStructuralTemplateAttribute, templateKind, i18nMessage, sourceSpan) {
const isTextBinding = typeof value === 'string';
if (templateKind === TemplateKind.Structural) {
if (!isStructuralTemplateAttribute) {
switch (type) {
case BindingType.Property:
case BindingType.Class:
case BindingType.Style:
return createExtractedAttributeOp(xref, BindingKind.Property, null, name, null, null, i18nMessage, securityContext);
case BindingType.TwoWay:
return createExtractedAttributeOp(xref, BindingKind.TwoWayProperty, null, name, null, null, i18nMessage, securityContext);
}
}
if (!isTextBinding && (type === BindingType.Attribute || type === BindingType.LegacyAnimation || type === BindingType.Animation)) {
return null;
}
}
let bindingType = BINDING_KINDS.get(type);
if (templateKind === TemplateKind.NgTemplate) {
if (type === BindingType.Class || type === BindingType.Style || type === BindingType.Attribute && !isTextBinding) {
bindingType = BindingKind.Property;
}
}
return createBindingOp(xref, bindingType, name, convertAstWithInterpolation(view.job, value, i18nMessage), unit, securityContext, isTextBinding, isStructuralTemplateAttribute, templateKind, i18nMessage, sourceSpan);
}
function makeListenerHandlerOps(unit, handler, handlerSpan) {
handler = astOf(handler);
const handlerOps = new Array();
let handlerExprs = handler instanceof Chain ? handler.expressions : [handler];
if (handlerExprs.length === 0) {
throw new Error('Expected listener to have non-empty expression list.');
}
const expressions = handlerExprs.map(expr => convertAst(expr, unit.job, handlerSpan));
const returnExpr = expressions.pop();
handlerOps.push(...expressions.map(e => createStatementOp(new ExpressionStatement(e, e.sourceSpan))));
handlerOps.push(createStatementOp(new ReturnStatement(returnExpr, returnExpr.sourceSpan)));
return handlerOps;
}
function makeTwoWayListenerHandlerOps(unit, handler, handlerSpan) {
handler = astOf(handler);
const handlerOps = new Array();
if (handler instanceof Chain) {
if (handler.expressions.length === 1) {
handler = handler.expressions[0];
} else {
throw new Error('Expected two-way listener to have a single expression.');
}
}
const handlerExpr = convertAst(handler, unit.job, handlerSpan);
const eventReference = new LexicalReadExpr('$event');
const twoWaySetExpr = new TwoWayBindingSetExpr(handlerExpr, eventReference);
handlerOps.push(createStatementOp(new ExpressionStatement(twoWaySetExpr)));
handlerOps.push(createStatementOp(new ReturnStatement(eventReference)));
return handlerOps;
}
function astOf(ast) {
return ast instanceof ASTWithSource ? ast.ast : ast;
}
function ingestReferences(op, element) {
assertIsArray(op.localRefs);
for (const {
name,
value
} of element.references) {
op.localRefs.push({
name,
target: value
});
}
}
function assertIsArray(value) {
if (!Array.isArray(value)) {
throw new Error(`AssertionError: expected an array`);
}
}
function convertSourceSpan(span, baseSourceSpan) {
if (baseSourceSpan === null) {
return null;
}
const start = baseSourceSpan.start.moveBy(span.start);
const end = baseSourceSpan.start.moveBy(span.end);
const fullStart = baseSourceSpan.fullStart.moveBy(span.start);
return new ParseSourceSpan(start, end, fullStart);
}
function ingestControlFlowInsertionPoint(unit, xref, node) {
let root = null;
for (const child of node.children) {
if (child instanceof Comment$1 || child instanceof LetDeclaration$1) {
continue;
}
if (root !== null) {
return null;
}
if (child instanceof Element$1 || child instanceof Template && child.tagName !== null) {
root = child;
} else {
return null;
}
}
if (root !== null) {
for (const attr of root.attributes) {
if (!attr.name.startsWith(ANIMATE_PREFIX$1)) {
const securityContext = domSchema.securityContext(NG_TEMPLATE_TAG_NAME, attr.name, true);
unit.update.push(createBindingOp(xref, BindingKind.Attribute, attr.name, literal(attr.value), null, securityContext, true, false, null, asMessage(attr.i18n), attr.sourceSpan));
}
}
for (const attr of root.inputs) {
if (attr.type !== BindingType.LegacyAnimation && attr.type !== BindingType.Animation && attr.type !== BindingType.Attribute) {
const securityContext = domSchema.securityContext(NG_TEMPLATE_TAG_NAME, attr.name, true);
unit.create.push(createExtractedAttributeOp(xref, BindingKind.Property, null, attr.name, null, null, null, securityContext));
}
}
const tagName = root instanceof Element$1 ? root.name : root.tagName;
return tagName === NG_TEMPLATE_TAG_NAME ? null : tagName;
}
return null;
}
let ENABLE_TEMPLATE_SOURCE_LOCATIONS = false;
function setEnableTemplateSourceLocations(value) {
ENABLE_TEMPLATE_SOURCE_LOCATIONS = value;
}
function getTemplateSourceLocationsEnabled() {
return ENABLE_TEMPLATE_SOURCE_LOCATIONS;
}
function renderFlagCheckIfStmt(flags, statements) {
return ifStmt(variable(RENDER_FLAGS).bitwiseAnd(literal(flags), null), statements);
}
function toQueryFlags(query) {
return (query.descendants ? 1 : 0) | (query.static ? 2 : 0) | (query.emitDistinctChangesOnly ? 4 : 0);
}
function getQueryPredicate(query, constantPool) {
if (Array.isArray(query.predicate)) {
let predicate = [];
query.predicate.forEach(selector => {
const selectors = selector.split(',').map(token => literal(token.trim()));
predicate.push(...selectors);
});
return constantPool.getConstLiteral(literalArr(predicate), true);
} else {
switch (query.predicate.forwardRef) {
case 0:
case 2:
return query.predicate.expression;
case 1:
return importExpr(Identifiers.resolveForwardRef).callFn([query.predicate.expression]);
}
}
}
function getQueryCreateParameters(query, constantPool, prependParams) {
const parameters = [];
if (prependParams !== undefined) {
parameters.push(...prependParams);
}
if (query.isSignal) {
parameters.push(new ReadPropExpr(variable(CONTEXT_NAME), query.propertyName));
}
parameters.push(getQueryPredicate(query, constantPool), literal(toQueryFlags(query)));
if (query.read) {
parameters.push(query.read);
}
return parameters;
}
const queryAdvancePlaceholder = Symbol('queryAdvancePlaceholder');
function collapseAdvanceStatements(statements) {
const result = [];
let advanceCollapseCount = 0;
const flushAdvanceCount = () => {
if (advanceCollapseCount > 0) {
result.unshift(importExpr(Identifiers.queryAdvance).callFn(advanceCollapseCount === 1 ? [] : [literal(advanceCollapseCount)]).toStmt());
advanceCollapseCount = 0;
}
};
for (let i = statements.length - 1; i >= 0; i--) {
const st = statements[i];
if (st === queryAdvancePlaceholder) {
advanceCollapseCount++;
} else {
flushAdvanceCount();
result.unshift(st);
}
}
flushAdvanceCount();
return result;
}
function createViewQueriesFunction(viewQueries, constantPool, name) {
const createStatements = [];
const updateStatements = [];
const tempAllocator = temporaryAllocator(st => updateStatements.push(st), TEMPORARY_NAME);
let viewQuerySignalCall = null;
let viewQueryCall = null;
viewQueries.forEach(query => {
const params = getQueryCreateParameters(query, constantPool);
if (query.isSignal) {
viewQuerySignalCall ??= importExpr(Identifiers.viewQuerySignal);
viewQuerySignalCall = viewQuerySignalCall.callFn(params);
} else {
viewQueryCall ??= importExpr(Identifiers.viewQuery);
viewQueryCall = viewQueryCall.callFn(params);
}
if (query.isSignal) {
updateStatements.push(queryAdvancePlaceholder);
return;
}
const temporary = tempAllocator();
const getQueryList = importExpr(Identifiers.loadQuery).callFn([]);
const refresh = importExpr(Identifiers.queryRefresh).callFn([temporary.set(getQueryList)]);
const updateDirective = variable(CONTEXT_NAME).prop(query.propertyName).set(query.first ? temporary.prop('first') : temporary);
updateStatements.push(refresh.and(updateDirective).toStmt());
});
if (viewQuerySignalCall !== null) {
createStatements.push(new ExpressionStatement(viewQuerySignalCall));
}
if (viewQueryCall !== null) {
createStatements.push(new ExpressionStatement(viewQueryCall));
}
const viewQueryFnName = name ? `${name}_Query` : null;
return fn([new FnParam(RENDER_FLAGS, NUMBER_TYPE), new FnParam(CONTEXT_NAME, null)], [renderFlagCheckIfStmt(1, createStatements), renderFlagCheckIfStmt(2, collapseAdvanceStatements(updateStatements))], INFERRED_TYPE, null, viewQueryFnName);
}
function createContentQueriesFunction(queries, constantPool, name) {
const createStatements = [];
const updateStatements = [];
const tempAllocator = temporaryAllocator(st => updateStatements.push(st), TEMPORARY_NAME);
let contentQuerySignalCall = null;
let contentQueryCall = null;
for (const query of queries) {
const params = getQueryCreateParameters(query, constantPool, [variable('dirIndex')]);
if (query.isSignal) {
contentQuerySignalCall ??= importExpr(Identifiers.contentQuerySignal);
contentQuerySignalCall = contentQuerySignalCall.callFn(params);
} else {
contentQueryCall ??= importExpr(Identifiers.contentQuery);
contentQueryCall = contentQueryCall.callFn(params);
}
if (query.isSignal) {
updateStatements.push(queryAdvancePlaceholder);
continue;
}
const temporary = tempAllocator();
const getQueryList = importExpr(Identifiers.loadQuery).callFn([]);
const refresh = importExpr(Identifiers.queryRefresh).callFn([temporary.set(getQueryList)]);
const updateDirective = variable(CONTEXT_NAME).prop(query.propertyName).set(query.first ? temporary.prop('first') : temporary);
updateStatements.push(refresh.and(updateDirective).toStmt());
}
if (contentQuerySignalCall !== null) {
createStatements.push(new ExpressionStatement(contentQuerySignalCall));
}
if (contentQueryCall !== null) {
createStatements.push(new ExpressionStatement(contentQueryCall));
}
const contentQueriesFnName = name ? `${name}_ContentQueries` : null;
return fn([new FnParam(RENDER_FLAGS, NUMBER_TYPE), new FnParam(CONTEXT_NAME, null), new FnParam('dirIndex', null)], [renderFlagCheckIfStmt(1, createStatements), renderFlagCheckIfStmt(2, collapseAdvanceStatements(updateStatements))], INFERRED_TYPE, null, contentQueriesFnName);
}
class HtmlParser extends Parser$1 {
constructor() {
super(getHtmlTagDefinition);
}
parse(source, url, options) {
return super.parse(source, url, options);
}
}
const PROPERTY_PARTS_SEPARATOR = '.';
const ATTRIBUTE_PREFIX = 'attr';
const ANIMATE_PREFIX = 'animate';
const CLASS_PREFIX = 'class';
const STYLE_PREFIX = 'style';
const TEMPLATE_ATTR_PREFIX$1 = '*';
const LEGACY_ANIMATE_PROP_PREFIX = 'animate-';
class BindingParser {
_exprParser;
_schemaRegistry;
errors;
constructor(_exprParser, _schemaRegistry, errors) {
this._exprParser = _exprParser;
this._schemaRegistry = _schemaRegistry;
this.errors = errors;
}
createBoundHostProperties(properties, sourceSpan) {
const boundProps = [];
for (const propName of Object.keys(properties)) {
const expression = properties[propName];
if (typeof expression === 'string') {
this.parsePropertyBinding(propName, expression, true, false, sourceSpan, sourceSpan.start.offset, undefined, [], boundProps, sourceSpan);
} else {
this._reportError(`Value of the host property binding "${propName}" needs to be a string representing an expression but got "${expression}" (${typeof expression})`, sourceSpan);
}
}
return boundProps;
}
createDirectiveHostEventAsts(hostListeners, sourceSpan) {
const targetEvents = [];
for (const propName of Object.keys(hostListeners)) {
const expression = hostListeners[propName];
if (typeof expression === 'string') {
this.parseEvent(propName, expression, false, sourceSpan, sourceSpan, [], targetEvents, sourceSpan);
} else {
this._reportError(`Value of the host listener "${propName}" needs to be a string representing an expression but got "${expression}" (${typeof expression})`, sourceSpan);
}
}
return targetEvents;
}
parseInterpolation(value, sourceSpan, interpolatedTokens) {
const absoluteOffset = sourceSpan.fullStart.offset;
try {
const ast = this._exprParser.parseInterpolation(value, sourceSpan, absoluteOffset, interpolatedTokens);
if (ast) {
this.errors.push(...ast.errors);
}
return ast;
} catch (e) {
this._reportError(`${e}`, sourceSpan);
return this._exprParser.wrapLiteralPrimitive('ERROR', sourceSpan, absoluteOffset);
}
}
parseInterpolationExpression(expression, sourceSpan) {
const absoluteOffset = sourceSpan.start.offset;
try {
const ast = this._exprParser.parseInterpolationExpression(expression, sourceSpan, absoluteOffset);
if (ast) {
this.errors.push(...ast.errors);
}
return ast;
} catch (e) {
this._reportError(`${e}`, sourceSpan);
return this._exprParser.wrapLiteralPrimitive('ERROR', sourceSpan, absoluteOffset);
}
}
parseInlineTemplateBinding(tplKey, tplValue, sourceSpan, absoluteValueOffset, targetMatchableAttrs, targetProps, targetVars, isIvyAst) {
const absoluteKeyOffset = sourceSpan.start.offset + TEMPLATE_ATTR_PREFIX$1.length;
const bindings = this._parseTemplateBindings(tplKey, tplValue, sourceSpan, absoluteKeyOffset, absoluteValueOffset);
for (const binding of bindings) {
const bindingSpan = moveParseSourceSpan(sourceSpan, binding.sourceSpan);
const key = binding.key.source;
const keySpan = moveParseSourceSpan(sourceSpan, binding.key.span);
if (binding instanceof VariableBinding) {
const value = binding.value ? binding.value.source : '$implicit';
const valueSpan = binding.value ? moveParseSourceSpan(sourceSpan, binding.value.span) : undefined;
targetVars.push(new ParsedVariable(key, value, bindingSpan, keySpan, valueSpan));
} else if (binding.value) {
const srcSpan = isIvyAst ? bindingSpan : sourceSpan;
const valueSpan = moveParseSourceSpan(sourceSpan, binding.value.ast.sourceSpan);
this._parsePropertyAst(key, binding.value, false, srcSpan, keySpan, valueSpan, targetMatchableAttrs, targetProps);
} else {
targetMatchableAttrs.push([key, '']);
this.parseLiteralAttr(key, null, keySpan, absoluteValueOffset, undefined, targetMatchableAttrs, targetProps, keySpan);
}
}
}
_parseTemplateBindings(tplKey, tplValue, sourceSpan, absoluteKeyOffset, absoluteValueOffset) {
try {
const bindingsResult = this._exprParser.parseTemplateBindings(tplKey, tplValue, sourceSpan, absoluteKeyOffset, absoluteValueOffset);
bindingsResult.errors.forEach(e => this.errors.push(e));
bindingsResult.warnings.forEach(warning => {
this._reportError(warning, sourceSpan, ParseErrorLevel.WARNING);
});
return bindingsResult.templateBindings;
} catch (e) {
this._reportError(`${e}`, sourceSpan);
return [];
}
}
parseLiteralAttr(name, value, sourceSpan, absoluteOffset, valueSpan, targetMatchableAttrs, targetProps, keySpan) {
if (isLegacyAnimationLabel(name)) {
name = name.substring(1);
if (keySpan !== undefined) {
keySpan = moveParseSourceSpan(keySpan, new AbsoluteSourceSpan(keySpan.start.offset + 1, keySpan.end.offset));
}
if (value) {
this._reportError(`Assigning animation triggers via @prop="exp" attributes with an expression is invalid.` + ` Use property bindings (e.g. [@prop]="exp") or use an attribute without a value (e.g. @prop) instead.`, sourceSpan, ParseErrorLevel.ERROR);
}
this._parseLegacyAnimation(name, value, sourceSpan, absoluteOffset, keySpan, valueSpan, targetMatchableAttrs, targetProps);
} else {
targetProps.push(new ParsedProperty(name, this._exprParser.wrapLiteralPrimitive(value, '', absoluteOffset), ParsedPropertyType.LITERAL_ATTR, sourceSpan, keySpan, valueSpan));
}
}
parsePropertyBinding(name, expression, isHost, isPartOfAssignmentBinding, sourceSpan, absoluteOffset, valueSpan, targetMatchableAttrs, targetProps, keySpan) {
if (name.length === 0) {
this._reportError(`Property name is missing in binding`, sourceSpan);
}
let isLegacyAnimationProp = false;
if (name.startsWith(LEGACY_ANIMATE_PROP_PREFIX)) {
isLegacyAnimationProp = true;
name = name.substring(LEGACY_ANIMATE_PROP_PREFIX.length);
if (keySpan !== undefined) {
keySpan = moveParseSourceSpan(keySpan, new AbsoluteSourceSpan(keySpan.start.offset + LEGACY_ANIMATE_PROP_PREFIX.length, keySpan.end.offset));
}
} else if (isLegacyAnimationLabel(name)) {
isLegacyAnimationProp = true;
name = name.substring(1);
if (keySpan !== undefined) {
keySpan = moveParseSourceSpan(keySpan, new AbsoluteSourceSpan(keySpan.start.offset + 1, keySpan.end.offset));
}
}
if (isLegacyAnimationProp) {
this._parseLegacyAnimation(name, expression, sourceSpan, absoluteOffset, keySpan, valueSpan, targetMatchableAttrs, targetProps);
} else if (name.startsWith(`${ANIMATE_PREFIX}${PROPERTY_PARTS_SEPARATOR}`)) {
this._parseAnimation(name, this.parseBinding(expression, isHost, valueSpan || sourceSpan, absoluteOffset), sourceSpan, keySpan, valueSpan, targetMatchableAttrs, targetProps);
} else {
this._parsePropertyAst(name, this.parseBinding(expression, isHost, valueSpan || sourceSpan, absoluteOffset), isPartOfAssignmentBinding, sourceSpan, keySpan, valueSpan, targetMatchableAttrs, targetProps);
}
}
parsePropertyInterpolation(name, value, sourceSpan, valueSpan, targetMatchableAttrs, targetProps, keySpan, interpolatedTokens) {
const expr = this.parseInterpolation(value, valueSpan || sourceSpan, interpolatedTokens);
if (expr) {
this._parsePropertyAst(name, expr, false, sourceSpan, keySpan, valueSpan, targetMatchableAttrs, targetProps);
return true;
}
return false;
}
_parsePropertyAst(name, ast, isPartOfAssignmentBinding, sourceSpan, keySpan, valueSpan, targetMatchableAttrs, targetProps) {
targetMatchableAttrs.push([name, ast.source]);
targetProps.push(new ParsedProperty(name, ast, isPartOfAssignmentBinding ? ParsedPropertyType.TWO_WAY : ParsedPropertyType.DEFAULT, sourceSpan, keySpan, valueSpan));
}
_parseAnimation(name, ast, sourceSpan, keySpan, valueSpan, targetMatchableAttrs, targetProps) {
targetMatchableAttrs.push([name, ast.source]);
targetProps.push(new ParsedProperty(name, ast, ParsedPropertyType.ANIMATION, sourceSpan, keySpan, valueSpan));
}
_parseLegacyAnimation(name, expression, sourceSpan, absoluteOffset, keySpan, valueSpan, targetMatchableAttrs, targetProps) {
if (name.length === 0) {
this._reportError('Animation trigger is missing', sourceSpan);
}
const ast = this.parseBinding(expression || 'undefined', false, valueSpan || sourceSpan, absoluteOffset);
targetMatchableAttrs.push([name, ast.source]);
targetProps.push(new ParsedProperty(name, ast, ParsedPropertyType.LEGACY_ANIMATION, sourceSpan, keySpan, valueSpan));
}
parseBinding(value, isHostBinding, sourceSpan, absoluteOffset) {
try {
const ast = isHostBinding ? this._exprParser.parseSimpleBinding(value, sourceSpan, absoluteOffset) : this._exprParser.parseBinding(value, sourceSpan, absoluteOffset);
if (ast) {
this.errors.push(...ast.errors);
}
return ast;
} catch (e) {
this._reportError(`${e}`, sourceSpan);
return this._exprParser.wrapLiteralPrimitive('ERROR', sourceSpan, absoluteOffset);
}
}
createBoundElementProperty(elementSelector, boundProp, skipValidation = false, mapPropertyName = true) {
if (boundProp.isLegacyAnimation) {
return new BoundElementProperty(boundProp.name, BindingType.LegacyAnimation, SecurityContext.NONE, boundProp.expression, null, boundProp.sourceSpan, boundProp.keySpan, boundProp.valueSpan);
}
let unit = null;
let bindingType = undefined;
let boundPropertyName = null;
const parts = boundProp.name.split(PROPERTY_PARTS_SEPARATOR);
let securityContexts = undefined;
if (parts.length > 1) {
if (parts[0] == ATTRIBUTE_PREFIX) {
boundPropertyName = parts.slice(1).join(PROPERTY_PARTS_SEPARATOR);
if (!skipValidation) {
this._validatePropertyOrAttributeName(boundPropertyName, boundProp.sourceSpan, true);
}
securityContexts = calcPossibleSecurityContexts(this._schemaRegistry, elementSelector, boundPropertyName, true);
const nsSeparatorIdx = boundPropertyName.indexOf(':');
if (nsSeparatorIdx > -1) {
const ns = boundPropertyName.substring(0, nsSeparatorIdx);
const name = boundPropertyName.substring(nsSeparatorIdx + 1);
boundPropertyName = mergeNsAndName(ns, name);
}
bindingType = BindingType.Attribute;
} else if (parts[0] == CLASS_PREFIX) {
boundPropertyName = parts[1];
bindingType = BindingType.Class;
securityContexts = [SecurityContext.NONE];
} else if (parts[0] == STYLE_PREFIX) {
unit = parts.length > 2 ? parts[2] : null;
boundPropertyName = parts[1];
bindingType = BindingType.Style;
securityContexts = [SecurityContext.STYLE];
} else if (parts[0] == ANIMATE_PREFIX) {
boundPropertyName = boundProp.name;
bindingType = BindingType.Animation;
securityContexts = [SecurityContext.NONE];
}
}
if (boundPropertyName === null) {
const mappedPropName = this._schemaRegistry.getMappedPropName(boundProp.name);
boundPropertyName = mapPropertyName ? mappedPropName : boundProp.name;
securityContexts = calcPossibleSecurityContexts(this._schemaRegistry, elementSelector, mappedPropName, false);
bindingType = boundProp.type === ParsedPropertyType.TWO_WAY ? BindingType.TwoWay : BindingType.Property;
if (!skipValidation) {
this._validatePropertyOrAttributeName(mappedPropName, boundProp.sourceSpan, false);
}
}
return new BoundElementProperty(boundPropertyName, bindingType, securityContexts[0], boundProp.expression, unit, boundProp.sourceSpan, boundProp.keySpan, boundProp.valueSpan);
}
parseEvent(name, expression, isAssignmentEvent, sourceSpan, handlerSpan, targetMatchableAttrs, targetEvents, keySpan) {
if (name.length === 0) {
this._reportError(`Event name is missing in binding`, sourceSpan);
}
if (isLegacyAnimationLabel(name)) {
name = name.slice(1);
if (keySpan !== undefined) {
keySpan = moveParseSourceSpan(keySpan, new AbsoluteSourceSpan(keySpan.start.offset + 1, keySpan.end.offset));
}
this._parseLegacyAnimationEvent(name, expression, sourceSpan, handlerSpan, targetEvents, keySpan);
} else {
this._parseRegularEvent(name, expression, isAssignmentEvent, sourceSpan, handlerSpan, targetMatchableAttrs, targetEvents, keySpan);
}
}
calcPossibleSecurityContexts(selector, propName, isAttribute) {
const prop = this._schemaRegistry.getMappedPropName(propName);
return calcPossibleSecurityContexts(this._schemaRegistry, selector, prop, isAttribute);
}
parseEventListenerName(rawName) {
const [target, eventName] = splitAtColon(rawName, [null, rawName]);
return {
eventName: eventName,
target
};
}
parseLegacyAnimationEventName(rawName) {
const matches = splitAtPeriod(rawName, [rawName, null]);
return {
eventName: matches[0],
phase: matches[1] === null ? null : matches[1].toLowerCase()
};
}
_parseLegacyAnimationEvent(name, expression, sourceSpan, handlerSpan, targetEvents, keySpan) {
const {
eventName,
phase
} = this.parseLegacyAnimationEventName(name);
const ast = this._parseAction(expression, handlerSpan);
targetEvents.push(new ParsedEvent(eventName, phase, ParsedEventType.LegacyAnimation, ast, sourceSpan, handlerSpan, keySpan));
if (eventName.length === 0) {
this._reportError(`Animation event name is missing in binding`, sourceSpan);
}
if (phase) {
if (phase !== 'start' && phase !== 'done') {
this._reportError(`The provided animation output phase value "${phase}" for "@${eventName}" is not supported (use start or done)`, sourceSpan);
}
} else {
this._reportError(`The animation trigger output event (@${eventName}) is missing its phase value name (start or done are currently supported)`, sourceSpan);
}
}
_parseRegularEvent(name, expression, isAssignmentEvent, sourceSpan, handlerSpan, targetMatchableAttrs, targetEvents, keySpan) {
const {
eventName,
target
} = this.parseEventListenerName(name);
const prevErrorCount = this.errors.length;
const ast = this._parseAction(expression, handlerSpan);
const isValid = this.errors.length === prevErrorCount;
targetMatchableAttrs.push([name, ast.source]);
if (isAssignmentEvent && isValid && !this._isAllowedAssignmentEvent(ast)) {
this._reportError('Unsupported expression in a two-way binding', sourceSpan);
}
let eventType = ParsedEventType.Regular;
if (isAssignmentEvent) {
eventType = ParsedEventType.TwoWay;
}
if (name.startsWith(`${ANIMATE_PREFIX}${PROPERTY_PARTS_SEPARATOR}`)) {
eventType = ParsedEventType.Animation;
}
targetEvents.push(new ParsedEvent(eventName, target, eventType, ast, sourceSpan, handlerSpan, keySpan));
}
_parseAction(value, sourceSpan) {
const absoluteOffset = sourceSpan && sourceSpan.start ? sourceSpan.start.offset : 0;
try {
const ast = this._exprParser.parseAction(value, sourceSpan, absoluteOffset);
if (ast) {
this.errors.push(...ast.errors);
}
if (!ast || ast.ast instanceof EmptyExpr$1) {
this._reportError(`Empty expressions are not allowed`, sourceSpan);
return this._exprParser.wrapLiteralPrimitive('ERROR', sourceSpan, absoluteOffset);
}
return ast;
} catch (e) {
this._reportError(`${e}`, sourceSpan);
return this._exprParser.wrapLiteralPrimitive('ERROR', sourceSpan, absoluteOffset);
}
}
_reportError(message, sourceSpan, level = ParseErrorLevel.ERROR) {
this.errors.push(new ParseError(sourceSpan, message, level));
}
_validatePropertyOrAttributeName(propName, sourceSpan, isAttr) {
const report = isAttr ? this._schemaRegistry.validateAttribute(propName) : this._schemaRegistry.validateProperty(propName);
if (report.error) {
this._reportError(report.msg, sourceSpan, ParseErrorLevel.ERROR);
}
}
_isAllowedAssignmentEvent(ast) {
if (ast instanceof ASTWithSource) {
return this._isAllowedAssignmentEvent(ast.ast);
}
if (ast instanceof NonNullAssert) {
return this._isAllowedAssignmentEvent(ast.expression);
}
if (ast instanceof Call && ast.args.length === 1 && ast.receiver instanceof PropertyRead && ast.receiver.name === '$any' && ast.receiver.receiver instanceof ImplicitReceiver) {
return this._isAllowedAssignmentEvent(ast.args[0]);
}
if (ast instanceof PropertyRead || ast instanceof KeyedRead) {
if (!hasRecursiveSafeReceiver(ast)) {
return true;
}
}
return false;
}
}
function hasRecursiveSafeReceiver(ast) {
if (ast instanceof SafePropertyRead || ast instanceof SafeKeyedRead) {
return true;
}
if (ast instanceof ParenthesizedExpression) {
return hasRecursiveSafeReceiver(ast.expression);
}
if (ast instanceof PropertyRead || ast instanceof KeyedRead || ast instanceof Call) {
return hasRecursiveSafeReceiver(ast.receiver);
}
return false;
}
function isLegacyAnimationLabel(name) {
return name[0] == '@';
}
function calcPossibleSecurityContexts(registry, selector, propName, isAttribute) {
let ctxs;
const nameToContext = elName => registry.securityContext(elName, propName, isAttribute);
if (selector === null) {
ctxs = registry.allKnownElementNames().map(nameToContext);
} else {
ctxs = [];
CssSelector.parse(selector).forEach(selector => {
const elementNames = selector.element ? [selector.element] : registry.allKnownElementNames();
const notElementNames = new Set(selector.notSelectors.filter(selector => selector.isElementSelector()).map(selector => selector.element));
const possibleElementNames = elementNames.filter(elName => !notElementNames.has(elName));
ctxs.push(...possibleElementNames.map(nameToContext));
});
}
return ctxs.length === 0 ? [SecurityContext.NONE] : Array.from(new Set(ctxs)).sort();
}
function moveParseSourceSpan(sourceSpan, absoluteSpan) {
const startDiff = absoluteSpan.start - sourceSpan.start.offset;
const endDiff = absoluteSpan.end - sourceSpan.end.offset;
return new ParseSourceSpan(sourceSpan.start.moveBy(startDiff), sourceSpan.end.moveBy(endDiff), sourceSpan.fullStart.moveBy(startDiff), sourceSpan.details);
}
function isStyleUrlResolvable(url) {
if (url == null || url.length === 0 || url[0] == '/') return false;
const schemeMatch = url.match(URL_WITH_SCHEMA_REGEXP);
return schemeMatch === null || schemeMatch[1] == 'package' || schemeMatch[1] == 'asset';
}
const URL_WITH_SCHEMA_REGEXP = /^([^:/?#]+):/;
const NG_CONTENT_SELECT_ATTR = 'select';
const LINK_ELEMENT = 'link';
const LINK_STYLE_REL_ATTR = 'rel';
const LINK_STYLE_HREF_ATTR = 'href';
const LINK_STYLE_REL_VALUE = 'stylesheet';
const STYLE_ELEMENT = 'style';
const SCRIPT_ELEMENT = 'script';
const NG_NON_BINDABLE_ATTR = 'ngNonBindable';
const NG_PROJECT_AS = 'ngProjectAs';
function preparseElement(ast) {
let selectAttr = null;
let hrefAttr = null;
let relAttr = null;
let nonBindable = false;
let projectAs = '';
ast.attrs.forEach(attr => {
const lcAttrName = attr.name.toLowerCase();
if (lcAttrName == NG_CONTENT_SELECT_ATTR) {
selectAttr = attr.value;
} else if (lcAttrName == LINK_STYLE_HREF_ATTR) {
hrefAttr = attr.value;
} else if (lcAttrName == LINK_STYLE_REL_ATTR) {
relAttr = attr.value;
} else if (attr.name == NG_NON_BINDABLE_ATTR) {
nonBindable = true;
} else if (attr.name == NG_PROJECT_AS) {
if (attr.value.length > 0) {
projectAs = attr.value;
}
}
});
selectAttr = normalizeNgContentSelect(selectAttr);
const nodeName = ast.name.toLowerCase();
let type = PreparsedElementType.OTHER;
if (isNgContent(nodeName)) {
type = PreparsedElementType.NG_CONTENT;
} else if (nodeName == STYLE_ELEMENT) {
type = PreparsedElementType.STYLE;
} else if (nodeName == SCRIPT_ELEMENT) {
type = PreparsedElementType.SCRIPT;
} else if (nodeName == LINK_ELEMENT && relAttr == LINK_STYLE_REL_VALUE) {
type = PreparsedElementType.STYLESHEET;
}
return new PreparsedElement(type, selectAttr, hrefAttr, nonBindable, projectAs);
}
var PreparsedElementType;
(function (PreparsedElementType) {
PreparsedElementType[PreparsedElementType["NG_CONTENT"] = 0] = "NG_CONTENT";
PreparsedElementType[PreparsedElementType["STYLE"] = 1] = "STYLE";
PreparsedElementType[PreparsedElementType["STYLESHEET"] = 2] = "STYLESHEET";
PreparsedElementType[PreparsedElementType["SCRIPT"] = 3] = "SCRIPT";
PreparsedElementType[PreparsedElementType["OTHER"] = 4] = "OTHER";
})(PreparsedElementType || (PreparsedElementType = {}));
class PreparsedElement {
type;
selectAttr;
hrefAttr;
nonBindable;
projectAs;
constructor(type, selectAttr, hrefAttr, nonBindable, projectAs) {
this.type = type;
this.selectAttr = selectAttr;
this.hrefAttr = hrefAttr;
this.nonBindable = nonBindable;
this.projectAs = projectAs;
}
}
function normalizeNgContentSelect(selectAttr) {
if (selectAttr === null || selectAttr.length === 0) {
return '*';
}
return selectAttr;
}
const FOR_LOOP_EXPRESSION_PATTERN = /^\s*([0-9A-Za-z_$]*)\s+of\s+([\S\s]*)/;
const FOR_LOOP_TRACK_PATTERN = /^track\s+([\S\s]*)/;
const CONDITIONAL_ALIAS_PATTERN = /^(as\s+)(.*)/;
const ELSE_IF_PATTERN = /^else[^\S\r\n]+if/;
const FOR_LOOP_LET_PATTERN = /^let\s+([\S\s]*)/;
const IDENTIFIER_PATTERN = /^[$A-Z_][0-9A-Z_$]*$/i;
const CHARACTERS_IN_SURROUNDING_WHITESPACE_PATTERN = /(\s*)(\S+)(\s*)/;
const ALLOWED_FOR_LOOP_LET_VARIABLES = new Set(['$index', '$first', '$last', '$even', '$odd', '$count']);
function isConnectedForLoopBlock(name) {
return name === 'empty';
}
function isConnectedIfLoopBlock(name) {
return name === 'else' || ELSE_IF_PATTERN.test(name);
}
function createIfBlock(ast, connectedBlocks, visitor, bindingParser) {
const errors = validateIfConnectedBlocks(connectedBlocks);
const branches = [];
const mainBlockParams = parseConditionalBlockParameters(ast, errors, bindingParser);
if (mainBlockParams !== null) {
branches.push(new IfBlockBranch(mainBlockParams.expression, visitAll(visitor, ast.children, ast.children), mainBlockParams.expressionAlias, ast.sourceSpan, ast.startSourceSpan, ast.endSourceSpan, ast.nameSpan, ast.i18n));
}
for (const block of connectedBlocks) {
if (ELSE_IF_PATTERN.test(block.name)) {
const params = parseConditionalBlockParameters(block, errors, bindingParser);
if (params !== null) {
const children = visitAll(visitor, block.children, block.children);
branches.push(new IfBlockBranch(params.expression, children, params.expressionAlias, block.sourceSpan, block.startSourceSpan, block.endSourceSpan, block.nameSpan, block.i18n));
}
} else if (block.name === 'else') {
const children = visitAll(visitor, block.children, block.children);
branches.push(new IfBlockBranch(null, children, null, block.sourceSpan, block.startSourceSpan, block.endSourceSpan, block.nameSpan, block.i18n));
}
}
const ifBlockStartSourceSpan = branches.length > 0 ? branches[0].startSourceSpan : ast.startSourceSpan;
const ifBlockEndSourceSpan = branches.length > 0 ? branches[branches.length - 1].endSourceSpan : ast.endSourceSpan;
let wholeSourceSpan = ast.sourceSpan;
const lastBranch = branches[branches.length - 1];
if (lastBranch !== undefined) {
wholeSourceSpan = new ParseSourceSpan(ifBlockStartSourceSpan.start, lastBranch.sourceSpan.end);
}
return {
node: new IfBlock(branches, wholeSourceSpan, ast.startSourceSpan, ifBlockEndSourceSpan, ast.nameSpan),
errors
};
}
function createForLoop(ast, connectedBlocks, visitor, bindingParser) {
const errors = [];
const params = parseForLoopParameters(ast, errors, bindingParser);
let node = null;
let empty = null;
for (const block of connectedBlocks) {
if (block.name === 'empty') {
if (empty !== null) {
errors.push(new ParseError(block.sourceSpan, '@for loop can only have one @empty block'));
} else if (block.parameters.length > 0) {
errors.push(new ParseError(block.sourceSpan, '@empty block cannot have parameters'));
} else {
empty = new ForLoopBlockEmpty(visitAll(visitor, block.children, block.children), block.sourceSpan, block.startSourceSpan, block.endSourceSpan, block.nameSpan, block.i18n);
}
} else {
errors.push(new ParseError(block.sourceSpan, `Unrecognized @for loop block "${block.name}"`));
}
}
if (params !== null) {
if (params.trackBy === null) {
errors.push(new ParseError(ast.startSourceSpan, '@for loop must have a "track" expression'));
} else {
const endSpan = empty?.endSourceSpan ?? ast.endSourceSpan;
const sourceSpan = new ParseSourceSpan(ast.sourceSpan.start, endSpan?.end ?? ast.sourceSpan.end);
validateTrackByExpression(params.trackBy.expression, params.trackBy.keywordSpan, errors);
node = new ForLoopBlock(params.itemName, params.expression, params.trackBy.expression, params.trackBy.keywordSpan, params.context, visitAll(visitor, ast.children, ast.children), empty, sourceSpan, ast.sourceSpan, ast.startSourceSpan, endSpan, ast.nameSpan, ast.i18n);
}
}
return {
node,
errors
};
}
function createSwitchBlock(ast, visitor, bindingParser) {
const errors = validateSwitchBlock(ast);
const primaryExpression = ast.parameters.length > 0 ? parseBlockParameterToBinding(ast.parameters[0], bindingParser) : bindingParser.parseBinding('', false, ast.sourceSpan, 0);
const groups = [];
const unknownBlocks = [];
let collectedCases = [];
let firstCaseStart = null;
for (const node of ast.children) {
if (!(node instanceof Block)) {
continue;
}
if ((node.name !== 'case' || node.parameters.length === 0) && node.name !== 'default') {
unknownBlocks.push(new UnknownBlock(node.name, node.sourceSpan, node.nameSpan));
continue;
}
const isCase = node.name === 'case';
let expression = null;
if (isCase) {
expression = parseBlockParameterToBinding(node.parameters[0], bindingParser);
}
const switchCase = new SwitchBlockCase(expression, node.sourceSpan, node.startSourceSpan, node.endSourceSpan, node.nameSpan);
collectedCases.push(switchCase);
const caseWithoutBody = node.children.length === 0 && node.endSourceSpan !== null && node.endSourceSpan.start.offset === node.endSourceSpan.end.offset;
if (caseWithoutBody) {
if (firstCaseStart === null) {
firstCaseStart = node.sourceSpan;
}
continue;
}
let sourceSpan = node.sourceSpan;
let startSourceSpan = node.startSourceSpan;
if (firstCaseStart !== null) {
sourceSpan = new ParseSourceSpan(firstCaseStart.start, node.sourceSpan.end);
startSourceSpan = new ParseSourceSpan(firstCaseStart.start, node.startSourceSpan.end);
firstCaseStart = null;
}
const group = new SwitchBlockCaseGroup(collectedCases, visitAll(visitor, node.children, node.children), sourceSpan, startSourceSpan, node.endSourceSpan, node.nameSpan, node.i18n);
groups.push(group);
collectedCases = [];
}
const node = new SwitchBlock(primaryExpression, groups, unknownBlocks, ast.sourceSpan, ast.startSourceSpan, ast.endSourceSpan, ast.nameSpan);
return {
node,
errors
};
}
function parseForLoopParameters(block, errors, bindingParser) {
if (block.parameters.length === 0) {
errors.push(new ParseError(block.startSourceSpan, '@for loop does not have an expression'));
return null;
}
const [expressionParam, ...secondaryParams] = block.parameters;
const match = stripOptionalParentheses(expressionParam, errors)?.match(FOR_LOOP_EXPRESSION_PATTERN);
if (!match || match[2].trim().length === 0) {
errors.push(new ParseError(expressionParam.sourceSpan, 'Cannot parse expression. @for loop expression must match the pattern "<identifier> of <expression>"'));
return null;
}
const [, itemName, rawExpression] = match;
if (ALLOWED_FOR_LOOP_LET_VARIABLES.has(itemName)) {
errors.push(new ParseError(expressionParam.sourceSpan, `@for loop item name cannot be one of ${Array.from(ALLOWED_FOR_LOOP_LET_VARIABLES).join(', ')}.`));
}
const variableName = expressionParam.expression.split(' ')[0];
const variableSpan = new ParseSourceSpan(expressionParam.sourceSpan.start, expressionParam.sourceSpan.start.moveBy(variableName.length));
const result = {
itemName: new Variable(itemName, '$implicit', variableSpan, variableSpan),
trackBy: null,
expression: parseBlockParameterToBinding(expressionParam, bindingParser, rawExpression),
context: Array.from(ALLOWED_FOR_LOOP_LET_VARIABLES, variableName => {
const emptySpanAfterForBlockStart = new ParseSourceSpan(block.startSourceSpan.end, block.startSourceSpan.end);
return new Variable(variableName, variableName, emptySpanAfterForBlockStart, emptySpanAfterForBlockStart);
})
};
for (const param of secondaryParams) {
const letMatch = param.expression.match(FOR_LOOP_LET_PATTERN);
if (letMatch !== null) {
const variablesSpan = new ParseSourceSpan(param.sourceSpan.start.moveBy(letMatch[0].length - letMatch[1].length), param.sourceSpan.end);
parseLetParameter(param.sourceSpan, letMatch[1], variablesSpan, itemName, result.context, errors);
continue;
}
const trackMatch = param.expression.match(FOR_LOOP_TRACK_PATTERN);
if (trackMatch !== null) {
if (result.trackBy !== null) {
errors.push(new ParseError(param.sourceSpan, '@for loop can only have one "track" expression'));
} else {
const expression = parseBlockParameterToBinding(param, bindingParser, trackMatch[1]);
if (expression.ast instanceof EmptyExpr$1) {
errors.push(new ParseError(block.startSourceSpan, '@for loop must have a "track" expression'));
}
const keywordSpan = new ParseSourceSpan(param.sourceSpan.start, param.sourceSpan.start.moveBy('track'.length));
result.trackBy = {
expression,
keywordSpan
};
}
continue;
}
errors.push(new ParseError(param.sourceSpan, `Unrecognized @for loop parameter "${param.expression}"`));
}
return result;
}
function validateTrackByExpression(expression, parseSourceSpan, errors) {
const visitor = new PipeVisitor();
expression.ast.visit(visitor);
if (visitor.hasPipe) {
errors.push(new ParseError(parseSourceSpan, 'Cannot use pipes in track expressions'));
}
}
function parseLetParameter(sourceSpan, expression, span, loopItemName, context, errors) {
const parts = expression.split(',');
let startSpan = span.start;
for (const part of parts) {
const expressionParts = part.split('=');
const name = expressionParts.length === 2 ? expressionParts[0].trim() : '';
const variableName = expressionParts.length === 2 ? expressionParts[1].trim() : '';
if (name.length === 0 || variableName.length === 0) {
errors.push(new ParseError(sourceSpan, `Invalid @for loop "let" parameter. Parameter should match the pattern "<name> = <variable name>"`));
} else if (!ALLOWED_FOR_LOOP_LET_VARIABLES.has(variableName)) {
errors.push(new ParseError(sourceSpan, `Unknown "let" parameter variable "${variableName}". The allowed variables are: ${Array.from(ALLOWED_FOR_LOOP_LET_VARIABLES).join(', ')}`));
} else if (name === loopItemName) {
errors.push(new ParseError(sourceSpan, `Invalid @for loop "let" parameter. Variable cannot be called "${loopItemName}"`));
} else if (context.some(v => v.name === name)) {
errors.push(new ParseError(sourceSpan, `Duplicate "let" parameter variable "${variableName}"`));
} else {
const [, keyLeadingWhitespace, keyName] = expressionParts[0].match(CHARACTERS_IN_SURROUNDING_WHITESPACE_PATTERN) ?? [];
const keySpan = keyLeadingWhitespace !== undefined && expressionParts.length === 2 ? new ParseSourceSpan(startSpan.moveBy(keyLeadingWhitespace.length), startSpan.moveBy(keyLeadingWhitespace.length + keyName.length)) : span;
let valueSpan = undefined;
if (expressionParts.length === 2) {
const [, valueLeadingWhitespace, implicit] = expressionParts[1].match(CHARACTERS_IN_SURROUNDING_WHITESPACE_PATTERN) ?? [];
valueSpan = valueLeadingWhitespace !== undefined ? new ParseSourceSpan(startSpan.moveBy(expressionParts[0].length + 1 + valueLeadingWhitespace.length), startSpan.moveBy(expressionParts[0].length + 1 + valueLeadingWhitespace.length + implicit.length)) : undefined;
}
const sourceSpan = new ParseSourceSpan(keySpan.start, valueSpan?.end ?? keySpan.end);
context.push(new Variable(name, variableName, sourceSpan, keySpan, valueSpan));
}
startSpan = startSpan.moveBy(part.length + 1);
}
}
function validateIfConnectedBlocks(connectedBlocks) {
const errors = [];
let hasElse = false;
for (let i = 0; i < connectedBlocks.length; i++) {
const block = connectedBlocks[i];
if (block.name === 'else') {
if (hasElse) {
errors.push(new ParseError(block.startSourceSpan, 'Conditional can only have one @else block'));
} else if (connectedBlocks.length > 1 && i < connectedBlocks.length - 1) {
errors.push(new ParseError(block.startSourceSpan, '@else block must be last inside the conditional'));
} else if (block.parameters.length > 0) {
errors.push(new ParseError(block.startSourceSpan, '@else block cannot have parameters'));
}
hasElse = true;
} else if (!ELSE_IF_PATTERN.test(block.name)) {
errors.push(new ParseError(block.startSourceSpan, `Unrecognized conditional block @${block.name}`));
}
}
return errors;
}
function validateSwitchBlock(ast) {
const errors = [];
let hasDefault = false;
if (ast.parameters.length !== 1) {
errors.push(new ParseError(ast.startSourceSpan, '@switch block must have exactly one parameter'));
return errors;
}
for (const node of ast.children) {
if (node instanceof Comment || node instanceof Text && node.value.trim().length === 0) {
continue;
}
if (!(node instanceof Block) || node.name !== 'case' && node.name !== 'default') {
errors.push(new ParseError(node.sourceSpan, '@switch block can only contain @case and @default blocks'));
continue;
}
if (node.name === 'default') {
if (hasDefault) {
errors.push(new ParseError(node.startSourceSpan, '@switch block can only have one @default block'));
} else if (node.parameters.length > 0) {
errors.push(new ParseError(node.startSourceSpan, '@default block cannot have parameters'));
}
hasDefault = true;
} else if (node.name === 'case' && node.parameters.length !== 1) {
errors.push(new ParseError(node.startSourceSpan, '@case block must have exactly one parameter'));
}
}
return errors;
}
function parseBlockParameterToBinding(ast, bindingParser, part) {
let start;
let end;
if (typeof part === 'string') {
start = Math.max(0, ast.expression.lastIndexOf(part));
end = start + part.length;
} else {
start = 0;
end = ast.expression.length;
}
return bindingParser.parseBinding(ast.expression.slice(start, end), false, ast.sourceSpan, ast.sourceSpan.start.offset + start);
}
function parseConditionalBlockParameters(block, errors, bindingParser) {
if (block.parameters.length === 0) {
errors.push(new ParseError(block.startSourceSpan, 'Conditional block does not have an expression'));
return null;
}
const expression = parseBlockParameterToBinding(block.parameters[0], bindingParser);
let expressionAlias = null;
for (let i = 1; i < block.parameters.length; i++) {
const param = block.parameters[i];
const aliasMatch = param.expression.match(CONDITIONAL_ALIAS_PATTERN);
if (aliasMatch === null) {
errors.push(new ParseError(param.sourceSpan, `Unrecognized conditional parameter "${param.expression}"`));
} else if (block.name !== 'if' && !ELSE_IF_PATTERN.test(block.name)) {
errors.push(new ParseError(param.sourceSpan, '"as" expression is only allowed on `@if` and `@else if` blocks'));
} else if (expressionAlias !== null) {
errors.push(new ParseError(param.sourceSpan, 'Conditional can only have one "as" expression'));
} else {
const name = aliasMatch[2].trim();
if (IDENTIFIER_PATTERN.test(name)) {
const variableStart = param.sourceSpan.start.moveBy(aliasMatch[1].length);
const variableSpan = new ParseSourceSpan(variableStart, variableStart.moveBy(name.length));
expressionAlias = new Variable(name, name, variableSpan, variableSpan);
} else {
errors.push(new ParseError(param.sourceSpan, '"as" expression must be a valid JavaScript identifier'));
}
}
}
return {
expression,
expressionAlias
};
}
function stripOptionalParentheses(param, errors) {
const expression = param.expression;
const spaceRegex = /^\s$/;
let openParens = 0;
let start = 0;
let end = expression.length - 1;
for (let i = 0; i < expression.length; i++) {
const char = expression[i];
if (char === '(') {
start = i + 1;
openParens++;
} else if (spaceRegex.test(char)) {
continue;
} else {
break;
}
}
if (openParens === 0) {
return expression;
}
for (let i = expression.length - 1; i > -1; i--) {
const char = expression[i];
if (char === ')') {
end = i;
openParens--;
if (openParens === 0) {
break;
}
} else if (spaceRegex.test(char)) {
continue;
} else {
break;
}
}
if (openParens !== 0) {
errors.push(new ParseError(param.sourceSpan, 'Unclosed parentheses in expression'));
return null;
}
return expression.slice(start, end);
}
class PipeVisitor extends RecursiveAstVisitor {
hasPipe = false;
visitPipe() {
this.hasPipe = true;
}
}
const TIME_PATTERN = /^\d+\.?\d*(ms|s)?$/;
const SEPARATOR_PATTERN = /^\s$/;
const COMMA_DELIMITED_SYNTAX = new Map([[$LBRACE, $RBRACE], [$LBRACKET, $RBRACKET], [$LPAREN, $RPAREN]]);
var OnTriggerType;
(function (OnTriggerType) {
OnTriggerType["IDLE"] = "idle";
OnTriggerType["TIMER"] = "timer";
OnTriggerType["INTERACTION"] = "interaction";
OnTriggerType["IMMEDIATE"] = "immediate";
OnTriggerType["HOVER"] = "hover";
OnTriggerType["VIEWPORT"] = "viewport";
OnTriggerType["NEVER"] = "never";
})(OnTriggerType || (OnTriggerType = {}));
function parseNeverTrigger({
expression,
sourceSpan
}, triggers, errors) {
const neverIndex = expression.indexOf('never');
const neverSourceSpan = new ParseSourceSpan(sourceSpan.start.moveBy(neverIndex), sourceSpan.start.moveBy(neverIndex + 'never'.length));
const prefetchSpan = getPrefetchSpan(expression, sourceSpan);
const hydrateSpan = getHydrateSpan(expression, sourceSpan);
if (neverIndex === -1) {
errors.push(new ParseError(sourceSpan, `Could not find "never" keyword in expression`));
} else {
trackTrigger('never', triggers, errors, new NeverDeferredTrigger(neverSourceSpan, sourceSpan, prefetchSpan, null, hydrateSpan));
}
}
function parseWhenTrigger({
expression,
sourceSpan
}, bindingParser, triggers, errors) {
const whenIndex = expression.indexOf('when');
const whenSourceSpan = new ParseSourceSpan(sourceSpan.start.moveBy(whenIndex), sourceSpan.start.moveBy(whenIndex + 'when'.length));
const prefetchSpan = getPrefetchSpan(expression, sourceSpan);
const hydrateSpan = getHydrateSpan(expression, sourceSpan);
if (whenIndex === -1) {
errors.push(new ParseError(sourceSpan, `Could not find "when" keyword in expression`));
} else {
const start = getTriggerParametersStart(expression, whenIndex + 1);
const parsed = bindingParser.parseBinding(expression.slice(start), false, sourceSpan, sourceSpan.start.offset + start);
trackTrigger('when', triggers, errors, new BoundDeferredTrigger(parsed, sourceSpan, prefetchSpan, whenSourceSpan, hydrateSpan));
}
}
function parseOnTrigger({
expression,
sourceSpan
}, bindingParser, triggers, errors, placeholder) {
const onIndex = expression.indexOf('on');
const onSourceSpan = new ParseSourceSpan(sourceSpan.start.moveBy(onIndex), sourceSpan.start.moveBy(onIndex + 'on'.length));
const prefetchSpan = getPrefetchSpan(expression, sourceSpan);
const hydrateSpan = getHydrateSpan(expression, sourceSpan);
if (onIndex === -1) {
errors.push(new ParseError(sourceSpan, `Could not find "on" keyword in expression`));
} else {
const start = getTriggerParametersStart(expression, onIndex + 1);
const isHydrationTrigger = expression.startsWith('hydrate');
const parser = new OnTriggerParser(expression, bindingParser, start, sourceSpan, triggers, errors, isHydrationTrigger ? validateHydrateReferenceBasedTrigger : validatePlainReferenceBasedTrigger, isHydrationTrigger, prefetchSpan, onSourceSpan, hydrateSpan);
parser.parse();
}
}
function getPrefetchSpan(expression, sourceSpan) {
if (!expression.startsWith('prefetch')) {
return null;
}
return new ParseSourceSpan(sourceSpan.start, sourceSpan.start.moveBy('prefetch'.length));
}
function getHydrateSpan(expression, sourceSpan) {
if (!expression.startsWith('hydrate')) {
return null;
}
return new ParseSourceSpan(sourceSpan.start, sourceSpan.start.moveBy('hydrate'.length));
}
class OnTriggerParser {
expression;
bindingParser;
start;
span;
triggers;
errors;
validator;
isHydrationTrigger;
prefetchSpan;
onSourceSpan;
hydrateSpan;
index = 0;
tokens;
constructor(expression, bindingParser, start, span, triggers, errors, validator, isHydrationTrigger, prefetchSpan, onSourceSpan, hydrateSpan) {
this.expression = expression;
this.bindingParser = bindingParser;
this.start = start;
this.span = span;
this.triggers = triggers;
this.errors = errors;
this.validator = validator;
this.isHydrationTrigger = isHydrationTrigger;
this.prefetchSpan = prefetchSpan;
this.onSourceSpan = onSourceSpan;
this.hydrateSpan = hydrateSpan;
this.tokens = new Lexer().tokenize(expression.slice(start));
}
parse() {
while (this.tokens.length > 0 && this.index < this.tokens.length) {
const token = this.token();
if (!token.isIdentifier()) {
this.unexpectedToken(token);
break;
}
if (this.isFollowedByOrLast($COMMA)) {
this.consumeTrigger(token, []);
this.advance();
} else if (this.isFollowedByOrLast($LPAREN)) {
this.advance();
const prevErrors = this.errors.length;
const parameters = this.consumeParameters();
if (this.errors.length !== prevErrors) {
break;
}
this.consumeTrigger(token, parameters);
this.advance();
} else if (this.index < this.tokens.length - 1) {
this.unexpectedToken(this.tokens[this.index + 1]);
}
this.advance();
}
}
advance() {
this.index++;
}
isFollowedByOrLast(char) {
if (this.index === this.tokens.length - 1) {
return true;
}
return this.tokens[this.index + 1].isCharacter(char);
}
token() {
return this.tokens[Math.min(this.index, this.tokens.length - 1)];
}
consumeTrigger(identifier, parameters) {
const triggerNameStartSpan = this.span.start.moveBy(this.start + identifier.index - this.tokens[0].index);
const nameSpan = new ParseSourceSpan(triggerNameStartSpan, triggerNameStartSpan.moveBy(identifier.strValue.length));
const endSpan = triggerNameStartSpan.moveBy(this.token().end - identifier.index);
const isFirstTrigger = identifier.index === 0;
const onSourceSpan = isFirstTrigger ? this.onSourceSpan : null;
const prefetchSourceSpan = isFirstTrigger ? this.prefetchSpan : null;
const hydrateSourceSpan = isFirstTrigger ? this.hydrateSpan : null;
const sourceSpan = new ParseSourceSpan(isFirstTrigger ? this.span.start : triggerNameStartSpan, endSpan);
try {
switch (identifier.toString()) {
case OnTriggerType.IDLE:
this.trackTrigger('idle', createIdleTrigger(parameters, nameSpan, sourceSpan, prefetchSourceSpan, onSourceSpan, hydrateSourceSpan));
break;
case OnTriggerType.TIMER:
this.trackTrigger('timer', createTimerTrigger(parameters, nameSpan, sourceSpan, this.prefetchSpan, this.onSourceSpan, this.hydrateSpan));
break;
case OnTriggerType.INTERACTION:
this.trackTrigger('interaction', createInteractionTrigger(parameters, nameSpan, sourceSpan, this.prefetchSpan, this.onSourceSpan, this.hydrateSpan, this.validator));
break;
case OnTriggerType.IMMEDIATE:
this.trackTrigger('immediate', createImmediateTrigger(parameters, nameSpan, sourceSpan, this.prefetchSpan, this.onSourceSpan, this.hydrateSpan));
break;
case OnTriggerType.HOVER:
this.trackTrigger('hover', createHoverTrigger(parameters, nameSpan, sourceSpan, this.prefetchSpan, this.onSourceSpan, this.hydrateSpan, this.validator));
break;
case OnTriggerType.VIEWPORT:
this.trackTrigger('viewport', createViewportTrigger(this.start, this.isHydrationTrigger, this.bindingParser, parameters, nameSpan, sourceSpan, this.prefetchSpan, this.onSourceSpan, this.hydrateSpan, this.validator));
break;
default:
throw new Error(`Unrecognized trigger type "${identifier}"`);
}
} catch (e) {
this.error(identifier, e.message);
}
}
consumeParameters() {
const parameters = [];
if (!this.token().isCharacter($LPAREN)) {
this.unexpectedToken(this.token());
return parameters;
}
this.advance();
const commaDelimStack = [];
let tokens = [];
while (this.index < this.tokens.length) {
const token = this.token();
if (token.isCharacter($RPAREN) && commaDelimStack.length === 0) {
if (tokens.length) {
parameters.push({
expression: this.tokenRangeText(tokens),
start: tokens[0].index
});
}
break;
}
if (token.type === TokenType.Character && COMMA_DELIMITED_SYNTAX.has(token.numValue)) {
commaDelimStack.push(COMMA_DELIMITED_SYNTAX.get(token.numValue));
}
if (commaDelimStack.length > 0 && token.isCharacter(commaDelimStack[commaDelimStack.length - 1])) {
commaDelimStack.pop();
}
if (commaDelimStack.length === 0 && token.isCharacter($COMMA) && tokens.length > 0) {
parameters.push({
expression: this.tokenRangeText(tokens),
start: tokens[0].index
});
this.advance();
tokens = [];
continue;
}
tokens.push(token);
this.advance();
}
if (!this.token().isCharacter($RPAREN) || commaDelimStack.length > 0) {
this.error(this.token(), 'Unexpected end of expression');
}
if (this.index < this.tokens.length - 1 && !this.tokens[this.index + 1].isCharacter($COMMA)) {
this.unexpectedToken(this.tokens[this.index + 1]);
}
return parameters;
}
tokenRangeText(tokens) {
if (tokens.length === 0) {
return '';
}
return this.expression.slice(this.start + tokens[0].index, this.start + tokens[tokens.length - 1].end);
}
trackTrigger(name, trigger) {
trackTrigger(name, this.triggers, this.errors, trigger);
}
error(token, message) {
const newStart = this.span.start.moveBy(this.start + token.index);
const newEnd = newStart.moveBy(token.end - token.index);
this.errors.push(new ParseError(new ParseSourceSpan(newStart, newEnd), message));
}
unexpectedToken(token) {
this.error(token, `Unexpected token "${token}"`);
}
}
function trackTrigger(name, allTriggers, errors, trigger) {
if (allTriggers[name]) {
errors.push(new ParseError(trigger.sourceSpan, `Duplicate "${name}" trigger is not allowed`));
} else {
allTriggers[name] = trigger;
}
}
function createIdleTrigger(parameters, nameSpan, sourceSpan, prefetchSpan, onSourceSpan, hydrateSpan) {
if (parameters.length > 0) {
throw new Error(`"${OnTriggerType.IDLE}" trigger cannot have parameters`);
}
return new IdleDeferredTrigger(nameSpan, sourceSpan, prefetchSpan, onSourceSpan, hydrateSpan);
}
function createTimerTrigger(parameters, nameSpan, sourceSpan, prefetchSpan, onSourceSpan, hydrateSpan) {
if (parameters.length !== 1) {
throw new Error(`"${OnTriggerType.TIMER}" trigger must have exactly one parameter`);
}
const delay = parseDeferredTime(parameters[0].expression);
if (delay === null) {
throw new Error(`Could not parse time value of trigger "${OnTriggerType.TIMER}"`);
}
return new TimerDeferredTrigger(delay, nameSpan, sourceSpan, prefetchSpan, onSourceSpan, hydrateSpan);
}
function createImmediateTrigger(parameters, nameSpan, sourceSpan, prefetchSpan, onSourceSpan, hydrateSpan) {
if (parameters.length > 0) {
throw new Error(`"${OnTriggerType.IMMEDIATE}" trigger cannot have parameters`);
}
return new ImmediateDeferredTrigger(nameSpan, sourceSpan, prefetchSpan, onSourceSpan, hydrateSpan);
}
function createHoverTrigger(parameters, nameSpan, sourceSpan, prefetchSpan, onSourceSpan, hydrateSpan, validator) {
validator(OnTriggerType.HOVER, parameters);
return new HoverDeferredTrigger(parameters[0]?.expression ?? null, nameSpan, sourceSpan, prefetchSpan, onSourceSpan, hydrateSpan);
}
function createInteractionTrigger(parameters, nameSpan, sourceSpan, prefetchSpan, onSourceSpan, hydrateSpan, validator) {
validator(OnTriggerType.INTERACTION, parameters);
return new InteractionDeferredTrigger(parameters[0]?.expression ?? null, nameSpan, sourceSpan, prefetchSpan, onSourceSpan, hydrateSpan);
}
function createViewportTrigger(start, isHydrationTrigger, bindingParser, parameters, nameSpan, sourceSpan, prefetchSpan, onSourceSpan, hydrateSpan, validator) {
validator(OnTriggerType.VIEWPORT, parameters);
let reference;
let options;
if (parameters.length === 0) {
reference = options = null;
} else if (!parameters[0].expression.startsWith('{')) {
reference = parameters[0].expression;
options = null;
} else {
const parsed = bindingParser.parseBinding(parameters[0].expression, false, sourceSpan, sourceSpan.start.offset + start + parameters[0].start);
if (!(parsed.ast instanceof LiteralMap)) {
throw new Error('Options parameter of the "viewport" trigger must be an object literal');
} else if (parsed.ast.keys.some(key => key.kind === 'spread')) {
throw new Error('Spread operator are not allowed in this context');
} else if (parsed.ast.keys.some(key => key.kind === 'property' && key.key === 'root')) {
throw new Error('The "root" option is not supported in the options parameter of the "viewport" trigger');
}
const triggerIndex = parsed.ast.keys.findIndex(key => key.kind === 'property' && key.key === 'trigger');
if (triggerIndex === -1) {
reference = null;
options = parsed.ast;
} else {
const value = parsed.ast.values[triggerIndex];
const triggerFilter = (_, index) => index !== triggerIndex;
if (!(value instanceof PropertyRead) || !(value.receiver instanceof ImplicitReceiver)) {
throw new Error(`"trigger" option of the "viewport" trigger must be an identifier`);
}
reference = value.name;
options = new LiteralMap(parsed.ast.span, parsed.ast.sourceSpan, parsed.ast.keys.filter(triggerFilter), parsed.ast.values.filter(triggerFilter));
}
}
if (isHydrationTrigger && reference !== null) {
throw new Error(`"viewport" hydration trigger cannot have a "trigger"`);
} else if (options) {
const dynamicNode = DynamicAstValidator.findDynamicNode(options);
if (dynamicNode !== null) {
throw new Error(`Options of the "viewport" trigger must be an object ` + `literal containing only literal values, but "${dynamicNode.constructor.name}" was found`);
}
}
return new ViewportDeferredTrigger(reference, options, nameSpan, sourceSpan, prefetchSpan, onSourceSpan, hydrateSpan);
}
function validatePlainReferenceBasedTrigger(type, parameters) {
if (parameters.length > 1) {
throw new Error(`"${type}" trigger can only have zero or one parameters`);
}
}
function validateHydrateReferenceBasedTrigger(type, parameters) {
if (type === OnTriggerType.VIEWPORT) {
if (parameters.length > 1) {
throw new Error(`Hydration trigger "${type}" cannot have more than one parameter`);
}
return;
}
if (parameters.length > 0) {
throw new Error(`Hydration trigger "${type}" cannot have parameters`);
}
}
function getTriggerParametersStart(value, startPosition = 0) {
let hasFoundSeparator = false;
for (let i = startPosition; i < value.length; i++) {
if (SEPARATOR_PATTERN.test(value[i])) {
hasFoundSeparator = true;
} else if (hasFoundSeparator) {
return i;
}
}
return -1;
}
function parseDeferredTime(value) {
const match = value.match(TIME_PATTERN);
if (!match) {
return null;
}
const [time, units] = match;
return parseFloat(time) * (units === 's' ? 1000 : 1);
}
class DynamicAstValidator extends RecursiveAstVisitor {
dynamicNode = null;
static findDynamicNode(ast) {
const visitor = new DynamicAstValidator();
visitor.visit(ast);
return visitor.dynamicNode;
}
visit(ast) {
if (!(ast instanceof ASTWithSource) && !(ast instanceof LiteralPrimitive) && !(ast instanceof LiteralArray) && !(ast instanceof LiteralMap)) {
this.dynamicNode = ast;
} else {
super.visit(ast);
}
}
}
const PREFETCH_WHEN_PATTERN = /^prefetch\s+when\s/;
const PREFETCH_ON_PATTERN = /^prefetch\s+on\s/;
const HYDRATE_WHEN_PATTERN = /^hydrate\s+when\s/;
const HYDRATE_ON_PATTERN = /^hydrate\s+on\s/;
const HYDRATE_NEVER_PATTERN = /^hydrate\s+never(\s*)$/;
const MINIMUM_PARAMETER_PATTERN = /^minimum\s/;
const AFTER_PARAMETER_PATTERN = /^after\s/;
const WHEN_PARAMETER_PATTERN = /^when\s/;
const ON_PARAMETER_PATTERN = /^on\s/;
function isConnectedDeferLoopBlock(name) {
return name === 'placeholder' || name === 'loading' || name === 'error';
}
function createDeferredBlock(ast, connectedBlocks, visitor, bindingParser) {
const errors = [];
const {
placeholder,
loading,
error
} = parseConnectedBlocks(connectedBlocks, errors, visitor);
const {
triggers,
prefetchTriggers,
hydrateTriggers
} = parsePrimaryTriggers(ast, bindingParser, errors);
let lastEndSourceSpan = ast.endSourceSpan;
let endOfLastSourceSpan = ast.sourceSpan.end;
if (connectedBlocks.length > 0) {
const lastConnectedBlock = connectedBlocks[connectedBlocks.length - 1];
lastEndSourceSpan = lastConnectedBlock.endSourceSpan;
endOfLastSourceSpan = lastConnectedBlock.sourceSpan.end;
}
const sourceSpanWithConnectedBlocks = new ParseSourceSpan(ast.sourceSpan.start, endOfLastSourceSpan);
const node = new DeferredBlock(visitAll(visitor, ast.children, ast.children), triggers, prefetchTriggers, hydrateTriggers, placeholder, loading, error, ast.nameSpan, sourceSpanWithConnectedBlocks, ast.sourceSpan, ast.startSourceSpan, lastEndSourceSpan, ast.i18n);
return {
node,
errors
};
}
function parseConnectedBlocks(connectedBlocks, errors, visitor) {
let placeholder = null;
let loading = null;
let error = null;
for (const block of connectedBlocks) {
try {
if (!isConnectedDeferLoopBlock(block.name)) {
errors.push(new ParseError(block.startSourceSpan, `Unrecognized block "@${block.name}"`));
break;
}
switch (block.name) {
case 'placeholder':
if (placeholder !== null) {
errors.push(new ParseError(block.startSourceSpan, `@defer block can only have one @placeholder block`));
} else {
placeholder = parsePlaceholderBlock(block, visitor);
}
break;
case 'loading':
if (loading !== null) {
errors.push(new ParseError(block.startSourceSpan, `@defer block can only have one @loading block`));
} else {
loading = parseLoadingBlock(block, visitor);
}
break;
case 'error':
if (error !== null) {
errors.push(new ParseError(block.startSourceSpan, `@defer block can only have one @error block`));
} else {
error = parseErrorBlock(block, visitor);
}
break;
}
} catch (e) {
errors.push(new ParseError(block.startSourceSpan, e.message));
}
}
return {
placeholder,
loading,
error
};
}
function parsePlaceholderBlock(ast, visitor) {
let minimumTime = null;
for (const param of ast.parameters) {
if (MINIMUM_PARAMETER_PATTERN.test(param.expression)) {
if (minimumTime != null) {
throw new Error(`@placeholder block can only have one "minimum" parameter`);
}
const parsedTime = parseDeferredTime(param.expression.slice(getTriggerParametersStart(param.expression)));
if (parsedTime === null) {
throw new Error(`Could not parse time value of parameter "minimum"`);
}
minimumTime = parsedTime;
} else {
throw new Error(`Unrecognized parameter in @placeholder block: "${param.expression}"`);
}
}
return new DeferredBlockPlaceholder(visitAll(visitor, ast.children, ast.children), minimumTime, ast.nameSpan, ast.sourceSpan, ast.startSourceSpan, ast.endSourceSpan, ast.i18n);
}
function parseLoadingBlock(ast, visitor) {
let afterTime = null;
let minimumTime = null;
for (const param of ast.parameters) {
if (AFTER_PARAMETER_PATTERN.test(param.expression)) {
if (afterTime != null) {
throw new Error(`@loading block can only have one "after" parameter`);
}
const parsedTime = parseDeferredTime(param.expression.slice(getTriggerParametersStart(param.expression)));
if (parsedTime === null) {
throw new Error(`Could not parse time value of parameter "after"`);
}
afterTime = parsedTime;
} else if (MINIMUM_PARAMETER_PATTERN.test(param.expression)) {
if (minimumTime != null) {
throw new Error(`@loading block can only have one "minimum" parameter`);
}
const parsedTime = parseDeferredTime(param.expression.slice(getTriggerParametersStart(param.expression)));
if (parsedTime === null) {
throw new Error(`Could not parse time value of parameter "minimum"`);
}
minimumTime = parsedTime;
} else {
throw new Error(`Unrecognized parameter in @loading block: "${param.expression}"`);
}
}
return new DeferredBlockLoading(visitAll(visitor, ast.children, ast.children), afterTime, minimumTime, ast.nameSpan, ast.sourceSpan, ast.startSourceSpan, ast.endSourceSpan, ast.i18n);
}
function parseErrorBlock(ast, visitor) {
if (ast.parameters.length > 0) {
throw new Error(`@error block cannot have parameters`);
}
return new DeferredBlockError(visitAll(visitor, ast.children, ast.children), ast.nameSpan, ast.sourceSpan, ast.startSourceSpan, ast.endSourceSpan, ast.i18n);
}
function parsePrimaryTriggers(ast, bindingParser, errors, placeholder) {
const triggers = {};
const prefetchTriggers = {};
const hydrateTriggers = {};
for (const param of ast.parameters) {
if (WHEN_PARAMETER_PATTERN.test(param.expression)) {
parseWhenTrigger(param, bindingParser, triggers, errors);
} else if (ON_PARAMETER_PATTERN.test(param.expression)) {
parseOnTrigger(param, bindingParser, triggers, errors);
} else if (PREFETCH_WHEN_PATTERN.test(param.expression)) {
parseWhenTrigger(param, bindingParser, prefetchTriggers, errors);
} else if (PREFETCH_ON_PATTERN.test(param.expression)) {
parseOnTrigger(param, bindingParser, prefetchTriggers, errors);
} else if (HYDRATE_WHEN_PATTERN.test(param.expression)) {
parseWhenTrigger(param, bindingParser, hydrateTriggers, errors);
} else if (HYDRATE_ON_PATTERN.test(param.expression)) {
parseOnTrigger(param, bindingParser, hydrateTriggers, errors);
} else if (HYDRATE_NEVER_PATTERN.test(param.expression)) {
parseNeverTrigger(param, hydrateTriggers, errors);
} else {
errors.push(new ParseError(param.sourceSpan, 'Unrecognized trigger'));
}
}
if (hydrateTriggers.never && Object.keys(hydrateTriggers).length > 1) {
errors.push(new ParseError(ast.startSourceSpan, 'Cannot specify additional `hydrate` triggers if `hydrate never` is present'));
}
return {
triggers,
prefetchTriggers,
hydrateTriggers
};
}
const BIND_NAME_REGEXP = /^(?:(bind-)|(let-)|(ref-|#)|(on-)|(bindon-)|(@))(.*)$/;
const KW_BIND_IDX = 1;
const KW_LET_IDX = 2;
const KW_REF_IDX = 3;
const KW_ON_IDX = 4;
const KW_BINDON_IDX = 5;
const KW_AT_IDX = 6;
const IDENT_KW_IDX = 7;
const BINDING_DELIMS = {
BANANA_BOX: {
start: '[(',
end: ')]'
},
PROPERTY: {
start: '[',
end: ']'
},
EVENT: {
start: '(',
end: ')'
}
};
const TEMPLATE_ATTR_PREFIX = '*';
const UNSUPPORTED_SELECTORLESS_TAGS = new Set(['link', 'style', 'script', 'ng-template', 'ng-container', 'ng-content']);
const UNSUPPORTED_SELECTORLESS_DIRECTIVE_ATTRS = new Set(['ngProjectAs', 'ngNonBindable']);
function htmlAstToRender3Ast(htmlNodes, bindingParser, options) {
const transformer = new HtmlAstToIvyAst(bindingParser, options);
const ivyNodes = visitAll(transformer, htmlNodes, htmlNodes);
const allErrors = bindingParser.errors.concat(transformer.errors);
const result = {
nodes: ivyNodes,
errors: allErrors,
styleUrls: transformer.styleUrls,
styles: transformer.styles,
ngContentSelectors: transformer.ngContentSelectors
};
if (options.collectCommentNodes) {
result.commentNodes = transformer.commentNodes;
}
return result;
}
class HtmlAstToIvyAst {
bindingParser;
options;
errors = [];
styles = [];
styleUrls = [];
ngContentSelectors = [];
commentNodes = [];
inI18nBlock = false;
processedNodes = new Set();
constructor(bindingParser, options) {
this.bindingParser = bindingParser;
this.options = options;
}
visitElement(element) {
const isI18nRootElement = isI18nRootNode(element.i18n);
if (isI18nRootElement) {
if (this.inI18nBlock) {
this.reportError('Cannot mark an element as translatable inside of a translatable section. Please remove the nested i18n marker.', element.sourceSpan);
}
this.inI18nBlock = true;
}
const preparsedElement = preparseElement(element);
if (preparsedElement.type === PreparsedElementType.SCRIPT) {
return null;
} else if (preparsedElement.type === PreparsedElementType.STYLE) {
const contents = textContents(element);
if (contents !== null) {
this.styles.push(contents);
}
return null;
} else if (preparsedElement.type === PreparsedElementType.STYLESHEET && isStyleUrlResolvable(preparsedElement.hrefAttr)) {
this.styleUrls.push(preparsedElement.hrefAttr);
return null;
}
const isTemplateElement = isNgTemplate(element.name);
const {
attributes,
boundEvents,
references,
variables,
templateVariables,
elementHasInlineTemplate,
parsedProperties,
templateParsedProperties,
i18nAttrsMeta
} = this.prepareAttributes(element.attrs, isTemplateElement);
const directives = this.extractDirectives(element);
let children;
if (preparsedElement.nonBindable) {
children = visitAll(NON_BINDABLE_VISITOR, element.children).flat(Infinity);
} else {
children = visitAll(this, element.children, element.children);
}
let parsedElement;
if (preparsedElement.type === PreparsedElementType.NG_CONTENT) {
const selector = preparsedElement.selectAttr;
const attrs = element.attrs.map(attr => this.visitAttribute(attr));
parsedElement = new Content(selector, attrs, children, element.isSelfClosing, element.sourceSpan, element.startSourceSpan, element.endSourceSpan, element.i18n);
this.ngContentSelectors.push(selector);
} else if (isTemplateElement) {
const attrs = this.categorizePropertyAttributes(element.name, parsedProperties, i18nAttrsMeta);
parsedElement = new Template(element.name, attributes, attrs.bound, boundEvents, directives, [], children, references, variables, element.isSelfClosing, element.sourceSpan, element.startSourceSpan, element.endSourceSpan, element.i18n);
} else {
const attrs = this.categorizePropertyAttributes(element.name, parsedProperties, i18nAttrsMeta);
if (element.name === 'ng-container') {
for (const bound of attrs.bound) {
if (bound.type === BindingType.Attribute) {
this.reportError(`Attribute bindings are not supported on ng-container. Use property bindings instead.`, bound.sourceSpan);
}
}
}
parsedElement = new Element$1(element.name, attributes, attrs.bound, boundEvents, directives, children, references, element.isSelfClosing, element.sourceSpan, element.startSourceSpan, element.endSourceSpan, element.isVoid, element.i18n);
}
if (elementHasInlineTemplate) {
parsedElement = this.wrapInTemplate(parsedElement, templateParsedProperties, templateVariables, i18nAttrsMeta, isTemplateElement, isI18nRootElement);
}
if (isI18nRootElement) {
this.inI18nBlock = false;
}
return parsedElement;
}
visitAttribute(attribute) {
return new TextAttribute(attribute.name, attribute.value, attribute.sourceSpan, attribute.keySpan, attribute.valueSpan, attribute.i18n);
}
visitText(text) {
return this.processedNodes.has(text) ? null : this._visitTextWithInterpolation(text.value, text.sourceSpan, text.tokens, text.i18n);
}
visitExpansion(expansion) {
if (!expansion.i18n) {
return null;
}
if (!isI18nRootNode(expansion.i18n)) {
throw new Error(`Invalid type "${expansion.i18n.constructor}" for "i18n" property of ${expansion.sourceSpan.toString()}. Expected a "Message"`);
}
const message = expansion.i18n;
const vars = {};
const placeholders = {};
Object.keys(message.placeholders).forEach(key => {
const value = message.placeholders[key];
if (key.startsWith(I18N_ICU_VAR_PREFIX)) {
const formattedKey = key.trim();
const ast = this.bindingParser.parseInterpolationExpression(value.text, value.sourceSpan);
vars[formattedKey] = new BoundText(ast, value.sourceSpan);
} else {
placeholders[key] = this._visitTextWithInterpolation(value.text, value.sourceSpan, null);
}
});
return new Icu$1(vars, placeholders, expansion.sourceSpan, message);
}
visitExpansionCase(expansionCase) {
return null;
}
visitComment(comment) {
if (this.options.collectCommentNodes) {
this.commentNodes.push(new Comment$1(comment.value || '', comment.sourceSpan));
}
return null;
}
visitLetDeclaration(decl, context) {
const value = this.bindingParser.parseBinding(decl.value, false, decl.valueSpan, decl.valueSpan.start.offset);
if (value.errors.length === 0 && value.ast instanceof EmptyExpr$1) {
this.reportError('@let declaration value cannot be empty', decl.valueSpan);
}
return new LetDeclaration$1(decl.name, value, decl.sourceSpan, decl.nameSpan, decl.valueSpan);
}
visitComponent(component) {
const isI18nRootElement = isI18nRootNode(component.i18n);
if (isI18nRootElement) {
if (this.inI18nBlock) {
this.reportError('Cannot mark a component as translatable inside of a translatable section. Please remove the nested i18n marker.', component.sourceSpan);
}
this.inI18nBlock = true;
}
if (component.tagName !== null && UNSUPPORTED_SELECTORLESS_TAGS.has(component.tagName)) {
this.reportError(`Tag name "${component.tagName}" cannot be used as a component tag`, component.startSourceSpan);
return null;
}
const {
attributes,
boundEvents,
references,
templateVariables,
elementHasInlineTemplate,
parsedProperties,
templateParsedProperties,
i18nAttrsMeta
} = this.prepareAttributes(component.attrs, false);
this.validateSelectorlessReferences(references);
const directives = this.extractDirectives(component);
let children;
if (component.attrs.find(attr => attr.name === 'ngNonBindable')) {
children = visitAll(NON_BINDABLE_VISITOR, component.children).flat(Infinity);
} else {
children = visitAll(this, component.children, component.children);
}
const attrs = this.categorizePropertyAttributes(component.tagName, parsedProperties, i18nAttrsMeta);
let node = new Component$1(component.componentName, component.tagName, component.fullName, attributes, attrs.bound, boundEvents, directives, children, references, component.isSelfClosing, component.sourceSpan, component.startSourceSpan, component.endSourceSpan, component.i18n);
if (elementHasInlineTemplate) {
node = this.wrapInTemplate(node, templateParsedProperties, templateVariables, i18nAttrsMeta, false, isI18nRootElement);
}
if (isI18nRootElement) {
this.inI18nBlock = false;
}
return node;
}
visitDirective() {
return null;
}
visitBlockParameter() {
return null;
}
visitBlock(block, context) {
const index = Array.isArray(context) ? context.indexOf(block) : -1;
if (index === -1) {
throw new Error('Visitor invoked incorrectly. Expecting visitBlock to be invoked siblings array as its context');
}
if (this.processedNodes.has(block)) {
return null;
}
let result = null;
switch (block.name) {
case 'defer':
result = createDeferredBlock(block, this.findConnectedBlocks(index, context, isConnectedDeferLoopBlock), this, this.bindingParser);
break;
case 'switch':
result = createSwitchBlock(block, this, this.bindingParser);
break;
case 'for':
result = createForLoop(block, this.findConnectedBlocks(index, context, isConnectedForLoopBlock), this, this.bindingParser);
break;
case 'if':
result = createIfBlock(block, this.findConnectedBlocks(index, context, isConnectedIfLoopBlock), this, this.bindingParser);
break;
default:
let errorMessage;
if (isConnectedDeferLoopBlock(block.name)) {
errorMessage = `@${block.name} block can only be used after an @defer block.`;
this.processedNodes.add(block);
} else if (isConnectedForLoopBlock(block.name)) {
errorMessage = `@${block.name} block can only be used after an @for block.`;
this.processedNodes.add(block);
} else if (isConnectedIfLoopBlock(block.name)) {
errorMessage = `@${block.name} block can only be used after an @if or @else if block.`;
this.processedNodes.add(block);
} else {
errorMessage = `Unrecognized block @${block.name}.`;
}
result = {
node: new UnknownBlock(block.name, block.sourceSpan, block.nameSpan),
errors: [new ParseError(block.sourceSpan, errorMessage)]
};
break;
}
this.errors.push(...result.errors);
return result.node;
}
findConnectedBlocks(primaryBlockIndex, siblings, predicate) {
const relatedBlocks = [];
for (let i = primaryBlockIndex + 1; i < siblings.length; i++) {
const node = siblings[i];
if (node instanceof Comment) {
continue;
}
if (node instanceof Text && node.value.trim().length === 0) {
this.processedNodes.add(node);
continue;
}
if (!(node instanceof Block) || !predicate(node.name)) {
break;
}
relatedBlocks.push(node);
this.processedNodes.add(node);
}
return relatedBlocks;
}
categorizePropertyAttributes(elementName, properties, i18nPropsMeta) {
const bound = [];
const literal = [];
properties.forEach(prop => {
const i18n = i18nPropsMeta[prop.name];
if (prop.isLiteral) {
literal.push(new TextAttribute(prop.name, prop.expression.source || '', prop.sourceSpan, prop.keySpan, prop.valueSpan, i18n));
} else {
const bep = this.bindingParser.createBoundElementProperty(elementName, prop, true, false);
bound.push(BoundAttribute.fromBoundElementProperty(bep, i18n));
}
});
return {
bound,
literal
};
}
prepareAttributes(attrs, isTemplateElement) {
const parsedProperties = [];
const boundEvents = [];
const variables = [];
const references = [];
const attributes = [];
const i18nAttrsMeta = {};
const templateParsedProperties = [];
const templateVariables = [];
let elementHasInlineTemplate = false;
for (const attribute of attrs) {
let hasBinding = false;
const normalizedName = normalizeAttributeName(attribute.name);
let isTemplateBinding = false;
if (attribute.i18n) {
i18nAttrsMeta[attribute.name] = attribute.i18n;
}
if (normalizedName.startsWith(TEMPLATE_ATTR_PREFIX)) {
if (elementHasInlineTemplate) {
this.reportError(`Can't have multiple template bindings on one element. Use only one attribute prefixed with *`, attribute.sourceSpan);
}
isTemplateBinding = true;
elementHasInlineTemplate = true;
const templateValue = attribute.value;
const templateKey = normalizedName.substring(TEMPLATE_ATTR_PREFIX.length);
const parsedVariables = [];
const absoluteValueOffset = attribute.valueSpan ? attribute.valueSpan.fullStart.offset : attribute.sourceSpan.fullStart.offset + attribute.name.length;
this.bindingParser.parseInlineTemplateBinding(templateKey, templateValue, attribute.sourceSpan, absoluteValueOffset, [], templateParsedProperties, parsedVariables, true);
templateVariables.push(...parsedVariables.map(v => new Variable(v.name, v.value, v.sourceSpan, v.keySpan, v.valueSpan)));
} else {
hasBinding = this.parseAttribute(isTemplateElement, attribute, [], parsedProperties, boundEvents, variables, references);
}
if (!hasBinding && !isTemplateBinding) {
attributes.push(this.visitAttribute(attribute));
}
}
return {
attributes,
boundEvents,
references,
variables,
templateVariables,
elementHasInlineTemplate,
parsedProperties,
templateParsedProperties,
i18nAttrsMeta
};
}
parseAttribute(isTemplateElement, attribute, matchableAttributes, parsedProperties, boundEvents, variables, references) {
const name = normalizeAttributeName(attribute.name);
const value = attribute.value;
const srcSpan = attribute.sourceSpan;
const absoluteOffset = attribute.valueSpan ? attribute.valueSpan.fullStart.offset : srcSpan.fullStart.offset;
function createKeySpan(srcSpan, prefix, identifier) {
const normalizationAdjustment = attribute.name.length - name.length;
const keySpanStart = srcSpan.start.moveBy(prefix.length + normalizationAdjustment);
const keySpanEnd = keySpanStart.moveBy(identifier.length);
return new ParseSourceSpan(keySpanStart, keySpanEnd, keySpanStart, identifier);
}
const bindParts = name.match(BIND_NAME_REGEXP);
if (bindParts) {
if (bindParts[KW_BIND_IDX] != null) {
const identifier = bindParts[IDENT_KW_IDX];
const keySpan = createKeySpan(srcSpan, bindParts[KW_BIND_IDX], identifier);
this.bindingParser.parsePropertyBinding(identifier, value, false, false, srcSpan, absoluteOffset, attribute.valueSpan, matchableAttributes, parsedProperties, keySpan);
} else if (bindParts[KW_LET_IDX]) {
if (isTemplateElement) {
const identifier = bindParts[IDENT_KW_IDX];
const keySpan = createKeySpan(srcSpan, bindParts[KW_LET_IDX], identifier);
this.parseVariable(identifier, value, srcSpan, keySpan, attribute.valueSpan, variables);
} else {
this.reportError(`"let-" is only supported on ng-template elements.`, srcSpan);
}
} else if (bindParts[KW_REF_IDX]) {
const identifier = bindParts[IDENT_KW_IDX];
const keySpan = createKeySpan(srcSpan, bindParts[KW_REF_IDX], identifier);
this.parseReference(identifier, value, srcSpan, keySpan, attribute.valueSpan, references);
} else if (bindParts[KW_ON_IDX]) {
const events = [];
const identifier = bindParts[IDENT_KW_IDX];
const keySpan = createKeySpan(srcSpan, bindParts[KW_ON_IDX], identifier);
this.bindingParser.parseEvent(identifier, value, false, srcSpan, attribute.valueSpan || srcSpan, matchableAttributes, events, keySpan);
addEvents(events, boundEvents);
} else if (bindParts[KW_BINDON_IDX]) {
const identifier = bindParts[IDENT_KW_IDX];
const keySpan = createKeySpan(srcSpan, bindParts[KW_BINDON_IDX], identifier);
this.bindingParser.parsePropertyBinding(identifier, value, false, true, srcSpan, absoluteOffset, attribute.valueSpan, matchableAttributes, parsedProperties, keySpan);
this.parseAssignmentEvent(identifier, value, srcSpan, attribute.valueSpan, matchableAttributes, boundEvents, keySpan, absoluteOffset);
} else if (bindParts[KW_AT_IDX]) {
const keySpan = createKeySpan(srcSpan, '', name);
this.bindingParser.parseLiteralAttr(name, value, srcSpan, absoluteOffset, attribute.valueSpan, matchableAttributes, parsedProperties, keySpan);
}
return true;
}
let delims = null;
if (name.startsWith(BINDING_DELIMS.BANANA_BOX.start)) {
delims = BINDING_DELIMS.BANANA_BOX;
} else if (name.startsWith(BINDING_DELIMS.PROPERTY.start)) {
delims = BINDING_DELIMS.PROPERTY;
} else if (name.startsWith(BINDING_DELIMS.EVENT.start)) {
delims = BINDING_DELIMS.EVENT;
}
if (delims !== null && name.endsWith(delims.end) && name.length > delims.start.length + delims.end.length) {
const identifier = name.substring(delims.start.length, name.length - delims.end.length);
const keySpan = createKeySpan(srcSpan, delims.start, identifier);
if (delims.start === BINDING_DELIMS.BANANA_BOX.start) {
this.bindingParser.parsePropertyBinding(identifier, value, false, true, srcSpan, absoluteOffset, attribute.valueSpan, matchableAttributes, parsedProperties, keySpan);
this.parseAssignmentEvent(identifier, value, srcSpan, attribute.valueSpan, matchableAttributes, boundEvents, keySpan, absoluteOffset);
} else if (delims.start === BINDING_DELIMS.PROPERTY.start) {
this.bindingParser.parsePropertyBinding(identifier, value, false, false, srcSpan, absoluteOffset, attribute.valueSpan, matchableAttributes, parsedProperties, keySpan);
} else {
const events = [];
this.bindingParser.parseEvent(identifier, value, false, srcSpan, attribute.valueSpan || srcSpan, matchableAttributes, events, keySpan);
addEvents(events, boundEvents);
}
return true;
}
const keySpan = createKeySpan(srcSpan, '', name);
const hasBinding = this.bindingParser.parsePropertyInterpolation(name, value, srcSpan, attribute.valueSpan, matchableAttributes, parsedProperties, keySpan, attribute.valueTokens ?? null);
return hasBinding;
}
extractDirectives(node) {
const elementName = node instanceof Component ? node.tagName : node.name;
const directives = [];
const seenDirectives = new Set();
for (const directive of node.directives) {
let invalid = false;
for (const attr of directive.attrs) {
if (attr.name.startsWith(TEMPLATE_ATTR_PREFIX)) {
invalid = true;
this.reportError(`Shorthand template syntax "${attr.name}" is not supported inside a directive context`, attr.sourceSpan);
} else if (UNSUPPORTED_SELECTORLESS_DIRECTIVE_ATTRS.has(attr.name)) {
invalid = true;
this.reportError(`Attribute "${attr.name}" is not supported in a directive context`, attr.sourceSpan);
}
}
if (!invalid && seenDirectives.has(directive.name)) {
invalid = true;
this.reportError(`Cannot apply directive "${directive.name}" multiple times on the same element`, directive.sourceSpan);
}
if (invalid) {
continue;
}
const {
attributes,
parsedProperties,
boundEvents,
references,
i18nAttrsMeta
} = this.prepareAttributes(directive.attrs, false);
this.validateSelectorlessReferences(references);
const {
bound: inputs
} = this.categorizePropertyAttributes(elementName, parsedProperties, i18nAttrsMeta);
for (const input of inputs) {
if (input.type !== BindingType.Property && input.type !== BindingType.TwoWay) {
invalid = true;
this.reportError('Binding is not supported in a directive context', input.sourceSpan);
}
}
if (invalid) {
continue;
}
seenDirectives.add(directive.name);
directives.push(new Directive$1(directive.name, attributes, inputs, boundEvents, references, directive.sourceSpan, directive.startSourceSpan, directive.endSourceSpan, undefined));
}
return directives;
}
filterAnimationAttributes(attributes) {
return attributes.filter(a => !a.name.startsWith('animate.'));
}
filterAnimationInputs(attributes) {
return attributes.filter(a => a.type !== BindingType.Animation);
}
wrapInTemplate(node, templateProperties, templateVariables, i18nAttrsMeta, isTemplateElement, isI18nRootElement) {
const attrs = this.categorizePropertyAttributes('ng-template', templateProperties, i18nAttrsMeta);
const templateAttrs = [];
attrs.literal.forEach(attr => templateAttrs.push(attr));
attrs.bound.forEach(attr => templateAttrs.push(attr));
const hoistedAttrs = {
attributes: [],
inputs: [],
outputs: []
};
if (node instanceof Element$1 || node instanceof Component$1) {
hoistedAttrs.attributes.push(...this.filterAnimationAttributes(node.attributes));
hoistedAttrs.inputs.push(...this.filterAnimationInputs(node.inputs));
hoistedAttrs.outputs.push(...node.outputs);
}
const i18n = isTemplateElement && isI18nRootElement ? undefined : node.i18n;
let name;
if (node instanceof Component$1) {
name = node.tagName;
} else if (node instanceof Template) {
name = null;
} else {
name = node.name;
}
return new Template(name, hoistedAttrs.attributes, hoistedAttrs.inputs, hoistedAttrs.outputs, [], templateAttrs, [node], [], templateVariables, false, node.sourceSpan, node.startSourceSpan, node.endSourceSpan, i18n);
}
_visitTextWithInterpolation(value, sourceSpan, interpolatedTokens, i18n) {
const valueNoNgsp = replaceNgsp(value);
const expr = this.bindingParser.parseInterpolation(valueNoNgsp, sourceSpan, interpolatedTokens);
return expr ? new BoundText(expr, sourceSpan, i18n) : new Text$3(valueNoNgsp, sourceSpan);
}
parseVariable(identifier, value, sourceSpan, keySpan, valueSpan, variables) {
if (identifier.indexOf('-') > -1) {
this.reportError(`"-" is not allowed in variable names`, sourceSpan);
} else if (identifier.length === 0) {
this.reportError(`Variable does not have a name`, sourceSpan);
}
variables.push(new Variable(identifier, value, sourceSpan, keySpan, valueSpan));
}
parseReference(identifier, value, sourceSpan, keySpan, valueSpan, references) {
if (identifier.indexOf('-') > -1) {
this.reportError(`"-" is not allowed in reference names`, sourceSpan);
} else if (identifier.length === 0) {
this.reportError(`Reference does not have a name`, sourceSpan);
} else if (references.some(reference => reference.name === identifier)) {
this.reportError(`Reference "#${identifier}" is defined more than once`, sourceSpan);
}
references.push(new Reference(identifier, value, sourceSpan, keySpan, valueSpan));
}
parseAssignmentEvent(name, expression, sourceSpan, valueSpan, targetMatchableAttrs, boundEvents, keySpan, absoluteOffset) {
const events = [];
this.bindingParser.parseEvent(`${name}Change`, expression, true, sourceSpan, valueSpan || sourceSpan, targetMatchableAttrs, events, keySpan);
addEvents(events, boundEvents);
}
validateSelectorlessReferences(references) {
if (references.length === 0) {
return;
}
const seenNames = new Set();
for (const ref of references) {
if (ref.value.length > 0) {
this.reportError('Cannot specify a value for a local reference in this context', ref.valueSpan || ref.sourceSpan);
} else if (seenNames.has(ref.name)) {
this.reportError('Duplicate reference names are not allowed', ref.sourceSpan);
} else {
seenNames.add(ref.name);
}
}
}
reportError(message, sourceSpan, level = ParseErrorLevel.ERROR) {
this.errors.push(new ParseError(sourceSpan, message, level));
}
}
class NonBindableVisitor {
visitElement(ast) {
const preparsedElement = preparseElement(ast);
if (preparsedElement.type === PreparsedElementType.SCRIPT || preparsedElement.type === PreparsedElementType.STYLE || preparsedElement.type === PreparsedElementType.STYLESHEET) {
return null;
}
const children = visitAll(this, ast.children, null);
return new Element$1(ast.name, visitAll(this, ast.attrs), [], [], [], children, [], ast.isSelfClosing, ast.sourceSpan, ast.startSourceSpan, ast.endSourceSpan, ast.isVoid);
}
visitComment(comment) {
return null;
}
visitAttribute(attribute) {
return new TextAttribute(attribute.name, attribute.value, attribute.sourceSpan, attribute.keySpan, attribute.valueSpan, attribute.i18n);
}
visitText(text) {
return new Text$3(text.value, text.sourceSpan);
}
visitExpansion(expansion) {
return null;
}
visitExpansionCase(expansionCase) {
return null;
}
visitBlock(block, context) {
const nodes = [new Text$3(block.startSourceSpan.toString(), block.startSourceSpan), ...visitAll(this, block.children)];
if (block.endSourceSpan !== null) {
nodes.push(new Text$3(block.endSourceSpan.toString(), block.endSourceSpan));
}
return nodes;
}
visitBlockParameter(parameter, context) {
return null;
}
visitLetDeclaration(decl, context) {
return new Text$3(`@let ${decl.name} = ${decl.value};`, decl.sourceSpan);
}
visitComponent(ast, context) {
const children = visitAll(this, ast.children, null);
return new Element$1(ast.fullName, visitAll(this, ast.attrs), [], [], [], children, [], ast.isSelfClosing, ast.sourceSpan, ast.startSourceSpan, ast.endSourceSpan, false);
}
visitDirective(directive, context) {
return null;
}
}
const NON_BINDABLE_VISITOR = new NonBindableVisitor();
function normalizeAttributeName(attrName) {
return /^data-/i.test(attrName) ? attrName.substring(5) : attrName;
}
function addEvents(events, boundEvents) {
boundEvents.push(...events.map(e => BoundEvent.fromParsedEvent(e)));
}
function textContents(node) {
if (node.children.length !== 1 || !(node.children[0] instanceof Text)) {
return null;
} else {
return node.children[0].value;
}
}
const LEADING_TRIVIA_CHARS = [' ', '\n', '\r', '\t'];
function parseTemplate(template, templateUrl, options = {}) {
const {
preserveWhitespaces,
enableI18nLegacyMessageIdFormat
} = options;
const selectorlessEnabled = options.enableSelectorless ?? false;
const bindingParser = makeBindingParser(selectorlessEnabled);
const htmlParser = new HtmlParser();
const parseResult = htmlParser.parse(template, templateUrl, {
leadingTriviaChars: LEADING_TRIVIA_CHARS,
...options,
tokenizeExpansionForms: true,
tokenizeBlocks: options.enableBlockSyntax ?? true,
tokenizeLet: options.enableLetSyntax ?? true,
selectorlessEnabled
});
if (!options.alwaysAttemptHtmlToR3AstConversion && parseResult.errors && parseResult.errors.length > 0) {
const parsedTemplate = {
preserveWhitespaces,
errors: parseResult.errors,
nodes: [],
styleUrls: [],
styles: [],
ngContentSelectors: []
};
if (options.collectCommentNodes) {
parsedTemplate.commentNodes = [];
}
return parsedTemplate;
}
let rootNodes = parseResult.rootNodes;
const retainEmptyTokens = !(options.preserveSignificantWhitespace ?? true);
const i18nMetaVisitor = new I18nMetaVisitor(!preserveWhitespaces, enableI18nLegacyMessageIdFormat, options.preserveSignificantWhitespace, retainEmptyTokens);
const i18nMetaResult = i18nMetaVisitor.visitAllWithErrors(rootNodes);
if (!options.alwaysAttemptHtmlToR3AstConversion && i18nMetaResult.errors && i18nMetaResult.errors.length > 0) {
const parsedTemplate = {
preserveWhitespaces,
errors: i18nMetaResult.errors,
nodes: [],
styleUrls: [],
styles: [],
ngContentSelectors: []
};
if (options.collectCommentNodes) {
parsedTemplate.commentNodes = [];
}
return parsedTemplate;
}
rootNodes = i18nMetaResult.rootNodes;
if (!preserveWhitespaces) {
rootNodes = visitAll(new WhitespaceVisitor(true, undefined, false), rootNodes);
if (i18nMetaVisitor.hasI18nMeta) {
rootNodes = visitAll(new I18nMetaVisitor(false, undefined, true, retainEmptyTokens), rootNodes);
}
}
const {
nodes,
errors,
styleUrls,
styles,
ngContentSelectors,
commentNodes
} = htmlAstToRender3Ast(rootNodes, bindingParser, {
collectCommentNodes: !!options.collectCommentNodes
});
errors.push(...parseResult.errors, ...i18nMetaResult.errors);
const parsedTemplate = {
preserveWhitespaces,
errors: errors.length > 0 ? errors : null,
nodes,
styleUrls,
styles,
ngContentSelectors
};
if (options.collectCommentNodes) {
parsedTemplate.commentNodes = commentNodes;
}
return parsedTemplate;
}
const elementRegistry = new DomElementSchemaRegistry();
function makeBindingParser(selectorlessEnabled = false) {
return new BindingParser(new Parser(new Lexer(), selectorlessEnabled), elementRegistry, []);
}
const COMPONENT_VARIABLE = '%COMP%';
const HOST_ATTR = `_nghost-${COMPONENT_VARIABLE}`;
const CONTENT_ATTR = `_ngcontent-${COMPONENT_VARIABLE}`;
function baseDirectiveFields(meta, constantPool, bindingParser) {
const definitionMap = new DefinitionMap();
const selectors = parseSelectorToR3Selector(meta.selector);
definitionMap.set('type', meta.type.value);
if (selectors.length > 0) {
definitionMap.set('selectors', asLiteral(selectors));
}
if (meta.queries.length > 0) {
definitionMap.set('contentQueries', createContentQueriesFunction(meta.queries, constantPool, meta.name));
}
if (meta.viewQueries.length) {
definitionMap.set('viewQuery', createViewQueriesFunction(meta.viewQueries, constantPool, meta.name));
}
definitionMap.set('hostBindings', createHostBindingsFunction(meta.host, meta.typeSourceSpan, bindingParser, constantPool, meta.selector || '', meta.name, definitionMap));
definitionMap.set('inputs', conditionallyCreateDirectiveBindingLiteral(meta.inputs, true));
definitionMap.set('outputs', conditionallyCreateDirectiveBindingLiteral(meta.outputs));
if (meta.exportAs !== null) {
definitionMap.set('exportAs', literalArr(meta.exportAs.map(e => literal(e))));
}
if (meta.isStandalone === false) {
definitionMap.set('standalone', literal(false));
}
if (meta.isSignal) {
definitionMap.set('signals', literal(true));
}
return definitionMap;
}
function addFeatures(definitionMap, meta) {
const features = [];
const providers = meta.providers;
const viewProviders = meta.viewProviders;
if (providers || viewProviders) {
const args = [providers || new LiteralArrayExpr([])];
if (viewProviders) {
args.push(viewProviders);
}
features.push(importExpr(Identifiers.ProvidersFeature).callFn(args));
}
if (meta.hostDirectives?.length) {
features.push(importExpr(Identifiers.HostDirectivesFeature).callFn([createHostDirectivesFeatureArg(meta.hostDirectives)]));
}
if (meta.usesInheritance) {
features.push(importExpr(Identifiers.InheritDefinitionFeature));
}
if (meta.lifecycle.usesOnChanges) {
features.push(importExpr(Identifiers.NgOnChangesFeature));
}
if ('externalStyles' in meta && meta.externalStyles?.length) {
const externalStyleNodes = meta.externalStyles.map(externalStyle => literal(externalStyle));
features.push(importExpr(Identifiers.ExternalStylesFeature).callFn([literalArr(externalStyleNodes)]));
}
if (features.length) {
definitionMap.set('features', literalArr(features));
}
}
function compileDirectiveFromMetadata(meta, constantPool, bindingParser) {
const definitionMap = baseDirectiveFields(meta, constantPool, bindingParser);
addFeatures(definitionMap, meta);
const expression = importExpr(Identifiers.defineDirective).callFn([definitionMap.toLiteralMap()], undefined, true);
const type = createDirectiveType(meta);
return {
expression,
type,
statements: []
};
}
function compileComponentFromMetadata(meta, constantPool, bindingParser) {
const definitionMap = baseDirectiveFields(meta, constantPool, bindingParser);
addFeatures(definitionMap, meta);
const selector = meta.selector && CssSelector.parse(meta.selector);
const firstSelector = selector && selector[0];
if (firstSelector) {
const selectorAttributes = firstSelector.getAttrs();
if (selectorAttributes.length) {
definitionMap.set('attrs', constantPool.getConstLiteral(literalArr(selectorAttributes.map(value => value != null ? literal(value) : literal(undefined))), true));
}
}
const templateTypeName = meta.name;
let allDeferrableDepsFn = null;
if (meta.defer.mode === 1 && meta.defer.dependenciesFn !== null) {
const fnName = `${templateTypeName}_DeferFn`;
constantPool.statements.push(new DeclareVarStmt(fnName, meta.defer.dependenciesFn, undefined, StmtModifier.Final));
allDeferrableDepsFn = variable(fnName);
}
const compilationMode = meta.isStandalone && !meta.hasDirectiveDependencies ? TemplateCompilationMode.DomOnly : TemplateCompilationMode.Full;
const tpl = ingestComponent(meta.name, meta.template.nodes, constantPool, compilationMode, meta.relativeContextFilePath, meta.i18nUseExternalIds, meta.defer, allDeferrableDepsFn, meta.relativeTemplatePath, getTemplateSourceLocationsEnabled());
transform(tpl, CompilationJobKind.Tmpl);
const templateFn = emitTemplateFn(tpl, constantPool);
if (tpl.contentSelectors !== null) {
definitionMap.set('ngContentSelectors', tpl.contentSelectors);
}
definitionMap.set('decls', literal(tpl.root.decls));
definitionMap.set('vars', literal(tpl.root.vars));
if (tpl.consts.length > 0) {
if (tpl.constsInitializers.length > 0) {
definitionMap.set('consts', arrowFn([], [...tpl.constsInitializers, new ReturnStatement(literalArr(tpl.consts))]));
} else {
definitionMap.set('consts', literalArr(tpl.consts));
}
}
definitionMap.set('template', templateFn);
if (meta.declarationListEmitMode !== 3 && meta.declarations.length > 0) {
definitionMap.set('dependencies', compileDeclarationList(literalArr(meta.declarations.map(decl => decl.type)), meta.declarationListEmitMode));
} else if (meta.declarationListEmitMode === 3) {
const args = [meta.type.value];
if (meta.rawImports) {
args.push(meta.rawImports);
}
definitionMap.set('dependencies', importExpr(Identifiers.getComponentDepsFactory).callFn(args));
}
if (meta.encapsulation === null) {
meta.encapsulation = ViewEncapsulation$1.Emulated;
}
let hasStyles = !!meta.externalStyles?.length;
if (meta.styles && meta.styles.length) {
const styleValues = meta.encapsulation == ViewEncapsulation$1.Emulated ? compileStyles(meta.styles, CONTENT_ATTR, HOST_ATTR) : meta.styles;
const styleNodes = styleValues.reduce((result, style) => {
if (style.trim().length > 0) {
result.push(constantPool.getConstLiteral(literal(style)));
}
return result;
}, []);
if (styleNodes.length > 0) {
hasStyles = true;
definitionMap.set('styles', literalArr(styleNodes));
}
}
if (!hasStyles && meta.encapsulation === ViewEncapsulation$1.Emulated) {
meta.encapsulation = ViewEncapsulation$1.None;
}
if (meta.encapsulation !== ViewEncapsulation$1.Emulated) {
definitionMap.set('encapsulation', literal(meta.encapsulation));
}
if (meta.animations !== null) {
definitionMap.set('data', literalMap([{
key: 'animation',
value: meta.animations,
quoted: false
}]));
}
if (meta.changeDetection !== null) {
if (typeof meta.changeDetection === 'number' && meta.changeDetection !== ChangeDetectionStrategy.Default) {
definitionMap.set('changeDetection', literal(meta.changeDetection));
} else if (typeof meta.changeDetection === 'object') {
definitionMap.set('changeDetection', meta.changeDetection);
}
}
const expression = importExpr(Identifiers.defineComponent).callFn([definitionMap.toLiteralMap()], undefined, true);
const type = createComponentType(meta);
return {
expression,
type,
statements: []
};
}
function createComponentType(meta) {
const typeParams = createBaseDirectiveTypeParams(meta);
typeParams.push(stringArrayAsType(meta.template.ngContentSelectors));
typeParams.push(expressionType(literal(meta.isStandalone)));
typeParams.push(createHostDirectivesType(meta));
if (meta.isSignal) {
typeParams.push(expressionType(literal(meta.isSignal)));
}
return expressionType(importExpr(Identifiers.ComponentDeclaration, typeParams));
}
function compileDeclarationList(list, mode) {
switch (mode) {
case 0:
return list;
case 1:
return arrowFn([], list);
case 2:
const resolvedList = list.prop('map').callFn([importExpr(Identifiers.resolveForwardRef)]);
return arrowFn([], resolvedList);
case 3:
throw new Error(`Unsupported with an array of pre-resolved dependencies`);
}
}
function stringAsType(str) {
return expressionType(literal(str));
}
function stringMapAsLiteralExpression(map) {
const mapValues = Object.keys(map).map(key => {
const value = Array.isArray(map[key]) ? map[key][0] : map[key];
return {
key,
value: literal(value),
quoted: true
};
});
return literalMap(mapValues);
}
function stringArrayAsType(arr) {
return arr.length > 0 ? expressionType(literalArr(arr.map(value => literal(value)))) : NONE_TYPE;
}
function createBaseDirectiveTypeParams(meta) {
const selectorForType = meta.selector !== null ? meta.selector.replace(/\n/g, '') : null;
return [typeWithParameters(meta.type.type, meta.typeArgumentCount), selectorForType !== null ? stringAsType(selectorForType) : NONE_TYPE, meta.exportAs !== null ? stringArrayAsType(meta.exportAs) : NONE_TYPE, expressionType(getInputsTypeExpression(meta)), expressionType(stringMapAsLiteralExpression(meta.outputs)), stringArrayAsType(meta.queries.map(q => q.propertyName))];
}
function getInputsTypeExpression(meta) {
return literalMap(Object.keys(meta.inputs).map(key => {
const value = meta.inputs[key];
const values = [{
key: 'alias',
value: literal(value.bindingPropertyName),
quoted: true
}, {
key: 'required',
value: literal(value.required),
quoted: true
}];
if (value.isSignal) {
values.push({
key: 'isSignal',
value: literal(value.isSignal),
quoted: true
});
}
return {
key,
value: literalMap(values),
quoted: true
};
}));
}
function createDirectiveType(meta) {
const typeParams = createBaseDirectiveTypeParams(meta);
typeParams.push(NONE_TYPE);
typeParams.push(expressionType(literal(meta.isStandalone)));
typeParams.push(createHostDirectivesType(meta));
if (meta.isSignal) {
typeParams.push(expressionType(literal(meta.isSignal)));
}
return expressionType(importExpr(Identifiers.DirectiveDeclaration, typeParams));
}
function createHostBindingsFunction(hostBindingsMetadata, typeSourceSpan, bindingParser, constantPool, selector, name, definitionMap) {
const bindings = bindingParser.createBoundHostProperties(hostBindingsMetadata.properties, typeSourceSpan);
const eventBindings = bindingParser.createDirectiveHostEventAsts(hostBindingsMetadata.listeners, typeSourceSpan);
if (hostBindingsMetadata.specialAttributes.styleAttr) {
hostBindingsMetadata.attributes['style'] = literal(hostBindingsMetadata.specialAttributes.styleAttr);
}
if (hostBindingsMetadata.specialAttributes.classAttr) {
hostBindingsMetadata.attributes['class'] = literal(hostBindingsMetadata.specialAttributes.classAttr);
}
const hostJob = ingestHostBinding({
componentName: name,
componentSelector: selector,
properties: bindings,
events: eventBindings,
attributes: hostBindingsMetadata.attributes
}, bindingParser, constantPool);
transform(hostJob, CompilationJobKind.Host);
definitionMap.set('hostAttrs', hostJob.root.attributes);
const varCount = hostJob.root.vars;
if (varCount !== null && varCount > 0) {
definitionMap.set('hostVars', literal(varCount));
}
return emitHostBindingFunction(hostJob);
}
const HOST_REG_EXP = /^(?:\[([^\]]+)\])|(?:\(([^\)]+)\))$/;
function parseHostBindings(host) {
const attributes = {};
const listeners = {};
const properties = {};
const specialAttributes = {};
for (const key of Object.keys(host)) {
const value = host[key];
const matches = key.match(HOST_REG_EXP);
if (matches === null) {
switch (key) {
case 'class':
if (typeof value !== 'string') {
throw new Error(`Class binding must be string`);
}
specialAttributes.classAttr = value;
break;
case 'style':
if (typeof value !== 'string') {
throw new Error(`Style binding must be string`);
}
specialAttributes.styleAttr = value;
break;
default:
if (typeof value === 'string') {
attributes[key] = literal(value);
} else {
attributes[key] = value;
}
}
} else if (matches[1] != null) {
if (typeof value !== 'string') {
throw new Error(`Property binding must be string`);
}
properties[matches[1]] = value;
} else if (matches[2] != null) {
if (typeof value !== 'string') {
throw new Error(`Event binding must be string`);
}
listeners[matches[2]] = value;
}
}
return {
attributes,
listeners,
properties,
specialAttributes
};
}
function verifyHostBindings(bindings, sourceSpan) {
const bindingParser = makeBindingParser();
bindingParser.createDirectiveHostEventAsts(bindings.listeners, sourceSpan);
bindingParser.createBoundHostProperties(bindings.properties, sourceSpan);
return bindingParser.errors;
}
function compileStyles(styles, selector, hostSelector) {
const shadowCss = new ShadowCss();
return styles.map(style => {
return shadowCss.shimCssText(style, selector, hostSelector);
});
}
function encapsulateStyle(style, componentIdentifier) {
const shadowCss = new ShadowCss();
const selector = componentIdentifier ? CONTENT_ATTR.replace(COMPONENT_VARIABLE, componentIdentifier) : CONTENT_ATTR;
const hostSelector = componentIdentifier ? HOST_ATTR.replace(COMPONENT_VARIABLE, componentIdentifier) : HOST_ATTR;
return shadowCss.shimCssText(style, selector, hostSelector);
}
function createHostDirectivesType(meta) {
if (!meta.hostDirectives?.length) {
return NONE_TYPE;
}
return expressionType(literalArr(meta.hostDirectives.map(hostMeta => literalMap([{
key: 'directive',
value: typeofExpr(hostMeta.directive.type),
quoted: false
}, {
key: 'inputs',
value: stringMapAsLiteralExpression(hostMeta.inputs || {}),
quoted: false
}, {
key: 'outputs',
value: stringMapAsLiteralExpression(hostMeta.outputs || {}),
quoted: false
}]))));
}
function createHostDirectivesFeatureArg(hostDirectives) {
const expressions = [];
let hasForwardRef = false;
for (const current of hostDirectives) {
if (!current.inputs && !current.outputs) {
expressions.push(current.directive.type);
} else {
const keys = [{
key: 'directive',
value: current.directive.type,
quoted: false
}];
if (current.inputs) {
const inputsLiteral = createHostDirectivesMappingArray(current.inputs);
if (inputsLiteral) {
keys.push({
key: 'inputs',
value: inputsLiteral,
quoted: false
});
}
}
if (current.outputs) {
const outputsLiteral = createHostDirectivesMappingArray(current.outputs);
if (outputsLiteral) {
keys.push({
key: 'outputs',
value: outputsLiteral,
quoted: false
});
}
}
expressions.push(literalMap(keys));
}
if (current.isForwardReference) {
hasForwardRef = true;
}
}
return hasForwardRef ? new FunctionExpr([], [new ReturnStatement(literalArr(expressions))]) : literalArr(expressions);
}
function createHostDirectivesMappingArray(mapping) {
const elements = [];
for (const publicName in mapping) {
if (mapping.hasOwnProperty(publicName)) {
elements.push(literal(publicName), literal(mapping[publicName]));
}
}
return elements.length > 0 ? literalArr(elements) : null;
}
function compileDeferResolverFunction(meta) {
const depExpressions = [];
if (meta.mode === 0) {
for (const dep of meta.dependencies) {
if (dep.isDeferrable) {
const innerFn = arrowFn([new FnParam('m', DYNAMIC_TYPE)], variable('m').prop(dep.isDefaultImport ? 'default' : dep.symbolName));
const importExpr = new DynamicImportExpr(dep.importPath).prop('then').callFn([innerFn]);
depExpressions.push(importExpr);
} else {
depExpressions.push(dep.typeReference);
}
}
} else {
for (const {
symbolName,
importPath,
isDefaultImport
} of meta.dependencies) {
const innerFn = arrowFn([new FnParam('m', DYNAMIC_TYPE)], variable('m').prop(isDefaultImport ? 'default' : symbolName));
const importExpr = new DynamicImportExpr(importPath).prop('then').callFn([innerFn]);
depExpressions.push(importExpr);
}
}
return arrowFn([], literalArr(depExpressions));
}
class CombinedRecursiveAstVisitor extends RecursiveAstVisitor {
visit(node) {
if (node instanceof ASTWithSource) {
this.visit(node.ast);
} else {
node.visit(this);
}
}
visitElement(element) {
this.visitAllTemplateNodes(element.attributes);
this.visitAllTemplateNodes(element.inputs);
this.visitAllTemplateNodes(element.outputs);
this.visitAllTemplateNodes(element.directives);
this.visitAllTemplateNodes(element.references);
this.visitAllTemplateNodes(element.children);
}
visitTemplate(template) {
this.visitAllTemplateNodes(template.attributes);
this.visitAllTemplateNodes(template.inputs);
this.visitAllTemplateNodes(template.outputs);
this.visitAllTemplateNodes(template.directives);
this.visitAllTemplateNodes(template.templateAttrs);
this.visitAllTemplateNodes(template.variables);
this.visitAllTemplateNodes(template.references);
this.visitAllTemplateNodes(template.children);
}
visitContent(content) {
this.visitAllTemplateNodes(content.children);
}
visitBoundAttribute(attribute) {
this.visit(attribute.value);
}
visitBoundEvent(attribute) {
this.visit(attribute.handler);
}
visitBoundText(text) {
this.visit(text.value);
}
visitIcu(icu) {
Object.keys(icu.vars).forEach(key => this.visit(icu.vars[key]));
Object.keys(icu.placeholders).forEach(key => this.visit(icu.placeholders[key]));
}
visitDeferredBlock(deferred) {
deferred.visitAll(this);
}
visitDeferredTrigger(trigger) {
if (trigger instanceof BoundDeferredTrigger) {
this.visit(trigger.value);
} else if (trigger instanceof ViewportDeferredTrigger && trigger.options !== null) {
this.visit(trigger.options);
}
}
visitDeferredBlockPlaceholder(block) {
this.visitAllTemplateNodes(block.children);
}
visitDeferredBlockError(block) {
this.visitAllTemplateNodes(block.children);
}
visitDeferredBlockLoading(block) {
this.visitAllTemplateNodes(block.children);
}
visitSwitchBlock(block) {
this.visit(block.expression);
this.visitAllTemplateNodes(block.groups);
}
visitSwitchBlockCase(block) {
block.expression && this.visit(block.expression);
}
visitSwitchBlockCaseGroup(block) {
this.visitAllTemplateNodes(block.cases);
this.visitAllTemplateNodes(block.children);
}
visitForLoopBlock(block) {
block.item.visit(this);
this.visitAllTemplateNodes(block.contextVariables);
this.visit(block.expression);
this.visitAllTemplateNodes(block.children);
block.empty?.visit(this);
}
visitForLoopBlockEmpty(block) {
this.visitAllTemplateNodes(block.children);
}
visitIfBlock(block) {
this.visitAllTemplateNodes(block.branches);
}
visitIfBlockBranch(block) {
block.expression && this.visit(block.expression);
block.expressionAlias?.visit(this);
this.visitAllTemplateNodes(block.children);
}
visitLetDeclaration(decl) {
this.visit(decl.value);
}
visitComponent(component) {
this.visitAllTemplateNodes(component.attributes);
this.visitAllTemplateNodes(component.inputs);
this.visitAllTemplateNodes(component.outputs);
this.visitAllTemplateNodes(component.directives);
this.visitAllTemplateNodes(component.references);
this.visitAllTemplateNodes(component.children);
}
visitDirective(directive) {
this.visitAllTemplateNodes(directive.attributes);
this.visitAllTemplateNodes(directive.inputs);
this.visitAllTemplateNodes(directive.outputs);
this.visitAllTemplateNodes(directive.references);
}
visitVariable(variable) {}
visitReference(reference) {}
visitTextAttribute(attribute) {}
visitText(text) {}
visitUnknownBlock(block) {}
visitAllTemplateNodes(nodes) {
for (const node of nodes) {
this.visit(node);
}
}
}
function diff(fullList, itemsToExclude) {
const exclude = new Set(itemsToExclude);
return fullList.filter(item => !exclude.has(item));
}
function findMatchingDirectivesAndPipes(template, directiveSelectors) {
const matcher = new SelectorMatcher();
for (const selector of directiveSelectors) {
const fakeDirective = {
selector,
exportAs: null,
inputs: {
hasBindingPropertyName() {
return false;
}
},
outputs: {
hasBindingPropertyName() {
return false;
}
}
};
matcher.addSelectables(CssSelector.parse(selector), [fakeDirective]);
}
const parsedTemplate = parseTemplate(template, '');
const binder = new R3TargetBinder(matcher);
const bound = binder.bind({
template: parsedTemplate.nodes
});
const eagerDirectiveSelectors = bound.getEagerlyUsedDirectives().map(dir => dir.selector);
const allMatchedDirectiveSelectors = bound.getUsedDirectives().map(dir => dir.selector);
const eagerPipes = bound.getEagerlyUsedPipes();
return {
directives: {
regular: eagerDirectiveSelectors,
deferCandidates: diff(allMatchedDirectiveSelectors, eagerDirectiveSelectors)
},
pipes: {
regular: eagerPipes,
deferCandidates: diff(bound.getUsedPipes(), eagerPipes)
}
};
}
class R3TargetBinder {
directiveMatcher;
constructor(directiveMatcher) {
this.directiveMatcher = directiveMatcher;
}
bind(target) {
if (!target.template && !target.host) {
throw new Error('Empty bound targets are not supported');
}
const directives = new Map();
const eagerDirectives = [];
const missingDirectives = new Set();
const bindings = new Map();
const references = new Map();
const scopedNodeEntities = new Map();
const expressions = new Map();
const symbols = new Map();
const nestingLevel = new Map();
const usedPipes = new Set();
const eagerPipes = new Set();
const deferBlocks = [];
if (target.template) {
const scope = Scope.apply(target.template);
extractScopedNodeEntities(scope, scopedNodeEntities);
DirectiveBinder.apply(target.template, this.directiveMatcher, directives, eagerDirectives, missingDirectives, bindings, references);
TemplateBinder.applyWithScope(target.template, scope, expressions, symbols, nestingLevel, usedPipes, eagerPipes, deferBlocks);
}
if (target.host) {
directives.set(target.host.node, target.host.directives);
TemplateBinder.applyWithScope(target.host.node, Scope.apply(target.host.node), expressions, symbols, nestingLevel, usedPipes, eagerPipes, deferBlocks);
}
return new R3BoundTarget(target, directives, eagerDirectives, missingDirectives, bindings, references, expressions, symbols, nestingLevel, scopedNodeEntities, usedPipes, eagerPipes, deferBlocks);
}
}
class Scope {
parentScope;
rootNode;
namedEntities = new Map();
elementLikeInScope = new Set();
childScopes = new Map();
isDeferred;
constructor(parentScope, rootNode) {
this.parentScope = parentScope;
this.rootNode = rootNode;
this.isDeferred = parentScope !== null && parentScope.isDeferred ? true : rootNode instanceof DeferredBlock;
}
static newRootScope() {
return new Scope(null, null);
}
static apply(template) {
const scope = Scope.newRootScope();
scope.ingest(template);
return scope;
}
ingest(nodeOrNodes) {
if (nodeOrNodes instanceof Template) {
nodeOrNodes.variables.forEach(node => this.visitVariable(node));
nodeOrNodes.children.forEach(node => node.visit(this));
} else if (nodeOrNodes instanceof IfBlockBranch) {
if (nodeOrNodes.expressionAlias !== null) {
this.visitVariable(nodeOrNodes.expressionAlias);
}
nodeOrNodes.children.forEach(node => node.visit(this));
} else if (nodeOrNodes instanceof ForLoopBlock) {
this.visitVariable(nodeOrNodes.item);
nodeOrNodes.contextVariables.forEach(v => this.visitVariable(v));
nodeOrNodes.children.forEach(node => node.visit(this));
} else if (nodeOrNodes instanceof SwitchBlockCaseGroup || nodeOrNodes instanceof ForLoopBlockEmpty || nodeOrNodes instanceof DeferredBlock || nodeOrNodes instanceof DeferredBlockError || nodeOrNodes instanceof DeferredBlockPlaceholder || nodeOrNodes instanceof DeferredBlockLoading || nodeOrNodes instanceof Content) {
nodeOrNodes.children.forEach(node => node.visit(this));
} else if (!(nodeOrNodes instanceof HostElement)) {
nodeOrNodes.forEach(node => node.visit(this));
}
}
visitElement(element) {
this.visitElementLike(element);
}
visitTemplate(template) {
template.directives.forEach(node => node.visit(this));
template.references.forEach(node => this.visitReference(node));
this.ingestScopedNode(template);
}
visitVariable(variable) {
this.maybeDeclare(variable);
}
visitReference(reference) {
this.maybeDeclare(reference);
}
visitDeferredBlock(deferred) {
this.ingestScopedNode(deferred);
deferred.placeholder?.visit(this);
deferred.loading?.visit(this);
deferred.error?.visit(this);
}
visitDeferredBlockPlaceholder(block) {
this.ingestScopedNode(block);
}
visitDeferredBlockError(block) {
this.ingestScopedNode(block);
}
visitDeferredBlockLoading(block) {
this.ingestScopedNode(block);
}
visitSwitchBlock(block) {
block.groups.forEach(node => node.visit(this));
}
visitSwitchBlockCase(block) {}
visitSwitchBlockCaseGroup(block) {
this.ingestScopedNode(block);
}
visitForLoopBlock(block) {
this.ingestScopedNode(block);
block.empty?.visit(this);
}
visitForLoopBlockEmpty(block) {
this.ingestScopedNode(block);
}
visitIfBlock(block) {
block.branches.forEach(node => node.visit(this));
}
visitIfBlockBranch(block) {
this.ingestScopedNode(block);
}
visitContent(content) {
this.ingestScopedNode(content);
}
visitLetDeclaration(decl) {
this.maybeDeclare(decl);
}
visitComponent(component) {
this.visitElementLike(component);
}
visitDirective(directive) {
directive.references.forEach(current => this.visitReference(current));
}
visitBoundAttribute(attr) {}
visitBoundEvent(event) {}
visitBoundText(text) {}
visitText(text) {}
visitTextAttribute(attr) {}
visitIcu(icu) {}
visitDeferredTrigger(trigger) {}
visitUnknownBlock(block) {}
visitElementLike(node) {
node.directives.forEach(current => current.visit(this));
node.references.forEach(current => this.visitReference(current));
node.children.forEach(current => current.visit(this));
this.elementLikeInScope.add(node);
}
maybeDeclare(thing) {
if (!this.namedEntities.has(thing.name)) {
this.namedEntities.set(thing.name, thing);
}
}
lookup(name) {
if (this.namedEntities.has(name)) {
return this.namedEntities.get(name);
} else if (this.parentScope !== null) {
return this.parentScope.lookup(name);
} else {
return null;
}
}
getChildScope(node) {
const res = this.childScopes.get(node);
if (res === undefined) {
throw new Error(`Assertion error: child scope for ${node} not found`);
}
return res;
}
ingestScopedNode(node) {
const scope = new Scope(this, node);
scope.ingest(node);
this.childScopes.set(node, scope);
}
}
class DirectiveBinder {
directiveMatcher;
directives;
eagerDirectives;
missingDirectives;
bindings;
references;
isInDeferBlock = false;
constructor(directiveMatcher, directives, eagerDirectives, missingDirectives, bindings, references) {
this.directiveMatcher = directiveMatcher;
this.directives = directives;
this.eagerDirectives = eagerDirectives;
this.missingDirectives = missingDirectives;
this.bindings = bindings;
this.references = references;
}
static apply(template, directiveMatcher, directives, eagerDirectives, missingDirectives, bindings, references) {
const matcher = new DirectiveBinder(directiveMatcher, directives, eagerDirectives, missingDirectives, bindings, references);
matcher.ingest(template);
}
ingest(template) {
template.forEach(node => node.visit(this));
}
visitElement(element) {
this.visitElementOrTemplate(element);
}
visitTemplate(template) {
this.visitElementOrTemplate(template);
}
visitDeferredBlock(deferred) {
const wasInDeferBlock = this.isInDeferBlock;
this.isInDeferBlock = true;
deferred.children.forEach(child => child.visit(this));
this.isInDeferBlock = wasInDeferBlock;
deferred.placeholder?.visit(this);
deferred.loading?.visit(this);
deferred.error?.visit(this);
}
visitDeferredBlockPlaceholder(block) {
block.children.forEach(child => child.visit(this));
}
visitDeferredBlockError(block) {
block.children.forEach(child => child.visit(this));
}
visitDeferredBlockLoading(block) {
block.children.forEach(child => child.visit(this));
}
visitSwitchBlock(block) {
block.groups.forEach(node => node.visit(this));
}
visitSwitchBlockCase(block) {}
visitSwitchBlockCaseGroup(block) {
block.children.forEach(node => node.visit(this));
}
visitForLoopBlock(block) {
block.item.visit(this);
block.contextVariables.forEach(v => v.visit(this));
block.children.forEach(node => node.visit(this));
block.empty?.visit(this);
}
visitForLoopBlockEmpty(block) {
block.children.forEach(node => node.visit(this));
}
visitIfBlock(block) {
block.branches.forEach(node => node.visit(this));
}
visitIfBlockBranch(block) {
block.expressionAlias?.visit(this);
block.children.forEach(node => node.visit(this));
}
visitContent(content) {
content.children.forEach(child => child.visit(this));
}
visitComponent(node) {
if (this.directiveMatcher instanceof SelectorlessMatcher) {
const componentMatches = this.directiveMatcher.match(node.componentName);
if (componentMatches.length > 0) {
this.trackSelectorlessMatchesAndDirectives(node, componentMatches);
} else {
this.missingDirectives.add(node.componentName);
}
}
node.directives.forEach(directive => directive.visit(this));
node.children.forEach(child => child.visit(this));
}
visitDirective(node) {
if (this.directiveMatcher instanceof SelectorlessMatcher) {
const directives = this.directiveMatcher.match(node.name);
if (directives.length > 0) {
this.trackSelectorlessMatchesAndDirectives(node, directives);
} else {
this.missingDirectives.add(node.name);
}
}
}
visitElementOrTemplate(node) {
if (this.directiveMatcher instanceof SelectorMatcher) {
const directives = [];
const cssSelector = createCssSelectorFromNode(node);
this.directiveMatcher.match(cssSelector, (_, results) => directives.push(...results));
this.trackSelectorBasedBindingsAndDirectives(node, directives);
} else {
node.references.forEach(ref => {
if (ref.value.trim() === '') {
this.references.set(ref, node);
}
});
}
node.directives.forEach(directive => directive.visit(this));
node.children.forEach(child => child.visit(this));
}
trackMatchedDirectives(node, directives) {
if (directives.length > 0) {
this.directives.set(node, directives);
if (!this.isInDeferBlock) {
this.eagerDirectives.push(...directives);
}
}
}
trackSelectorlessMatchesAndDirectives(node, directives) {
if (directives.length === 0) {
return;
}
this.trackMatchedDirectives(node, directives);
const setBinding = (meta, attribute, ioType) => {
if (meta[ioType].hasBindingPropertyName(attribute.name)) {
this.bindings.set(attribute, meta);
}
};
for (const directive of directives) {
node.inputs.forEach(input => setBinding(directive, input, 'inputs'));
node.attributes.forEach(attr => setBinding(directive, attr, 'inputs'));
node.outputs.forEach(output => setBinding(directive, output, 'outputs'));
}
node.references.forEach(ref => this.references.set(ref, {
directive: directives[0],
node: node
}));
}
trackSelectorBasedBindingsAndDirectives(node, directives) {
this.trackMatchedDirectives(node, directives);
node.references.forEach(ref => {
let dirTarget = null;
if (ref.value.trim() === '') {
dirTarget = directives.find(dir => dir.isComponent) || null;
} else {
dirTarget = directives.find(dir => dir.exportAs !== null && dir.exportAs.some(value => value === ref.value)) || null;
if (dirTarget === null) {
return;
}
}
if (dirTarget !== null) {
this.references.set(ref, {
directive: dirTarget,
node
});
} else {
this.references.set(ref, node);
}
});
const setAttributeBinding = (attribute, ioType) => {
const dir = directives.find(dir => dir[ioType].hasBindingPropertyName(attribute.name));
const binding = dir !== undefined ? dir : node;
this.bindings.set(attribute, binding);
};
node.inputs.forEach(input => setAttributeBinding(input, 'inputs'));
node.attributes.forEach(attr => setAttributeBinding(attr, 'inputs'));
if (node instanceof Template) {
node.templateAttrs.forEach(attr => setAttributeBinding(attr, 'inputs'));
}
node.outputs.forEach(output => setAttributeBinding(output, 'outputs'));
}
visitVariable(variable) {}
visitReference(reference) {}
visitTextAttribute(attribute) {}
visitBoundAttribute(attribute) {}
visitBoundEvent(attribute) {}
visitBoundAttributeOrEvent(node) {}
visitText(text) {}
visitBoundText(text) {}
visitIcu(icu) {}
visitDeferredTrigger(trigger) {}
visitUnknownBlock(block) {}
visitLetDeclaration(decl) {}
}
class TemplateBinder extends CombinedRecursiveAstVisitor {
bindings;
symbols;
usedPipes;
eagerPipes;
deferBlocks;
nestingLevel;
scope;
rootNode;
level;
visitNode = node => node.visit(this);
constructor(bindings, symbols, usedPipes, eagerPipes, deferBlocks, nestingLevel, scope, rootNode, level) {
super();
this.bindings = bindings;
this.symbols = symbols;
this.usedPipes = usedPipes;
this.eagerPipes = eagerPipes;
this.deferBlocks = deferBlocks;
this.nestingLevel = nestingLevel;
this.scope = scope;
this.rootNode = rootNode;
this.level = level;
}
static applyWithScope(nodeOrNodes, scope, expressions, symbols, nestingLevel, usedPipes, eagerPipes, deferBlocks) {
const template = nodeOrNodes instanceof Template ? nodeOrNodes : null;
const binder = new TemplateBinder(expressions, symbols, usedPipes, eagerPipes, deferBlocks, nestingLevel, scope, template, 0);
binder.ingest(nodeOrNodes);
}
ingest(nodeOrNodes) {
if (nodeOrNodes instanceof Template) {
nodeOrNodes.variables.forEach(this.visitNode);
nodeOrNodes.children.forEach(this.visitNode);
this.nestingLevel.set(nodeOrNodes, this.level);
} else if (nodeOrNodes instanceof IfBlockBranch) {
if (nodeOrNodes.expressionAlias !== null) {
this.visitNode(nodeOrNodes.expressionAlias);
}
nodeOrNodes.children.forEach(this.visitNode);
this.nestingLevel.set(nodeOrNodes, this.level);
} else if (nodeOrNodes instanceof ForLoopBlock) {
this.visitNode(nodeOrNodes.item);
nodeOrNodes.contextVariables.forEach(v => this.visitNode(v));
nodeOrNodes.trackBy.visit(this);
nodeOrNodes.children.forEach(this.visitNode);
this.nestingLevel.set(nodeOrNodes, this.level);
} else if (nodeOrNodes instanceof DeferredBlock) {
if (this.scope.rootNode !== nodeOrNodes) {
throw new Error(`Assertion error: resolved incorrect scope for deferred block ${nodeOrNodes}`);
}
this.deferBlocks.push([nodeOrNodes, this.scope]);
nodeOrNodes.children.forEach(node => node.visit(this));
this.nestingLevel.set(nodeOrNodes, this.level);
} else if (nodeOrNodes instanceof SwitchBlockCaseGroup || nodeOrNodes instanceof ForLoopBlockEmpty || nodeOrNodes instanceof DeferredBlockError || nodeOrNodes instanceof DeferredBlockPlaceholder || nodeOrNodes instanceof DeferredBlockLoading || nodeOrNodes instanceof Content) {
nodeOrNodes.children.forEach(node => node.visit(this));
this.nestingLevel.set(nodeOrNodes, this.level);
} else if (nodeOrNodes instanceof HostElement) {
this.nestingLevel.set(nodeOrNodes, 0);
} else {
nodeOrNodes.forEach(this.visitNode);
}
}
visitTemplate(template) {
template.inputs.forEach(this.visitNode);
template.outputs.forEach(this.visitNode);
template.directives.forEach(this.visitNode);
template.templateAttrs.forEach(this.visitNode);
template.references.forEach(this.visitNode);
this.ingestScopedNode(template);
}
visitVariable(variable) {
if (this.rootNode !== null) {
this.symbols.set(variable, this.rootNode);
}
}
visitReference(reference) {
if (this.rootNode !== null) {
this.symbols.set(reference, this.rootNode);
}
}
visitDeferredBlock(deferred) {
this.ingestScopedNode(deferred);
deferred.triggers.when?.value.visit(this);
deferred.prefetchTriggers.when?.value.visit(this);
deferred.hydrateTriggers.when?.value.visit(this);
deferred.hydrateTriggers.never?.visit(this);
deferred.placeholder && this.visitNode(deferred.placeholder);
deferred.loading && this.visitNode(deferred.loading);
deferred.error && this.visitNode(deferred.error);
}
visitDeferredBlockPlaceholder(block) {
this.ingestScopedNode(block);
}
visitDeferredBlockError(block) {
this.ingestScopedNode(block);
}
visitDeferredBlockLoading(block) {
this.ingestScopedNode(block);
}
visitSwitchBlockCase(block) {
block.expression?.visit(this);
}
visitSwitchBlockCaseGroup(block) {
block.cases.forEach(caseNode => caseNode.visit(this));
this.ingestScopedNode(block);
}
visitForLoopBlock(block) {
block.expression.visit(this);
this.ingestScopedNode(block);
block.empty?.visit(this);
}
visitForLoopBlockEmpty(block) {
this.ingestScopedNode(block);
}
visitIfBlockBranch(block) {
block.expression?.visit(this);
this.ingestScopedNode(block);
}
visitContent(content) {
this.ingestScopedNode(content);
}
visitLetDeclaration(decl) {
super.visitLetDeclaration(decl);
if (this.rootNode !== null) {
this.symbols.set(decl, this.rootNode);
}
}
visitPipe(ast, context) {
this.usedPipes.add(ast.name);
if (!this.scope.isDeferred) {
this.eagerPipes.add(ast.name);
}
return super.visitPipe(ast, context);
}
visitPropertyRead(ast, context) {
this.maybeMap(ast, ast.name);
return super.visitPropertyRead(ast, context);
}
visitSafePropertyRead(ast, context) {
this.maybeMap(ast, ast.name);
return super.visitSafePropertyRead(ast, context);
}
ingestScopedNode(node) {
const childScope = this.scope.getChildScope(node);
const binder = new TemplateBinder(this.bindings, this.symbols, this.usedPipes, this.eagerPipes, this.deferBlocks, this.nestingLevel, childScope, node, this.level + 1);
binder.ingest(node);
}
maybeMap(ast, name) {
if (!(ast.receiver instanceof ImplicitReceiver)) {
return;
}
const target = this.scope.lookup(name);
if (target !== null) {
this.bindings.set(ast, target);
}
}
}
class R3BoundTarget {
target;
directives;
eagerDirectives;
missingDirectives;
bindings;
references;
exprTargets;
symbols;
nestingLevel;
scopedNodeEntities;
usedPipes;
eagerPipes;
deferredBlocks;
deferredScopes;
constructor(target, directives, eagerDirectives, missingDirectives, bindings, references, exprTargets, symbols, nestingLevel, scopedNodeEntities, usedPipes, eagerPipes, rawDeferred) {
this.target = target;
this.directives = directives;
this.eagerDirectives = eagerDirectives;
this.missingDirectives = missingDirectives;
this.bindings = bindings;
this.references = references;
this.exprTargets = exprTargets;
this.symbols = symbols;
this.nestingLevel = nestingLevel;
this.scopedNodeEntities = scopedNodeEntities;
this.usedPipes = usedPipes;
this.eagerPipes = eagerPipes;
this.deferredBlocks = rawDeferred.map(current => current[0]);
this.deferredScopes = new Map(rawDeferred);
}
getEntitiesInScope(node) {
return this.scopedNodeEntities.get(node) ?? new Set();
}
getDirectivesOfNode(node) {
return this.directives.get(node) || null;
}
getReferenceTarget(ref) {
return this.references.get(ref) || null;
}
getConsumerOfBinding(binding) {
return this.bindings.get(binding) || null;
}
getExpressionTarget(expr) {
return this.exprTargets.get(expr) || null;
}
getDefinitionNodeOfSymbol(symbol) {
return this.symbols.get(symbol) || null;
}
getNestingLevel(node) {
return this.nestingLevel.get(node) || 0;
}
getUsedDirectives() {
const set = new Set();
this.directives.forEach(dirs => dirs.forEach(dir => set.add(dir)));
return Array.from(set.values());
}
getEagerlyUsedDirectives() {
const set = new Set(this.eagerDirectives);
return Array.from(set.values());
}
getUsedPipes() {
return Array.from(this.usedPipes);
}
getEagerlyUsedPipes() {
return Array.from(this.eagerPipes);
}
getDeferBlocks() {
return this.deferredBlocks;
}
getDeferredTriggerTarget(block, trigger) {
if (!(trigger instanceof InteractionDeferredTrigger) && !(trigger instanceof ViewportDeferredTrigger) && !(trigger instanceof HoverDeferredTrigger)) {
return null;
}
const name = trigger.reference;
if (name === null) {
let target = null;
if (block.placeholder !== null) {
for (const child of block.placeholder.children) {
if (child instanceof Comment$1) {
continue;
}
if (target !== null) {
return null;
}
if (child instanceof Element$1) {
target = child;
}
}
}
return target;
}
const outsideRef = this.findEntityInScope(block, name);
if (outsideRef instanceof Reference && this.getDefinitionNodeOfSymbol(outsideRef) !== block) {
const target = this.getReferenceTarget(outsideRef);
if (target !== null) {
return this.referenceTargetToElement(target);
}
}
if (block.placeholder !== null) {
const refInPlaceholder = this.findEntityInScope(block.placeholder, name);
const targetInPlaceholder = refInPlaceholder instanceof Reference ? this.getReferenceTarget(refInPlaceholder) : null;
if (targetInPlaceholder !== null) {
return this.referenceTargetToElement(targetInPlaceholder);
}
}
return null;
}
isDeferred(element) {
for (const block of this.deferredBlocks) {
if (!this.deferredScopes.has(block)) {
continue;
}
const stack = [this.deferredScopes.get(block)];
while (stack.length > 0) {
const current = stack.pop();
if (current.elementLikeInScope.has(element)) {
return true;
}
stack.push(...current.childScopes.values());
}
}
return false;
}
referencedDirectiveExists(name) {
return !this.missingDirectives.has(name);
}
findEntityInScope(rootNode, name) {
const entities = this.getEntitiesInScope(rootNode);
for (const entity of entities) {
if (entity.name === name) {
return entity;
}
}
return null;
}
referenceTargetToElement(target) {
if (target instanceof Element$1) {
return target;
}
if (target instanceof Template || target.node instanceof Component$1 || target.node instanceof Directive$1 || target.node instanceof HostElement) {
return null;
}
return this.referenceTargetToElement(target.node);
}
}
function extractScopedNodeEntities(rootScope, templateEntities) {
const entityMap = new Map();
function extractScopeEntities(scope) {
if (entityMap.has(scope.rootNode)) {
return entityMap.get(scope.rootNode);
}
const currentEntities = scope.namedEntities;
let entities;
if (scope.parentScope !== null) {
entities = new Map([...extractScopeEntities(scope.parentScope), ...currentEntities]);
} else {
entities = new Map(currentEntities);
}
entityMap.set(scope.rootNode, entities);
return entities;
}
const scopesToProcess = [rootScope];
while (scopesToProcess.length > 0) {
const scope = scopesToProcess.pop();
for (const childScope of scope.childScopes.values()) {
scopesToProcess.push(childScope);
}
extractScopeEntities(scope);
}
for (const [template, entities] of entityMap) {
templateEntities.set(template, new Set(entities.values()));
}
}
class ResourceLoader {}
class CompilerFacadeImpl {
jitEvaluator;
FactoryTarget = FactoryTarget;
ResourceLoader = ResourceLoader;
elementSchemaRegistry = new DomElementSchemaRegistry();
constructor(jitEvaluator = new JitEvaluator()) {
this.jitEvaluator = jitEvaluator;
}
compilePipe(angularCoreEnv, sourceMapUrl, facade) {
const metadata = {
name: facade.name,
type: wrapReference(facade.type),
typeArgumentCount: 0,
deps: null,
pipeName: facade.pipeName,
pure: facade.pure,
isStandalone: facade.isStandalone
};
const res = compilePipeFromMetadata(metadata);
return this.jitExpression(res.expression, angularCoreEnv, sourceMapUrl, []);
}
compilePipeDeclaration(angularCoreEnv, sourceMapUrl, declaration) {
const meta = convertDeclarePipeFacadeToMetadata(declaration);
const res = compilePipeFromMetadata(meta);
return this.jitExpression(res.expression, angularCoreEnv, sourceMapUrl, []);
}
compileInjectable(angularCoreEnv, sourceMapUrl, facade) {
const {
expression,
statements
} = compileInjectable({
name: facade.name,
type: wrapReference(facade.type),
typeArgumentCount: facade.typeArgumentCount,
providedIn: computeProvidedIn(facade.providedIn),
useClass: convertToProviderExpression(facade, 'useClass'),
useFactory: wrapExpression(facade, 'useFactory'),
useValue: convertToProviderExpression(facade, 'useValue'),
useExisting: convertToProviderExpression(facade, 'useExisting'),
deps: facade.deps?.map(convertR3DependencyMetadata)
}, true);
return this.jitExpression(expression, angularCoreEnv, sourceMapUrl, statements);
}
compileInjectableDeclaration(angularCoreEnv, sourceMapUrl, facade) {
const {
expression,
statements
} = compileInjectable({
name: facade.type.name,
type: wrapReference(facade.type),
typeArgumentCount: 0,
providedIn: computeProvidedIn(facade.providedIn),
useClass: convertToProviderExpression(facade, 'useClass'),
useFactory: wrapExpression(facade, 'useFactory'),
useValue: convertToProviderExpression(facade, 'useValue'),
useExisting: convertToProviderExpression(facade, 'useExisting'),
deps: facade.deps?.map(convertR3DeclareDependencyMetadata)
}, true);
return this.jitExpression(expression, angularCoreEnv, sourceMapUrl, statements);
}
compileInjector(angularCoreEnv, sourceMapUrl, facade) {
const meta = {
name: facade.name,
type: wrapReference(facade.type),
providers: facade.providers && facade.providers.length > 0 ? new WrappedNodeExpr(facade.providers) : null,
imports: facade.imports.map(i => new WrappedNodeExpr(i))
};
const res = compileInjector(meta);
return this.jitExpression(res.expression, angularCoreEnv, sourceMapUrl, []);
}
compileInjectorDeclaration(angularCoreEnv, sourceMapUrl, declaration) {
const meta = convertDeclareInjectorFacadeToMetadata(declaration);
const res = compileInjector(meta);
return this.jitExpression(res.expression, angularCoreEnv, sourceMapUrl, []);
}
compileNgModule(angularCoreEnv, sourceMapUrl, facade) {
const meta = {
kind: R3NgModuleMetadataKind.Global,
type: wrapReference(facade.type),
bootstrap: facade.bootstrap.map(wrapReference),
declarations: facade.declarations.map(wrapReference),
publicDeclarationTypes: null,
imports: facade.imports.map(wrapReference),
includeImportTypes: true,
exports: facade.exports.map(wrapReference),
selectorScopeMode: R3SelectorScopeMode.Inline,
containsForwardDecls: false,
schemas: facade.schemas ? facade.schemas.map(wrapReference) : null,
id: facade.id ? new WrappedNodeExpr(facade.id) : null
};
const res = compileNgModule(meta);
return this.jitExpression(res.expression, angularCoreEnv, sourceMapUrl, []);
}
compileNgModuleDeclaration(angularCoreEnv, sourceMapUrl, declaration) {
const expression = compileNgModuleDeclarationExpression(declaration);
return this.jitExpression(expression, angularCoreEnv, sourceMapUrl, []);
}
compileDirective(angularCoreEnv, sourceMapUrl, facade) {
const meta = convertDirectiveFacadeToMetadata(facade);
return this.compileDirectiveFromMeta(angularCoreEnv, sourceMapUrl, meta);
}
compileDirectiveDeclaration(angularCoreEnv, sourceMapUrl, declaration) {
const typeSourceSpan = this.createParseSourceSpan('Directive', declaration.type.name, sourceMapUrl);
const meta = convertDeclareDirectiveFacadeToMetadata(declaration, typeSourceSpan);
return this.compileDirectiveFromMeta(angularCoreEnv, sourceMapUrl, meta);
}
compileDirectiveFromMeta(angularCoreEnv, sourceMapUrl, meta) {
const constantPool = new ConstantPool();
const bindingParser = makeBindingParser();
const res = compileDirectiveFromMetadata(meta, constantPool, bindingParser);
return this.jitExpression(res.expression, angularCoreEnv, sourceMapUrl, constantPool.statements);
}
compileComponent(angularCoreEnv, sourceMapUrl, facade) {
const {
template,
defer
} = parseJitTemplate(facade.template, facade.name, sourceMapUrl, facade.preserveWhitespaces, undefined);
const meta = {
...facade,
...convertDirectiveFacadeToMetadata(facade),
selector: facade.selector || this.elementSchemaRegistry.getDefaultComponentElementName(),
template,
declarations: facade.declarations.map(convertDeclarationFacadeToMetadata),
declarationListEmitMode: 0,
defer,
styles: [...facade.styles, ...template.styles],
encapsulation: facade.encapsulation,
changeDetection: facade.changeDetection ?? null,
animations: facade.animations != null ? new WrappedNodeExpr(facade.animations) : null,
viewProviders: facade.viewProviders != null ? new WrappedNodeExpr(facade.viewProviders) : null,
relativeContextFilePath: '',
i18nUseExternalIds: true,
relativeTemplatePath: null
};
const jitExpressionSourceMap = `ng:///${facade.name}.js`;
return this.compileComponentFromMeta(angularCoreEnv, jitExpressionSourceMap, meta);
}
compileComponentDeclaration(angularCoreEnv, sourceMapUrl, declaration) {
const typeSourceSpan = this.createParseSourceSpan('Component', declaration.type.name, sourceMapUrl);
const meta = convertDeclareComponentFacadeToMetadata(declaration, typeSourceSpan, sourceMapUrl);
return this.compileComponentFromMeta(angularCoreEnv, sourceMapUrl, meta);
}
compileComponentFromMeta(angularCoreEnv, sourceMapUrl, meta) {
const constantPool = new ConstantPool();
const bindingParser = makeBindingParser();
const res = compileComponentFromMetadata(meta, constantPool, bindingParser);
return this.jitExpression(res.expression, angularCoreEnv, sourceMapUrl, constantPool.statements);
}
compileFactory(angularCoreEnv, sourceMapUrl, meta) {
const factoryRes = compileFactoryFunction({
name: meta.name,
type: wrapReference(meta.type),
typeArgumentCount: meta.typeArgumentCount,
deps: convertR3DependencyMetadataArray(meta.deps),
target: meta.target
});
return this.jitExpression(factoryRes.expression, angularCoreEnv, sourceMapUrl, factoryRes.statements);
}
compileFactoryDeclaration(angularCoreEnv, sourceMapUrl, meta) {
const factoryRes = compileFactoryFunction({
name: meta.type.name,
type: wrapReference(meta.type),
typeArgumentCount: 0,
deps: Array.isArray(meta.deps) ? meta.deps.map(convertR3DeclareDependencyMetadata) : meta.deps,
target: meta.target
});
return this.jitExpression(factoryRes.expression, angularCoreEnv, sourceMapUrl, factoryRes.statements);
}
createParseSourceSpan(kind, typeName, sourceUrl) {
return r3JitTypeSourceSpan(kind, typeName, sourceUrl);
}
jitExpression(def, context, sourceUrl, preStatements) {
const statements = [...preStatements, new DeclareVarStmt('$def', def, undefined, StmtModifier.Exported)];
const res = this.jitEvaluator.evaluateStatements(sourceUrl, statements, new R3JitReflector(context), true);
return res['$def'];
}
}
function convertToR3QueryMetadata(facade) {
return {
...facade,
isSignal: facade.isSignal,
predicate: convertQueryPredicate(facade.predicate),
read: facade.read ? new WrappedNodeExpr(facade.read) : null,
static: facade.static,
emitDistinctChangesOnly: facade.emitDistinctChangesOnly
};
}
function convertQueryDeclarationToMetadata(declaration) {
return {
propertyName: declaration.propertyName,
first: declaration.first ?? false,
predicate: convertQueryPredicate(declaration.predicate),
descendants: declaration.descendants ?? false,
read: declaration.read ? new WrappedNodeExpr(declaration.read) : null,
static: declaration.static ?? false,
emitDistinctChangesOnly: declaration.emitDistinctChangesOnly ?? true,
isSignal: !!declaration.isSignal
};
}
function convertQueryPredicate(predicate) {
return Array.isArray(predicate) ? predicate : createMayBeForwardRefExpression(new WrappedNodeExpr(predicate), 1);
}
function convertDirectiveFacadeToMetadata(facade) {
const inputsFromMetadata = parseInputsArray(facade.inputs || []);
const outputsFromMetadata = parseMappingStringArray(facade.outputs || []);
const propMetadata = facade.propMetadata;
const inputsFromType = {};
const outputsFromType = {};
for (const field in propMetadata) {
if (propMetadata.hasOwnProperty(field)) {
propMetadata[field].forEach(ann => {
if (isInput(ann)) {
inputsFromType[field] = {
bindingPropertyName: ann.alias || field,
classPropertyName: field,
required: ann.required || false,
isSignal: !!ann.isSignal,
transformFunction: ann.transform != null ? new WrappedNodeExpr(ann.transform) : null
};
} else if (isOutput(ann)) {
outputsFromType[field] = ann.alias || field;
}
});
}
}
const hostDirectives = facade.hostDirectives?.length ? facade.hostDirectives.map(hostDirective => {
return typeof hostDirective === 'function' ? {
directive: wrapReference(hostDirective),
inputs: null,
outputs: null,
isForwardReference: false
} : {
directive: wrapReference(hostDirective.directive),
isForwardReference: false,
inputs: hostDirective.inputs ? parseMappingStringArray(hostDirective.inputs) : null,
outputs: hostDirective.outputs ? parseMappingStringArray(hostDirective.outputs) : null
};
}) : null;
return {
...facade,
typeArgumentCount: 0,
typeSourceSpan: facade.typeSourceSpan,
type: wrapReference(facade.type),
deps: null,
host: {
...extractHostBindings(facade.propMetadata, facade.typeSourceSpan, facade.host)
},
inputs: {
...inputsFromMetadata,
...inputsFromType
},
outputs: {
...outputsFromMetadata,
...outputsFromType
},
queries: facade.queries.map(convertToR3QueryMetadata),
providers: facade.providers != null ? new WrappedNodeExpr(facade.providers) : null,
viewQueries: facade.viewQueries.map(convertToR3QueryMetadata),
hostDirectives
};
}
function convertDeclareDirectiveFacadeToMetadata(declaration, typeSourceSpan) {
const hostDirectives = declaration.hostDirectives?.length ? declaration.hostDirectives.map(dir => ({
directive: wrapReference(dir.directive),
isForwardReference: false,
inputs: dir.inputs ? getHostDirectiveBindingMapping(dir.inputs) : null,
outputs: dir.outputs ? getHostDirectiveBindingMapping(dir.outputs) : null
})) : null;
return {
name: declaration.type.name,
type: wrapReference(declaration.type),
typeSourceSpan,
selector: declaration.selector ?? null,
inputs: declaration.inputs ? inputsPartialMetadataToInputMetadata(declaration.inputs) : {},
outputs: declaration.outputs ?? {},
host: convertHostDeclarationToMetadata(declaration.host),
queries: (declaration.queries ?? []).map(convertQueryDeclarationToMetadata),
viewQueries: (declaration.viewQueries ?? []).map(convertQueryDeclarationToMetadata),
providers: declaration.providers !== undefined ? new WrappedNodeExpr(declaration.providers) : null,
exportAs: declaration.exportAs ?? null,
usesInheritance: declaration.usesInheritance ?? false,
lifecycle: {
usesOnChanges: declaration.usesOnChanges ?? false
},
deps: null,
typeArgumentCount: 0,
isStandalone: declaration.isStandalone ?? getJitStandaloneDefaultForVersion(declaration.version),
isSignal: declaration.isSignal ?? false,
hostDirectives
};
}
function convertHostDeclarationToMetadata(host = {}) {
return {
attributes: convertOpaqueValuesToExpressions(host.attributes ?? {}),
listeners: host.listeners ?? {},
properties: host.properties ?? {},
specialAttributes: {
classAttr: host.classAttribute,
styleAttr: host.styleAttribute
}
};
}
function getHostDirectiveBindingMapping(array) {
let result = null;
for (let i = 1; i < array.length; i += 2) {
result = result || {};
result[array[i - 1]] = array[i];
}
return result;
}
function convertOpaqueValuesToExpressions(obj) {
const result = {};
for (const key of Object.keys(obj)) {
result[key] = new WrappedNodeExpr(obj[key]);
}
return result;
}
function convertDeclareComponentFacadeToMetadata(decl, typeSourceSpan, sourceMapUrl) {
const {
template,
defer
} = parseJitTemplate(decl.template, decl.type.name, sourceMapUrl, decl.preserveWhitespaces ?? false, decl.deferBlockDependencies);
const declarations = [];
if (decl.dependencies) {
for (const innerDep of decl.dependencies) {
switch (innerDep.kind) {
case 'directive':
case 'component':
declarations.push(convertDirectiveDeclarationToMetadata(innerDep));
break;
case 'pipe':
declarations.push(convertPipeDeclarationToMetadata(innerDep));
break;
}
}
} else if (decl.components || decl.directives || decl.pipes) {
decl.components && declarations.push(...decl.components.map(dir => convertDirectiveDeclarationToMetadata(dir, true)));
decl.directives && declarations.push(...decl.directives.map(dir => convertDirectiveDeclarationToMetadata(dir)));
decl.pipes && declarations.push(...convertPipeMapToMetadata(decl.pipes));
}
const hasDirectiveDependencies = declarations.some(({
kind
}) => kind === R3TemplateDependencyKind.Directive || kind === R3TemplateDependencyKind.NgModule);
return {
...convertDeclareDirectiveFacadeToMetadata(decl, typeSourceSpan),
template,
styles: decl.styles ?? [],
declarations,
viewProviders: decl.viewProviders !== undefined ? new WrappedNodeExpr(decl.viewProviders) : null,
animations: decl.animations !== undefined ? new WrappedNodeExpr(decl.animations) : null,
defer,
changeDetection: decl.changeDetection ?? ChangeDetectionStrategy.Default,
encapsulation: decl.encapsulation ?? ViewEncapsulation$1.Emulated,
declarationListEmitMode: 2,
relativeContextFilePath: '',
i18nUseExternalIds: true,
relativeTemplatePath: null,
hasDirectiveDependencies
};
}
function convertDeclarationFacadeToMetadata(declaration) {
return {
...declaration,
type: new WrappedNodeExpr(declaration.type)
};
}
function convertDirectiveDeclarationToMetadata(declaration, isComponent = null) {
return {
kind: R3TemplateDependencyKind.Directive,
isComponent: isComponent || declaration.kind === 'component',
selector: declaration.selector,
type: new WrappedNodeExpr(declaration.type),
inputs: declaration.inputs ?? [],
outputs: declaration.outputs ?? [],
exportAs: declaration.exportAs ?? null
};
}
function convertPipeMapToMetadata(pipes) {
if (!pipes) {
return [];
}
return Object.keys(pipes).map(name => {
return {
kind: R3TemplateDependencyKind.Pipe,
name,
type: new WrappedNodeExpr(pipes[name])
};
});
}
function convertPipeDeclarationToMetadata(pipe) {
return {
kind: R3TemplateDependencyKind.Pipe,
name: pipe.name,
type: new WrappedNodeExpr(pipe.type)
};
}
function parseJitTemplate(template, typeName, sourceMapUrl, preserveWhitespaces, deferBlockDependencies) {
const parsed = parseTemplate(template, sourceMapUrl, {
preserveWhitespaces
});
if (parsed.errors !== null) {
const errors = parsed.errors.map(err => err.toString()).join(', ');
throw new Error(`Errors during JIT compilation of template for ${typeName}: ${errors}`);
}
const binder = new R3TargetBinder(null);
const boundTarget = binder.bind({
template: parsed.nodes
});
return {
template: parsed,
defer: createR3ComponentDeferMetadata(boundTarget, deferBlockDependencies)
};
}
function convertToProviderExpression(obj, property) {
if (obj.hasOwnProperty(property)) {
return createMayBeForwardRefExpression(new WrappedNodeExpr(obj[property]), 0);
} else {
return undefined;
}
}
function wrapExpression(obj, property) {
if (obj.hasOwnProperty(property)) {
return new WrappedNodeExpr(obj[property]);
} else {
return undefined;
}
}
function computeProvidedIn(providedIn) {
const expression = typeof providedIn === 'function' ? new WrappedNodeExpr(providedIn) : new LiteralExpr(providedIn ?? null);
return createMayBeForwardRefExpression(expression, 0);
}
function convertR3DependencyMetadataArray(facades) {
return facades == null ? null : facades.map(convertR3DependencyMetadata);
}
function convertR3DependencyMetadata(facade) {
const isAttributeDep = facade.attribute != null;
const rawToken = facade.token === null ? null : new WrappedNodeExpr(facade.token);
const token = isAttributeDep ? new WrappedNodeExpr(facade.attribute) : rawToken;
return createR3DependencyMetadata(token, isAttributeDep, facade.host, facade.optional, facade.self, facade.skipSelf);
}
function convertR3DeclareDependencyMetadata(facade) {
const isAttributeDep = facade.attribute ?? false;
const token = facade.token === null ? null : new WrappedNodeExpr(facade.token);
return createR3DependencyMetadata(token, isAttributeDep, facade.host ?? false, facade.optional ?? false, facade.self ?? false, facade.skipSelf ?? false);
}
function createR3DependencyMetadata(token, isAttributeDep, host, optional, self, skipSelf) {
const attributeNameType = isAttributeDep ? literal('unknown') : null;
return {
token,
attributeNameType,
host,
optional,
self,
skipSelf
};
}
function createR3ComponentDeferMetadata(boundTarget, deferBlockDependencies) {
const deferredBlocks = boundTarget.getDeferBlocks();
const blocks = new Map();
for (let i = 0; i < deferredBlocks.length; i++) {
const dependencyFn = deferBlockDependencies?.[i];
blocks.set(deferredBlocks[i], dependencyFn ? new WrappedNodeExpr(dependencyFn) : null);
}
return {
mode: 0,
blocks
};
}
function extractHostBindings(propMetadata, sourceSpan, host) {
const bindings = parseHostBindings(host || {});
const errors = verifyHostBindings(bindings, sourceSpan);
if (errors.length) {
throw new Error(errors.map(error => error.msg).join('\n'));
}
for (const field in propMetadata) {
if (propMetadata.hasOwnProperty(field)) {
propMetadata[field].forEach(ann => {
if (isHostBinding(ann)) {
bindings.properties[ann.hostPropertyName || field] = getSafePropertyAccessString('this', field);
} else if (isHostListener(ann)) {
bindings.listeners[ann.eventName || field] = `${field}(${(ann.args || []).join(',')})`;
}
});
}
}
return bindings;
}
function isHostBinding(value) {
return value.ngMetadataName === 'HostBinding';
}
function isHostListener(value) {
return value.ngMetadataName === 'HostListener';
}
function isInput(value) {
return value.ngMetadataName === 'Input';
}
function isOutput(value) {
return value.ngMetadataName === 'Output';
}
function inputsPartialMetadataToInputMetadata(inputs) {
return Object.keys(inputs).reduce((result, minifiedClassName) => {
const value = inputs[minifiedClassName];
if (typeof value === 'string' || Array.isArray(value)) {
result[minifiedClassName] = parseLegacyInputPartialOutput(value);
} else {
result[minifiedClassName] = {
bindingPropertyName: value.publicName,
classPropertyName: minifiedClassName,
transformFunction: value.transformFunction !== null ? new WrappedNodeExpr(value.transformFunction) : null,
required: value.isRequired,
isSignal: value.isSignal
};
}
return result;
}, {});
}
function parseLegacyInputPartialOutput(value) {
if (typeof value === 'string') {
return {
bindingPropertyName: value,
classPropertyName: value,
transformFunction: null,
required: false,
isSignal: false
};
}
return {
bindingPropertyName: value[0],
classPropertyName: value[1],
transformFunction: value[2] ? new WrappedNodeExpr(value[2]) : null,
required: false,
isSignal: false
};
}
function parseInputsArray(values) {
return values.reduce((results, value) => {
if (typeof value === 'string') {
const [bindingPropertyName, classPropertyName] = parseMappingString(value);
results[classPropertyName] = {
bindingPropertyName,
classPropertyName,
required: false,
isSignal: false,
transformFunction: null
};
} else {
results[value.name] = {
bindingPropertyName: value.alias || value.name,
classPropertyName: value.name,
required: value.required || false,
isSignal: false,
transformFunction: value.transform != null ? new WrappedNodeExpr(value.transform) : null
};
}
return results;
}, {});
}
function parseMappingStringArray(values) {
return values.reduce((results, value) => {
const [alias, fieldName] = parseMappingString(value);
results[fieldName] = alias;
return results;
}, {});
}
function parseMappingString(value) {
const [fieldName, bindingPropertyName] = value.split(':', 2).map(str => str.trim());
return [bindingPropertyName ?? fieldName, fieldName];
}
function convertDeclarePipeFacadeToMetadata(declaration) {
return {
name: declaration.type.name,
type: wrapReference(declaration.type),
typeArgumentCount: 0,
pipeName: declaration.name,
deps: null,
pure: declaration.pure ?? true,
isStandalone: declaration.isStandalone ?? getJitStandaloneDefaultForVersion(declaration.version)
};
}
function convertDeclareInjectorFacadeToMetadata(declaration) {
return {
name: declaration.type.name,
type: wrapReference(declaration.type),
providers: declaration.providers !== undefined && declaration.providers.length > 0 ? new WrappedNodeExpr(declaration.providers) : null,
imports: declaration.imports !== undefined ? declaration.imports.map(i => new WrappedNodeExpr(i)) : []
};
}
function publishFacade(global) {
const ng = global.ng || (global.ng = {});
ng.ɵcompilerFacade = new CompilerFacadeImpl();
}
class CompilerConfig {
defaultEncapsulation;
preserveWhitespaces;
strictInjectionParameters;
constructor({
defaultEncapsulation = ViewEncapsulation$1.Emulated,
preserveWhitespaces,
strictInjectionParameters
} = {}) {
this.defaultEncapsulation = defaultEncapsulation;
this.preserveWhitespaces = preserveWhitespacesDefault(noUndefined(preserveWhitespaces));
this.strictInjectionParameters = strictInjectionParameters === true;
}
}
function preserveWhitespacesDefault(preserveWhitespacesOption, defaultSetting = false) {
return preserveWhitespacesOption === null ? defaultSetting : preserveWhitespacesOption;
}
const _I18N_ATTR = 'i18n';
const _I18N_ATTR_PREFIX = 'i18n-';
const _I18N_COMMENT_PREFIX_REGEXP = /^i18n:?/;
const MEANING_SEPARATOR = '|';
const ID_SEPARATOR = '@@';
let i18nCommentsWarned = false;
function extractMessages(nodes, implicitTags, implicitAttrs, preserveSignificantWhitespace) {
const visitor = new _Visitor(implicitTags, implicitAttrs, preserveSignificantWhitespace);
return visitor.extract(nodes);
}
function mergeTranslations(nodes, translations, implicitTags, implicitAttrs) {
const visitor = new _Visitor(implicitTags, implicitAttrs);
return visitor.merge(nodes, translations);
}
class ExtractionResult {
messages;
errors;
constructor(messages, errors) {
this.messages = messages;
this.errors = errors;
}
}
var _VisitorMode;
(function (_VisitorMode) {
_VisitorMode[_VisitorMode["Extract"] = 0] = "Extract";
_VisitorMode[_VisitorMode["Merge"] = 1] = "Merge";
})(_VisitorMode || (_VisitorMode = {}));
class _Visitor {
_implicitTags;
_implicitAttrs;
_preserveSignificantWhitespace;
_depth;
_inI18nNode;
_inImplicitNode;
_inI18nBlock;
_blockMeaningAndDesc;
_blockChildren;
_blockStartDepth;
_inIcu;
_msgCountAtSectionStart;
_errors;
_mode;
_messages;
_translations;
_createI18nMessage;
constructor(_implicitTags, _implicitAttrs, _preserveSignificantWhitespace = true) {
this._implicitTags = _implicitTags;
this._implicitAttrs = _implicitAttrs;
this._preserveSignificantWhitespace = _preserveSignificantWhitespace;
}
extract(nodes) {
this._init(_VisitorMode.Extract);
nodes.forEach(node => node.visit(this, null));
if (this._inI18nBlock) {
this._reportError(nodes[nodes.length - 1], 'Unclosed block');
}
return new ExtractionResult(this._messages, this._errors);
}
merge(nodes, translations) {
this._init(_VisitorMode.Merge);
this._translations = translations;
const wrapper = new Element('wrapper', [], [], nodes, false, undefined, undefined, undefined, false);
const translatedNode = wrapper.visit(this, null);
if (this._inI18nBlock) {
this._reportError(nodes[nodes.length - 1], 'Unclosed block');
}
return new ParseTreeResult(translatedNode.children, this._errors);
}
visitExpansionCase(icuCase, context) {
const expression = visitAll(this, icuCase.expression, context);
if (this._mode === _VisitorMode.Merge) {
return new ExpansionCase(icuCase.value, expression, icuCase.sourceSpan, icuCase.valueSourceSpan, icuCase.expSourceSpan);
}
}
visitExpansion(icu, context) {
this._mayBeAddBlockChildren(icu);
const wasInIcu = this._inIcu;
if (!this._inIcu) {
if (this._isInTranslatableSection) {
this._addMessage([icu]);
}
this._inIcu = true;
}
const cases = visitAll(this, icu.cases, context);
if (this._mode === _VisitorMode.Merge) {
icu = new Expansion(icu.switchValue, icu.type, cases, icu.sourceSpan, icu.switchValueSourceSpan);
}
this._inIcu = wasInIcu;
return icu;
}
visitComment(comment, context) {
const isOpening = _isOpeningComment(comment);
if (isOpening && this._isInTranslatableSection) {
this._reportError(comment, 'Could not start a block inside a translatable section');
return;
}
const isClosing = _isClosingComment(comment);
if (isClosing && !this._inI18nBlock) {
this._reportError(comment, 'Trying to close an unopened block');
return;
}
if (!this._inI18nNode && !this._inIcu) {
if (!this._inI18nBlock) {
if (isOpening) {
if (!i18nCommentsWarned && console && console.warn) {
i18nCommentsWarned = true;
const details = comment.sourceSpan.details ? `, ${comment.sourceSpan.details}` : '';
console.warn(`I18n comments are deprecated, use an <ng-container> element instead (${comment.sourceSpan.start}${details})`);
}
this._inI18nBlock = true;
this._blockStartDepth = this._depth;
this._blockChildren = [];
this._blockMeaningAndDesc = comment.value.replace(_I18N_COMMENT_PREFIX_REGEXP, '').trim();
this._openTranslatableSection(comment);
}
} else {
if (isClosing) {
if (this._depth == this._blockStartDepth) {
this._closeTranslatableSection(comment, this._blockChildren);
this._inI18nBlock = false;
const message = this._addMessage(this._blockChildren, this._blockMeaningAndDesc);
const nodes = this._translateMessage(comment, message);
return visitAll(this, nodes);
} else {
this._reportError(comment, 'I18N blocks should not cross element boundaries');
return;
}
}
}
}
}
visitText(text, context) {
if (this._isInTranslatableSection) {
this._mayBeAddBlockChildren(text);
}
return text;
}
visitElement(el, context) {
return this._visitElementLike(el, context);
}
visitAttribute(attribute, context) {
throw new Error('unreachable code');
}
visitBlock(block, context) {
visitAll(this, block.children, context);
}
visitBlockParameter(parameter, context) {}
visitLetDeclaration(decl, context) {}
visitComponent(component, context) {
return this._visitElementLike(component, context);
}
visitDirective(directive, context) {
throw new Error('unreachable code');
}
_init(mode) {
this._mode = mode;
this._inI18nBlock = false;
this._inI18nNode = false;
this._depth = 0;
this._inIcu = false;
this._msgCountAtSectionStart = undefined;
this._errors = [];
this._messages = [];
this._inImplicitNode = false;
this._createI18nMessage = createI18nMessageFactory(!this._preserveSignificantWhitespace, this._preserveSignificantWhitespace);
}
_visitElementLike(node, context) {
this._mayBeAddBlockChildren(node);
this._depth++;
const wasInI18nNode = this._inI18nNode;
const wasInImplicitNode = this._inImplicitNode;
let childNodes = [];
let translatedChildNodes = undefined;
const nodeName = node instanceof Component ? node.tagName : node.name;
const i18nAttr = _getI18nAttr(node);
const i18nMeta = i18nAttr ? i18nAttr.value : '';
const isImplicit = this._implicitTags.some(tag => nodeName === tag) && !this._inIcu && !this._isInTranslatableSection;
const isTopLevelImplicit = !wasInImplicitNode && isImplicit;
this._inImplicitNode = wasInImplicitNode || isImplicit;
if (!this._isInTranslatableSection && !this._inIcu) {
if (i18nAttr || isTopLevelImplicit) {
this._inI18nNode = true;
const message = this._addMessage(node.children, i18nMeta);
translatedChildNodes = this._translateMessage(node, message);
}
if (this._mode == _VisitorMode.Extract) {
const isTranslatable = i18nAttr || isTopLevelImplicit;
if (isTranslatable) this._openTranslatableSection(node);
visitAll(this, node.children);
if (isTranslatable) this._closeTranslatableSection(node, node.children);
}
} else {
if (i18nAttr || isTopLevelImplicit) {
this._reportError(node, 'Could not mark an element as translatable inside a translatable section');
}
if (this._mode == _VisitorMode.Extract) {
visitAll(this, node.children);
}
}
if (this._mode === _VisitorMode.Merge) {
const visitNodes = translatedChildNodes || node.children;
visitNodes.forEach(child => {
const visited = child.visit(this, context);
if (visited && !this._isInTranslatableSection) {
childNodes = childNodes.concat(visited);
}
});
}
this._visitAttributesOf(node);
this._depth--;
this._inI18nNode = wasInI18nNode;
this._inImplicitNode = wasInImplicitNode;
if (this._mode === _VisitorMode.Merge) {
if (node instanceof Element) {
return new Element(node.name, this._translateAttributes(node), this._translateDirectives(node), childNodes, node.isSelfClosing, node.sourceSpan, node.startSourceSpan, node.endSourceSpan, node.isVoid);
} else {
return new Component(node.componentName, node.tagName, node.fullName, this._translateAttributes(node), this._translateDirectives(node), childNodes, node.isSelfClosing, node.sourceSpan, node.startSourceSpan, node.endSourceSpan);
}
}
return null;
}
_visitAttributesOf(el) {
const explicitAttrNameToValue = {};
const implicitAttrNames = this._implicitAttrs[el instanceof Component ? el.tagName || '' : el.name] || [];
el.attrs.filter(attr => attr instanceof Attribute && attr.name.startsWith(_I18N_ATTR_PREFIX)).forEach(attr => {
explicitAttrNameToValue[attr.name.slice(_I18N_ATTR_PREFIX.length)] = attr.value;
});
el.attrs.forEach(attr => {
if (attr.name in explicitAttrNameToValue) {
this._addMessage([attr], explicitAttrNameToValue[attr.name]);
} else if (implicitAttrNames.some(name => attr.name === name)) {
this._addMessage([attr]);
}
});
}
_addMessage(ast, msgMeta) {
if (ast.length == 0 || this._isEmptyAttributeValue(ast) || this._isPlaceholderOnlyAttributeValue(ast) || this._isPlaceholderOnlyMessage(ast)) {
return null;
}
const {
meaning,
description,
id
} = _parseMessageMeta(msgMeta);
const message = this._createI18nMessage(ast, meaning, description, id);
this._messages.push(message);
return message;
}
_isEmptyAttributeValue(ast) {
if (!isAttrNode(ast)) return false;
const node = ast[0];
return node.value.trim() === '';
}
_isPlaceholderOnlyAttributeValue(ast) {
if (!isAttrNode(ast)) return false;
const tokens = ast[0].valueTokens ?? [];
const interpolations = tokens.filter(token => token.type === 17);
const plainText = tokens.filter(token => token.type === 16).map(token => token.parts[0].trim()).join('');
return interpolations.length === 1 && plainText === '';
}
_isPlaceholderOnlyMessage(ast) {
if (!isTextNode(ast)) return false;
const tokens = ast[0].tokens;
const interpolations = tokens.filter(token => token.type === 8);
const plainText = tokens.filter(token => token.type === 5).map(token => token.parts[0].trim()).join('');
return interpolations.length === 1 && plainText === '';
}
_translateMessage(el, message) {
if (message && this._mode === _VisitorMode.Merge) {
const nodes = this._translations.get(message);
if (nodes) {
return nodes;
}
this._reportError(el, `Translation unavailable for message id="${this._translations.digest(message)}"`);
}
return [];
}
_translateAttributes(node) {
const i18nParsedMessageMeta = {};
const translatedAttributes = [];
node.attrs.forEach(attr => {
if (attr.name.startsWith(_I18N_ATTR_PREFIX)) {
i18nParsedMessageMeta[attr.name.slice(_I18N_ATTR_PREFIX.length)] = _parseMessageMeta(attr.value);
}
});
node.attrs.forEach(attr => {
if (attr.name === _I18N_ATTR || attr.name.startsWith(_I18N_ATTR_PREFIX)) {
return;
}
if (attr.value && attr.value != '' && i18nParsedMessageMeta.hasOwnProperty(attr.name)) {
const {
meaning,
description,
id
} = i18nParsedMessageMeta[attr.name];
const message = this._createI18nMessage([attr], meaning, description, id);
const nodes = this._translations.get(message);
if (nodes) {
if (nodes.length == 0) {
translatedAttributes.push(new Attribute(attr.name, '', attr.sourceSpan, undefined, undefined, undefined, undefined));
} else if (nodes[0] instanceof Text) {
const value = nodes[0].value;
translatedAttributes.push(new Attribute(attr.name, value, attr.sourceSpan, undefined, undefined, undefined, undefined));
} else {
this._reportError(node, `Unexpected translation for attribute "${attr.name}" (id="${id || this._translations.digest(message)}")`);
}
} else {
this._reportError(node, `Translation unavailable for attribute "${attr.name}" (id="${id || this._translations.digest(message)}")`);
}
} else {
translatedAttributes.push(attr);
}
});
return translatedAttributes;
}
_translateDirectives(node) {
return node.directives.map(dir => new Directive(dir.name, this._translateAttributes(dir), dir.sourceSpan, dir.startSourceSpan, dir.endSourceSpan));
}
_mayBeAddBlockChildren(node) {
if (this._inI18nBlock && !this._inIcu && this._depth == this._blockStartDepth) {
this._blockChildren.push(node);
}
}
_openTranslatableSection(node) {
if (this._isInTranslatableSection) {
this._reportError(node, 'Unexpected section start');
} else {
this._msgCountAtSectionStart = this._messages.length;
}
}
get _isInTranslatableSection() {
return this._msgCountAtSectionStart !== void 0;
}
_closeTranslatableSection(node, directChildren) {
if (!this._isInTranslatableSection) {
this._reportError(node, 'Unexpected section end');
return;
}
const startIndex = this._msgCountAtSectionStart;
const significantChildren = directChildren.reduce((count, node) => count + (node instanceof Comment ? 0 : 1), 0);
if (significantChildren == 1) {
for (let i = this._messages.length - 1; i >= startIndex; i--) {
const ast = this._messages[i].nodes;
if (!(ast.length == 1 && ast[0] instanceof Text$2)) {
this._messages.splice(i, 1);
break;
}
}
}
this._msgCountAtSectionStart = undefined;
}
_reportError(node, msg) {
this._errors.push(new ParseError(node.sourceSpan, msg));
}
}
function _isOpeningComment(n) {
return !!(n instanceof Comment && n.value && n.value.startsWith('i18n'));
}
function _isClosingComment(n) {
return !!(n instanceof Comment && n.value && n.value === '/i18n');
}
function _getI18nAttr(p) {
return p.attrs.find(attr => attr instanceof Attribute && attr.name === _I18N_ATTR) || null;
}
function _parseMessageMeta(i18n) {
if (!i18n) return {
meaning: '',
description: '',
id: ''
};
const idIndex = i18n.indexOf(ID_SEPARATOR);
const descIndex = i18n.indexOf(MEANING_SEPARATOR);
const [meaningAndDesc, id] = idIndex > -1 ? [i18n.slice(0, idIndex), i18n.slice(idIndex + 2)] : [i18n, ''];
const [meaning, description] = descIndex > -1 ? [meaningAndDesc.slice(0, descIndex), meaningAndDesc.slice(descIndex + 1)] : ['', meaningAndDesc];
return {
meaning,
description,
id: id.trim()
};
}
function isTextNode(ast) {
return ast.length === 1 && ast[0] instanceof Text;
}
function isAttrNode(ast) {
return ast.length === 1 && ast[0] instanceof Attribute;
}
class XmlTagDefinition {
closedByParent = false;
implicitNamespacePrefix = null;
isVoid = false;
ignoreFirstLf = false;
canSelfClose = true;
preventNamespaceInheritance = false;
requireExtraParent(currentParent) {
return false;
}
isClosedByChild(name) {
return false;
}
getContentType() {
return TagContentType.PARSABLE_DATA;
}
}
const _TAG_DEFINITION = new XmlTagDefinition();
function getXmlTagDefinition(tagName) {
return _TAG_DEFINITION;
}
class XmlParser extends Parser$1 {
constructor() {
super(getXmlTagDefinition);
}
parse(source, url, options = {}) {
return super.parse(source, url, {
...options,
tokenizeBlocks: false,
tokenizeLet: false,
selectorlessEnabled: false
});
}
}
const _VERSION$1 = '1.2';
const _XMLNS$1 = 'urn:oasis:names:tc:xliff:document:1.2';
const _DEFAULT_SOURCE_LANG$1 = 'en';
const _PLACEHOLDER_TAG$2 = 'x';
const _MARKER_TAG$1 = 'mrk';
const _FILE_TAG = 'file';
const _SOURCE_TAG$1 = 'source';
const _SEGMENT_SOURCE_TAG = 'seg-source';
const _ALT_TRANS_TAG = 'alt-trans';
const _TARGET_TAG$1 = 'target';
const _UNIT_TAG$1 = 'trans-unit';
const _CONTEXT_GROUP_TAG = 'context-group';
const _CONTEXT_TAG = 'context';
class Xliff extends Serializer {
write(messages, locale) {
const visitor = new _WriteVisitor$1();
const transUnits = [];
messages.forEach(message => {
let contextTags = [];
message.sources.forEach(source => {
let contextGroupTag = new Tag(_CONTEXT_GROUP_TAG, {
purpose: 'location'
});
contextGroupTag.children.push(new CR(10), new Tag(_CONTEXT_TAG, {
'context-type': 'sourcefile'
}, [new Text$1(source.filePath)]), new CR(10), new Tag(_CONTEXT_TAG, {
'context-type': 'linenumber'
}, [new Text$1(`${source.startLine}`)]), new CR(8));
contextTags.push(new CR(8), contextGroupTag);
});
const transUnit = new Tag(_UNIT_TAG$1, {
id: message.id,
datatype: 'html'
});
transUnit.children.push(new CR(8), new Tag(_SOURCE_TAG$1, {}, visitor.serialize(message.nodes)), ...contextTags);
if (message.description) {
transUnit.children.push(new CR(8), new Tag('note', {
priority: '1',
from: 'description'
}, [new Text$1(message.description)]));
}
if (message.meaning) {
transUnit.children.push(new CR(8), new Tag('note', {
priority: '1',
from: 'meaning'
}, [new Text$1(message.meaning)]));
}
transUnit.children.push(new CR(6));
transUnits.push(new CR(6), transUnit);
});
const body = new Tag('body', {}, [...transUnits, new CR(4)]);
const file = new Tag('file', {
'source-language': locale || _DEFAULT_SOURCE_LANG$1,
datatype: 'plaintext',
original: 'ng2.template'
}, [new CR(4), body, new CR(2)]);
const xliff = new Tag('xliff', {
version: _VERSION$1,
xmlns: _XMLNS$1
}, [new CR(2), file, new CR()]);
return serialize$1([new Declaration({
version: '1.0',
encoding: 'UTF-8'
}), new CR(), xliff, new CR()]);
}
load(content, url) {
const xliffParser = new XliffParser();
const {
locale,
msgIdToHtml,
errors
} = xliffParser.parse(content, url);
const i18nNodesByMsgId = {};
const converter = new XmlToI18n$2();
Object.keys(msgIdToHtml).forEach(msgId => {
const {
i18nNodes,
errors: e
} = converter.convert(msgIdToHtml[msgId], url);
errors.push(...e);
i18nNodesByMsgId[msgId] = i18nNodes;
});
if (errors.length) {
throw new Error(`xliff parse errors:\n${errors.join('\n')}`);
}
return {
locale: locale,
i18nNodesByMsgId
};
}
digest(message) {
return digest$1(message);
}
}
let _WriteVisitor$1 = class _WriteVisitor {
visitText(text, context) {
return [new Text$1(text.value)];
}
visitContainer(container, context) {
const nodes = [];
container.children.forEach(node => nodes.push(...node.visit(this)));
return nodes;
}
visitIcu(icu, context) {
const nodes = [new Text$1(`{${icu.expressionPlaceholder}, ${icu.type}, `)];
Object.keys(icu.cases).forEach(c => {
nodes.push(new Text$1(`${c} {`), ...icu.cases[c].visit(this), new Text$1(`} `));
});
nodes.push(new Text$1(`}`));
return nodes;
}
visitTagPlaceholder(ph, context) {
const ctype = getCtypeForTag(ph.tag);
if (ph.isVoid) {
return [new Tag(_PLACEHOLDER_TAG$2, {
id: ph.startName,
ctype,
'equiv-text': `<${ph.tag}/>`
})];
}
const startTagPh = new Tag(_PLACEHOLDER_TAG$2, {
id: ph.startName,
ctype,
'equiv-text': `<${ph.tag}>`
});
const closeTagPh = new Tag(_PLACEHOLDER_TAG$2, {
id: ph.closeName,
ctype,
'equiv-text': `</${ph.tag}>`
});
return [startTagPh, ...this.serialize(ph.children), closeTagPh];
}
visitPlaceholder(ph, context) {
return [new Tag(_PLACEHOLDER_TAG$2, {
id: ph.name,
'equiv-text': `{{${ph.value}}}`
})];
}
visitBlockPlaceholder(ph, context) {
const ctype = `x-${ph.name.toLowerCase().replace(/[^a-z0-9]/g, '-')}`;
const startTagPh = new Tag(_PLACEHOLDER_TAG$2, {
id: ph.startName,
ctype,
'equiv-text': `@${ph.name}`
});
const closeTagPh = new Tag(_PLACEHOLDER_TAG$2, {
id: ph.closeName,
ctype,
'equiv-text': `}`
});
return [startTagPh, ...this.serialize(ph.children), closeTagPh];
}
visitIcuPlaceholder(ph, context) {
const equivText = `{${ph.value.expression}, ${ph.value.type}, ${Object.keys(ph.value.cases).map(value => value + ' {...}').join(' ')}}`;
return [new Tag(_PLACEHOLDER_TAG$2, {
id: ph.name,
'equiv-text': equivText
})];
}
serialize(nodes) {
return [].concat(...nodes.map(node => node.visit(this)));
}
};
class XliffParser {
_unitMlString;
_errors;
_msgIdToHtml;
_locale = null;
parse(xliff, url) {
this._unitMlString = null;
this._msgIdToHtml = {};
const xml = new XmlParser().parse(xliff, url);
this._errors = xml.errors;
visitAll(this, xml.rootNodes, null);
return {
msgIdToHtml: this._msgIdToHtml,
errors: this._errors,
locale: this._locale
};
}
visitElement(element, context) {
switch (element.name) {
case _UNIT_TAG$1:
this._unitMlString = null;
const idAttr = element.attrs.find(attr => attr.name === 'id');
if (!idAttr) {
this._addError(element, `<${_UNIT_TAG$1}> misses the "id" attribute`);
} else {
const id = idAttr.value;
if (this._msgIdToHtml.hasOwnProperty(id)) {
this._addError(element, `Duplicated translations for msg ${id}`);
} else {
visitAll(this, element.children, null);
if (typeof this._unitMlString === 'string') {
this._msgIdToHtml[id] = this._unitMlString;
} else {
this._addError(element, `Message ${id} misses a translation`);
}
}
}
break;
case _SOURCE_TAG$1:
case _SEGMENT_SOURCE_TAG:
case _ALT_TRANS_TAG:
break;
case _TARGET_TAG$1:
const innerTextStart = element.startSourceSpan.end.offset;
const innerTextEnd = element.endSourceSpan.start.offset;
const content = element.startSourceSpan.start.file.content;
const innerText = content.slice(innerTextStart, innerTextEnd);
this._unitMlString = innerText;
break;
case _FILE_TAG:
const localeAttr = element.attrs.find(attr => attr.name === 'target-language');
if (localeAttr) {
this._locale = localeAttr.value;
}
visitAll(this, element.children, null);
break;
default:
visitAll(this, element.children, null);
}
}
visitAttribute(attribute, context) {}
visitText(text, context) {}
visitComment(comment, context) {}
visitExpansion(expansion, context) {}
visitExpansionCase(expansionCase, context) {}
visitBlock(block, context) {}
visitBlockParameter(parameter, context) {}
visitLetDeclaration(decl, context) {}
visitComponent(component, context) {}
visitDirective(directive, context) {}
_addError(node, message) {
this._errors.push(new ParseError(node.sourceSpan, message));
}
}
let XmlToI18n$2 = class XmlToI18n {
_errors;
convert(message, url) {
const xmlIcu = new XmlParser().parse(message, url, {
tokenizeExpansionForms: true
});
this._errors = xmlIcu.errors;
const i18nNodes = this._errors.length > 0 || xmlIcu.rootNodes.length == 0 ? [] : [].concat(...visitAll(this, xmlIcu.rootNodes));
return {
i18nNodes: i18nNodes,
errors: this._errors
};
}
visitText(text, context) {
return new Text$2(text.value, text.sourceSpan);
}
visitElement(el, context) {
if (el.name === _PLACEHOLDER_TAG$2) {
const nameAttr = el.attrs.find(attr => attr.name === 'id');
if (nameAttr) {
return new Placeholder('', nameAttr.value, el.sourceSpan);
}
this._addError(el, `<${_PLACEHOLDER_TAG$2}> misses the "id" attribute`);
return null;
}
if (el.name === _MARKER_TAG$1) {
return [].concat(...visitAll(this, el.children));
}
this._addError(el, `Unexpected tag`);
return null;
}
visitExpansion(icu, context) {
const caseMap = {};
visitAll(this, icu.cases).forEach(c => {
caseMap[c.value] = new Container(c.nodes, icu.sourceSpan);
});
return new Icu(icu.switchValue, icu.type, caseMap, icu.sourceSpan);
}
visitExpansionCase(icuCase, context) {
return {
value: icuCase.value,
nodes: visitAll(this, icuCase.expression)
};
}
visitComment(comment, context) {}
visitAttribute(attribute, context) {}
visitBlock(block, context) {}
visitBlockParameter(parameter, context) {}
visitLetDeclaration(decl, context) {}
visitComponent(component, context) {
this._addError(component, 'Unexpected node');
}
visitDirective(directive, context) {
this._addError(directive, 'Unexpected node');
}
_addError(node, message) {
this._errors.push(new ParseError(node.sourceSpan, message));
}
};
function getCtypeForTag(tag) {
switch (tag.toLowerCase()) {
case 'br':
return 'lb';
case 'img':
return 'image';
default:
return `x-${tag}`;
}
}
const _VERSION = '2.0';
const _XMLNS = 'urn:oasis:names:tc:xliff:document:2.0';
const _DEFAULT_SOURCE_LANG = 'en';
const _PLACEHOLDER_TAG$1 = 'ph';
const _PLACEHOLDER_SPANNING_TAG = 'pc';
const _MARKER_TAG = 'mrk';
const _XLIFF_TAG = 'xliff';
const _SOURCE_TAG = 'source';
const _TARGET_TAG = 'target';
const _UNIT_TAG = 'unit';
class Xliff2 extends Serializer {
write(messages, locale) {
const visitor = new _WriteVisitor();
const units = [];
messages.forEach(message => {
const unit = new Tag(_UNIT_TAG, {
id: message.id
});
const notes = new Tag('notes');
if (message.description || message.meaning) {
if (message.description) {
notes.children.push(new CR(8), new Tag('note', {
category: 'description'
}, [new Text$1(message.description)]));
}
if (message.meaning) {
notes.children.push(new CR(8), new Tag('note', {
category: 'meaning'
}, [new Text$1(message.meaning)]));
}
}
message.sources.forEach(source => {
notes.children.push(new CR(8), new Tag('note', {
category: 'location'
}, [new Text$1(`${source.filePath}:${source.startLine}${source.endLine !== source.startLine ? ',' + source.endLine : ''}`)]));
});
notes.children.push(new CR(6));
unit.children.push(new CR(6), notes);
const segment = new Tag('segment');
segment.children.push(new CR(8), new Tag(_SOURCE_TAG, {}, visitor.serialize(message.nodes)), new CR(6));
unit.children.push(new CR(6), segment, new CR(4));
units.push(new CR(4), unit);
});
const file = new Tag('file', {
'original': 'ng.template',
id: 'ngi18n'
}, [...units, new CR(2)]);
const xliff = new Tag(_XLIFF_TAG, {
version: _VERSION,
xmlns: _XMLNS,
srcLang: locale || _DEFAULT_SOURCE_LANG
}, [new CR(2), file, new CR()]);
return serialize$1([new Declaration({
version: '1.0',
encoding: 'UTF-8'
}), new CR(), xliff, new CR()]);
}
load(content, url) {
const xliff2Parser = new Xliff2Parser();
const {
locale,
msgIdToHtml,
errors
} = xliff2Parser.parse(content, url);
const i18nNodesByMsgId = {};
const converter = new XmlToI18n$1();
Object.keys(msgIdToHtml).forEach(msgId => {
const {
i18nNodes,
errors: e
} = converter.convert(msgIdToHtml[msgId], url);
errors.push(...e);
i18nNodesByMsgId[msgId] = i18nNodes;
});
if (errors.length) {
throw new Error(`xliff2 parse errors:\n${errors.join('\n')}`);
}
return {
locale: locale,
i18nNodesByMsgId
};
}
digest(message) {
return decimalDigest(message);
}
}
class _WriteVisitor {
_nextPlaceholderId = 0;
visitText(text, context) {
return [new Text$1(text.value)];
}
visitContainer(container, context) {
const nodes = [];
container.children.forEach(node => nodes.push(...node.visit(this)));
return nodes;
}
visitIcu(icu, context) {
const nodes = [new Text$1(`{${icu.expressionPlaceholder}, ${icu.type}, `)];
Object.keys(icu.cases).forEach(c => {
nodes.push(new Text$1(`${c} {`), ...icu.cases[c].visit(this), new Text$1(`} `));
});
nodes.push(new Text$1(`}`));
return nodes;
}
visitTagPlaceholder(ph, context) {
const type = getTypeForTag(ph.tag);
if (ph.isVoid) {
const tagPh = new Tag(_PLACEHOLDER_TAG$1, {
id: (this._nextPlaceholderId++).toString(),
equiv: ph.startName,
type: type,
disp: `<${ph.tag}/>`
});
return [tagPh];
}
const tagPc = new Tag(_PLACEHOLDER_SPANNING_TAG, {
id: (this._nextPlaceholderId++).toString(),
equivStart: ph.startName,
equivEnd: ph.closeName,
type: type,
dispStart: `<${ph.tag}>`,
dispEnd: `</${ph.tag}>`
});
const nodes = [].concat(...ph.children.map(node => node.visit(this)));
if (nodes.length) {
nodes.forEach(node => tagPc.children.push(node));
} else {
tagPc.children.push(new Text$1(''));
}
return [tagPc];
}
visitPlaceholder(ph, context) {
const idStr = (this._nextPlaceholderId++).toString();
return [new Tag(_PLACEHOLDER_TAG$1, {
id: idStr,
equiv: ph.name,
disp: `{{${ph.value}}}`
})];
}
visitBlockPlaceholder(ph, context) {
const tagPc = new Tag(_PLACEHOLDER_SPANNING_TAG, {
id: (this._nextPlaceholderId++).toString(),
equivStart: ph.startName,
equivEnd: ph.closeName,
type: 'other',
dispStart: `@${ph.name}`,
dispEnd: `}`
});
const nodes = [].concat(...ph.children.map(node => node.visit(this)));
if (nodes.length) {
nodes.forEach(node => tagPc.children.push(node));
} else {
tagPc.children.push(new Text$1(''));
}
return [tagPc];
}
visitIcuPlaceholder(ph, context) {
const cases = Object.keys(ph.value.cases).map(value => value + ' {...}').join(' ');
const idStr = (this._nextPlaceholderId++).toString();
return [new Tag(_PLACEHOLDER_TAG$1, {
id: idStr,
equiv: ph.name,
disp: `{${ph.value.expression}, ${ph.value.type}, ${cases}}`
})];
}
serialize(nodes) {
this._nextPlaceholderId = 0;
return [].concat(...nodes.map(node => node.visit(this)));
}
}
class Xliff2Parser {
_unitMlString;
_errors;
_msgIdToHtml;
_locale = null;
parse(xliff, url) {
this._unitMlString = null;
this._msgIdToHtml = {};
const xml = new XmlParser().parse(xliff, url);
this._errors = xml.errors;
visitAll(this, xml.rootNodes, null);
return {
msgIdToHtml: this._msgIdToHtml,
errors: this._errors,
locale: this._locale
};
}
visitElement(element, context) {
switch (element.name) {
case _UNIT_TAG:
this._unitMlString = null;
const idAttr = element.attrs.find(attr => attr.name === 'id');
if (!idAttr) {
this._addError(element, `<${_UNIT_TAG}> misses the "id" attribute`);
} else {
const id = idAttr.value;
if (this._msgIdToHtml.hasOwnProperty(id)) {
this._addError(element, `Duplicated translations for msg ${id}`);
} else {
visitAll(this, element.children, null);
if (typeof this._unitMlString === 'string') {
this._msgIdToHtml[id] = this._unitMlString;
} else {
this._addError(element, `Message ${id} misses a translation`);
}
}
}
break;
case _SOURCE_TAG:
break;
case _TARGET_TAG:
const innerTextStart = element.startSourceSpan.end.offset;
const innerTextEnd = element.endSourceSpan.start.offset;
const content = element.startSourceSpan.start.file.content;
const innerText = content.slice(innerTextStart, innerTextEnd);
this._unitMlString = innerText;
break;
case _XLIFF_TAG:
const localeAttr = element.attrs.find(attr => attr.name === 'trgLang');
if (localeAttr) {
this._locale = localeAttr.value;
}
const versionAttr = element.attrs.find(attr => attr.name === 'version');
if (versionAttr) {
const version = versionAttr.value;
if (version !== '2.0') {
this._addError(element, `The XLIFF file version ${version} is not compatible with XLIFF 2.0 serializer`);
} else {
visitAll(this, element.children, null);
}
}
break;
default:
visitAll(this, element.children, null);
}
}
visitAttribute(attribute, context) {}
visitText(text, context) {}
visitComment(comment, context) {}
visitExpansion(expansion, context) {}
visitExpansionCase(expansionCase, context) {}
visitBlock(block, context) {}
visitBlockParameter(parameter, context) {}
visitLetDeclaration(decl, context) {}
visitComponent(component, context) {}
visitDirective(directive, context) {}
_addError(node, message) {
this._errors.push(new ParseError(node.sourceSpan, message));
}
}
let XmlToI18n$1 = class XmlToI18n {
_errors;
convert(message, url) {
const xmlIcu = new XmlParser().parse(message, url, {
tokenizeExpansionForms: true
});
this._errors = xmlIcu.errors;
const i18nNodes = this._errors.length > 0 || xmlIcu.rootNodes.length == 0 ? [] : [].concat(...visitAll(this, xmlIcu.rootNodes));
return {
i18nNodes,
errors: this._errors
};
}
visitText(text, context) {
return new Text$2(text.value, text.sourceSpan);
}
visitElement(el, context) {
switch (el.name) {
case _PLACEHOLDER_TAG$1:
const nameAttr = el.attrs.find(attr => attr.name === 'equiv');
if (nameAttr) {
return [new Placeholder('', nameAttr.value, el.sourceSpan)];
}
this._addError(el, `<${_PLACEHOLDER_TAG$1}> misses the "equiv" attribute`);
break;
case _PLACEHOLDER_SPANNING_TAG:
const startAttr = el.attrs.find(attr => attr.name === 'equivStart');
const endAttr = el.attrs.find(attr => attr.name === 'equivEnd');
if (!startAttr) {
this._addError(el, `<${_PLACEHOLDER_TAG$1}> misses the "equivStart" attribute`);
} else if (!endAttr) {
this._addError(el, `<${_PLACEHOLDER_TAG$1}> misses the "equivEnd" attribute`);
} else {
const startId = startAttr.value;
const endId = endAttr.value;
const nodes = [];
return nodes.concat(new Placeholder('', startId, el.sourceSpan), ...el.children.map(node => node.visit(this, null)), new Placeholder('', endId, el.sourceSpan));
}
break;
case _MARKER_TAG:
return [].concat(...visitAll(this, el.children));
default:
this._addError(el, `Unexpected tag`);
}
return null;
}
visitExpansion(icu, context) {
const caseMap = {};
visitAll(this, icu.cases).forEach(c => {
caseMap[c.value] = new Container(c.nodes, icu.sourceSpan);
});
return new Icu(icu.switchValue, icu.type, caseMap, icu.sourceSpan);
}
visitExpansionCase(icuCase, context) {
return {
value: icuCase.value,
nodes: [].concat(...visitAll(this, icuCase.expression))
};
}
visitComment(comment, context) {}
visitAttribute(attribute, context) {}
visitBlock(block, context) {}
visitBlockParameter(parameter, context) {}
visitLetDeclaration(decl, context) {}
visitComponent(component, context) {
this._addError(component, 'Unexpected node');
}
visitDirective(directive, context) {
this._addError(directive, 'Unexpected node');
}
_addError(node, message) {
this._errors.push(new ParseError(node.sourceSpan, message));
}
};
function getTypeForTag(tag) {
switch (tag.toLowerCase()) {
case 'br':
case 'b':
case 'i':
case 'u':
return 'fmt';
case 'img':
return 'image';
case 'a':
return 'link';
default:
return 'other';
}
}
const _TRANSLATIONS_TAG = 'translationbundle';
const _TRANSLATION_TAG = 'translation';
const _PLACEHOLDER_TAG = 'ph';
class Xtb extends Serializer {
write(messages, locale) {
throw new Error('Unsupported');
}
load(content, url) {
const xtbParser = new XtbParser();
const {
locale,
msgIdToHtml,
errors
} = xtbParser.parse(content, url);
const i18nNodesByMsgId = {};
const converter = new XmlToI18n();
Object.keys(msgIdToHtml).forEach(msgId => {
const valueFn = function () {
const {
i18nNodes,
errors
} = converter.convert(msgIdToHtml[msgId], url);
if (errors.length) {
throw new Error(`xtb parse errors:\n${errors.join('\n')}`);
}
return i18nNodes;
};
createLazyProperty(i18nNodesByMsgId, msgId, valueFn);
});
if (errors.length) {
throw new Error(`xtb parse errors:\n${errors.join('\n')}`);
}
return {
locale: locale,
i18nNodesByMsgId
};
}
digest(message) {
return digest(message);
}
createNameMapper(message) {
return new SimplePlaceholderMapper(message, toPublicName);
}
}
function createLazyProperty(messages, id, valueFn) {
Object.defineProperty(messages, id, {
configurable: true,
enumerable: true,
get: function () {
const value = valueFn();
Object.defineProperty(messages, id, {
enumerable: true,
value
});
return value;
},
set: _ => {
throw new Error('Could not overwrite an XTB translation');
}
});
}
class XtbParser {
_bundleDepth;
_errors;
_msgIdToHtml;
_locale = null;
parse(xtb, url) {
this._bundleDepth = 0;
this._msgIdToHtml = {};
const xml = new XmlParser().parse(xtb, url);
this._errors = xml.errors;
visitAll(this, xml.rootNodes);
return {
msgIdToHtml: this._msgIdToHtml,
errors: this._errors,
locale: this._locale
};
}
visitElement(element, context) {
switch (element.name) {
case _TRANSLATIONS_TAG:
this._bundleDepth++;
if (this._bundleDepth > 1) {
this._addError(element, `<${_TRANSLATIONS_TAG}> elements can not be nested`);
}
const langAttr = element.attrs.find(attr => attr.name === 'lang');
if (langAttr) {
this._locale = langAttr.value;
}
visitAll(this, element.children, null);
this._bundleDepth--;
break;
case _TRANSLATION_TAG:
const idAttr = element.attrs.find(attr => attr.name === 'id');
if (!idAttr) {
this._addError(element, `<${_TRANSLATION_TAG}> misses the "id" attribute`);
} else {
const id = idAttr.value;
if (this._msgIdToHtml.hasOwnProperty(id)) {
this._addError(element, `Duplicated translations for msg ${id}`);
} else {
const innerTextStart = element.startSourceSpan.end.offset;
const innerTextEnd = element.endSourceSpan.start.offset;
const content = element.startSourceSpan.start.file.content;
const innerText = content.slice(innerTextStart, innerTextEnd);
this._msgIdToHtml[id] = innerText;
}
}
break;
default:
this._addError(element, 'Unexpected tag');
}
}
visitAttribute(attribute, context) {}
visitText(text, context) {}
visitComment(comment, context) {}
visitExpansion(expansion, context) {}
visitExpansionCase(expansionCase, context) {}
visitBlock(block, context) {}
visitBlockParameter(block, context) {}
visitLetDeclaration(decl, context) {}
visitComponent(component, context) {
this._addError(component, 'Unexpected node');
}
visitDirective(directive, context) {
this._addError(directive, 'Unexpected node');
}
_addError(node, message) {
this._errors.push(new ParseError(node.sourceSpan, message));
}
}
class XmlToI18n {
_errors;
convert(message, url) {
const xmlIcu = new XmlParser().parse(message, url, {
tokenizeExpansionForms: true
});
this._errors = xmlIcu.errors;
const i18nNodes = this._errors.length > 0 || xmlIcu.rootNodes.length == 0 ? [] : visitAll(this, xmlIcu.rootNodes);
return {
i18nNodes,
errors: this._errors
};
}
visitText(text, context) {
return new Text$2(text.value, text.sourceSpan);
}
visitExpansion(icu, context) {
const caseMap = {};
visitAll(this, icu.cases).forEach(c => {
caseMap[c.value] = new Container(c.nodes, icu.sourceSpan);
});
return new Icu(icu.switchValue, icu.type, caseMap, icu.sourceSpan);
}
visitExpansionCase(icuCase, context) {
return {
value: icuCase.value,
nodes: visitAll(this, icuCase.expression)
};
}
visitElement(el, context) {
if (el.name === _PLACEHOLDER_TAG) {
const nameAttr = el.attrs.find(attr => attr.name === 'name');
if (nameAttr) {
return new Placeholder('', nameAttr.value, el.sourceSpan);
}
this._addError(el, `<${_PLACEHOLDER_TAG}> misses the "name" attribute`);
} else {
this._addError(el, `Unexpected tag`);
}
return null;
}
visitComment(comment, context) {}
visitAttribute(attribute, context) {}
visitBlock(block, context) {}
visitBlockParameter(block, context) {}
visitLetDeclaration(decl, context) {}
visitComponent(component, context) {
this._addError(component, 'Unexpected node');
}
visitDirective(directive, context) {
this._addError(directive, 'Unexpected node');
}
_addError(node, message) {
this._errors.push(new ParseError(node.sourceSpan, message));
}
}
class TranslationBundle {
_i18nNodesByMsgId;
digest;
mapperFactory;
_i18nToHtml;
constructor(_i18nNodesByMsgId = {}, locale, digest, mapperFactory, missingTranslationStrategy = MissingTranslationStrategy.Warning, console) {
this._i18nNodesByMsgId = _i18nNodesByMsgId;
this.digest = digest;
this.mapperFactory = mapperFactory;
this._i18nToHtml = new I18nToHtmlVisitor(_i18nNodesByMsgId, locale, digest, mapperFactory, missingTranslationStrategy, console);
}
static load(content, url, serializer, missingTranslationStrategy, console) {
const {
locale,
i18nNodesByMsgId
} = serializer.load(content, url);
const digestFn = m => serializer.digest(m);
const mapperFactory = m => serializer.createNameMapper(m);
return new TranslationBundle(i18nNodesByMsgId, locale, digestFn, mapperFactory, missingTranslationStrategy, console);
}
get(srcMsg) {
const html = this._i18nToHtml.convert(srcMsg);
if (html.errors.length) {
throw new Error(html.errors.join('\n'));
}
return html.nodes;
}
has(srcMsg) {
return this.digest(srcMsg) in this._i18nNodesByMsgId;
}
}
class I18nToHtmlVisitor {
_i18nNodesByMsgId;
_locale;
_digest;
_mapperFactory;
_missingTranslationStrategy;
_console;
_srcMsg;
_errors = [];
_contextStack = [];
_mapper;
constructor(_i18nNodesByMsgId = {}, _locale, _digest, _mapperFactory, _missingTranslationStrategy, _console) {
this._i18nNodesByMsgId = _i18nNodesByMsgId;
this._locale = _locale;
this._digest = _digest;
this._mapperFactory = _mapperFactory;
this._missingTranslationStrategy = _missingTranslationStrategy;
this._console = _console;
}
convert(srcMsg) {
this._contextStack.length = 0;
this._errors.length = 0;
const text = this._convertToText(srcMsg);
const url = srcMsg.nodes[0].sourceSpan.start.file.url;
const html = new HtmlParser().parse(text, url, {
tokenizeExpansionForms: true
});
return {
nodes: html.rootNodes,
errors: [...this._errors, ...html.errors]
};
}
visitText(text, context) {
return escapeXml(text.value);
}
visitContainer(container, context) {
return container.children.map(n => n.visit(this)).join('');
}
visitIcu(icu, context) {
const cases = Object.keys(icu.cases).map(k => `${k} {${icu.cases[k].visit(this)}}`);
const exp = this._srcMsg.placeholders.hasOwnProperty(icu.expression) ? this._srcMsg.placeholders[icu.expression].text : icu.expression;
return `{${exp}, ${icu.type}, ${cases.join(' ')}}`;
}
visitPlaceholder(ph, context) {
const phName = this._mapper(ph.name);
if (this._srcMsg.placeholders.hasOwnProperty(phName)) {
return this._srcMsg.placeholders[phName].text;
}
if (this._srcMsg.placeholderToMessage.hasOwnProperty(phName)) {
return this._convertToText(this._srcMsg.placeholderToMessage[phName]);
}
this._addError(ph, `Unknown placeholder "${ph.name}"`);
return '';
}
visitTagPlaceholder(ph, context) {
const tag = `${ph.tag}`;
const attrs = Object.keys(ph.attrs).map(name => `${name}="${ph.attrs[name]}"`).join(' ');
if (ph.isVoid) {
return `<${tag} ${attrs}/>`;
}
const children = ph.children.map(c => c.visit(this)).join('');
return `<${tag} ${attrs}>${children}</${tag}>`;
}
visitIcuPlaceholder(ph, context) {
return this._convertToText(this._srcMsg.placeholderToMessage[ph.name]);
}
visitBlockPlaceholder(ph, context) {
const params = ph.parameters.length === 0 ? '' : ` (${ph.parameters.join('; ')})`;
const children = ph.children.map(c => c.visit(this)).join('');
return `@${ph.name}${params} {${children}}`;
}
_convertToText(srcMsg) {
const id = this._digest(srcMsg);
const mapper = this._mapperFactory ? this._mapperFactory(srcMsg) : null;
let nodes;
this._contextStack.push({
msg: this._srcMsg,
mapper: this._mapper
});
this._srcMsg = srcMsg;
if (this._i18nNodesByMsgId.hasOwnProperty(id)) {
nodes = this._i18nNodesByMsgId[id];
this._mapper = name => mapper ? mapper.toInternalName(name) : name;
} else {
if (this._missingTranslationStrategy === MissingTranslationStrategy.Error) {
const ctx = this._locale ? ` for locale "${this._locale}"` : '';
this._addError(srcMsg.nodes[0], `Missing translation for message "${id}"${ctx}`);
} else if (this._console && this._missingTranslationStrategy === MissingTranslationStrategy.Warning) {
const ctx = this._locale ? ` for locale "${this._locale}"` : '';
this._console.warn(`Missing translation for message "${id}"${ctx}`);
}
nodes = srcMsg.nodes;
this._mapper = name => name;
}
const text = nodes.map(node => node.visit(this)).join('');
const context = this._contextStack.pop();
this._srcMsg = context.msg;
this._mapper = context.mapper;
return text;
}
_addError(el, msg) {
this._errors.push(new ParseError(el.sourceSpan, msg));
}
}
class I18NHtmlParser {
_htmlParser;
getTagDefinition;
_translationBundle;
constructor(_htmlParser, translations, translationsFormat, missingTranslation = MissingTranslationStrategy.Warning, console) {
this._htmlParser = _htmlParser;
if (translations) {
const serializer = createSerializer(translationsFormat);
this._translationBundle = TranslationBundle.load(translations, 'i18n', serializer, missingTranslation, console);
} else {
this._translationBundle = new TranslationBundle({}, null, digest$1, undefined, missingTranslation, console);
}
}
parse(source, url, options = {}) {
const parseResult = this._htmlParser.parse(source, url, {
...options
});
if (parseResult.errors.length) {
return new ParseTreeResult(parseResult.rootNodes, parseResult.errors);
}
return mergeTranslations(parseResult.rootNodes, this._translationBundle, [], {});
}
}
function createSerializer(format) {
format = (format || 'xlf').toLowerCase();
switch (format) {
case 'xmb':
return new Xmb();
case 'xtb':
return new Xtb();
case 'xliff2':
case 'xlf2':
return new Xliff2();
case 'xliff':
case 'xlf':
default:
return new Xliff();
}
}
class MessageBundle {
_htmlParser;
_implicitTags;
_implicitAttrs;
_locale;
_preserveWhitespace;
_messages = [];
constructor(_htmlParser, _implicitTags, _implicitAttrs, _locale = null, _preserveWhitespace = true) {
this._htmlParser = _htmlParser;
this._implicitTags = _implicitTags;
this._implicitAttrs = _implicitAttrs;
this._locale = _locale;
this._preserveWhitespace = _preserveWhitespace;
}
updateFromTemplate(source, url) {
const htmlParserResult = this._htmlParser.parse(source, url, {
tokenizeExpansionForms: true
});
if (htmlParserResult.errors.length) {
return htmlParserResult.errors;
}
const rootNodes = this._preserveWhitespace ? htmlParserResult.rootNodes : visitAllWithSiblings(new WhitespaceVisitor(false), htmlParserResult.rootNodes);
const i18nParserResult = extractMessages(rootNodes, this._implicitTags, this._implicitAttrs, this._preserveWhitespace);
if (i18nParserResult.errors.length) {
return i18nParserResult.errors;
}
this._messages.push(...i18nParserResult.messages);
return [];
}
getMessages() {
return this._messages;
}
write(serializer, filterSources) {
const messages = {};
const mapperVisitor = new MapPlaceholderNames();
this._messages.forEach(message => {
const id = serializer.digest(message);
if (!messages.hasOwnProperty(id)) {
messages[id] = message;
} else {
messages[id].sources.push(...message.sources);
}
});
const msgList = Object.keys(messages).map(id => {
const mapper = serializer.createNameMapper(messages[id]);
const src = messages[id];
const nodes = mapper ? mapperVisitor.convert(src.nodes, mapper) : src.nodes;
let transformedMessage = new Message(nodes, {}, {}, src.meaning, src.description, id);
transformedMessage.sources = src.sources;
if (filterSources) {
transformedMessage.sources.forEach(source => source.filePath = filterSources(source.filePath));
}
return transformedMessage;
});
return serializer.write(msgList, this._locale);
}
}
class MapPlaceholderNames extends CloneVisitor {
convert(nodes, mapper) {
return mapper ? nodes.map(n => n.visit(this, mapper)) : nodes;
}
visitTagPlaceholder(ph, mapper) {
const startName = mapper.toPublicName(ph.startName);
const closeName = ph.closeName ? mapper.toPublicName(ph.closeName) : ph.closeName;
const children = ph.children.map(n => n.visit(this, mapper));
return new TagPlaceholder(ph.tag, ph.attrs, startName, closeName, children, ph.isVoid, ph.sourceSpan, ph.startSourceSpan, ph.endSourceSpan);
}
visitBlockPlaceholder(ph, mapper) {
const startName = mapper.toPublicName(ph.startName);
const closeName = ph.closeName ? mapper.toPublicName(ph.closeName) : ph.closeName;
const children = ph.children.map(n => n.visit(this, mapper));
return new BlockPlaceholder(ph.name, ph.parameters, startName, closeName, children, ph.sourceSpan, ph.startSourceSpan, ph.endSourceSpan);
}
visitPlaceholder(ph, mapper) {
return new Placeholder(ph.value, mapper.toPublicName(ph.name), ph.sourceSpan);
}
visitIcuPlaceholder(ph, mapper) {
return new IcuPlaceholder(ph.value, mapper.toPublicName(ph.name), ph.sourceSpan);
}
}
function compileClassMetadata(metadata) {
const fnCall = internalCompileClassMetadata(metadata);
return arrowFn([], [devOnlyGuardedExpression(fnCall).toStmt()]).callFn([]);
}
function internalCompileClassMetadata(metadata) {
return importExpr(Identifiers.setClassMetadata).callFn([metadata.type, metadata.decorators, metadata.ctorParameters ?? literal(null), metadata.propDecorators ?? literal(null)]);
}
function compileComponentClassMetadata(metadata, dependencies) {
if (dependencies === null || dependencies.length === 0) {
return compileClassMetadata(metadata);
}
return internalCompileSetClassMetadataAsync(metadata, dependencies.map(dep => new FnParam(dep.symbolName, DYNAMIC_TYPE)), compileComponentMetadataAsyncResolver(dependencies));
}
function compileOpaqueAsyncClassMetadata(metadata, deferResolver, deferredDependencyNames) {
return internalCompileSetClassMetadataAsync(metadata, deferredDependencyNames.map(name => new FnParam(name, DYNAMIC_TYPE)), deferResolver);
}
function internalCompileSetClassMetadataAsync(metadata, wrapperParams, dependencyResolverFn) {
const setClassMetadataCall = internalCompileClassMetadata(metadata);
const setClassMetaWrapper = arrowFn(wrapperParams, [setClassMetadataCall.toStmt()]);
const setClassMetaAsync = importExpr(Identifiers.setClassMetadataAsync).callFn([metadata.type, dependencyResolverFn, setClassMetaWrapper]);
return arrowFn([], [devOnlyGuardedExpression(setClassMetaAsync).toStmt()]).callFn([]);
}
function compileComponentMetadataAsyncResolver(dependencies) {
const dynamicImports = dependencies.map(({
symbolName,
importPath,
isDefaultImport
}) => {
const innerFn = arrowFn([new FnParam('m', DYNAMIC_TYPE)], variable('m').prop(isDefaultImport ? 'default' : symbolName));
return new DynamicImportExpr(importPath).prop('then').callFn([innerFn]);
});
return arrowFn([], literalArr(dynamicImports));
}
const MINIMUM_PARTIAL_LINKER_VERSION$5 = '12.0.0';
const MINIMUM_PARTIAL_LINKER_DEFER_SUPPORT_VERSION = '18.0.0';
function compileDeclareClassMetadata(metadata) {
const definitionMap = new DefinitionMap();
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$5));
definitionMap.set('version', literal('21.1.1'));
definitionMap.set('ngImport', importExpr(Identifiers.core));
definitionMap.set('type', metadata.type);
definitionMap.set('decorators', metadata.decorators);
definitionMap.set('ctorParameters', metadata.ctorParameters);
definitionMap.set('propDecorators', metadata.propDecorators);
return importExpr(Identifiers.declareClassMetadata).callFn([definitionMap.toLiteralMap()]);
}
function compileComponentDeclareClassMetadata(metadata, dependencies) {
if (dependencies === null || dependencies.length === 0) {
return compileDeclareClassMetadata(metadata);
}
const definitionMap = new DefinitionMap();
const callbackReturnDefinitionMap = new DefinitionMap();
callbackReturnDefinitionMap.set('decorators', metadata.decorators);
callbackReturnDefinitionMap.set('ctorParameters', metadata.ctorParameters ?? literal(null));
callbackReturnDefinitionMap.set('propDecorators', metadata.propDecorators ?? literal(null));
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_DEFER_SUPPORT_VERSION));
definitionMap.set('version', literal('21.1.1'));
definitionMap.set('ngImport', importExpr(Identifiers.core));
definitionMap.set('type', metadata.type);
definitionMap.set('resolveDeferredDeps', compileComponentMetadataAsyncResolver(dependencies));
definitionMap.set('resolveMetadata', arrowFn(dependencies.map(dep => new FnParam(dep.symbolName, DYNAMIC_TYPE)), callbackReturnDefinitionMap.toLiteralMap()));
return importExpr(Identifiers.declareClassMetadataAsync).callFn([definitionMap.toLiteralMap()]);
}
function toOptionalLiteralArray(values, mapper) {
if (values === null || values.length === 0) {
return null;
}
return literalArr(values.map(value => mapper(value)));
}
function toOptionalLiteralMap(object, mapper) {
const entries = Object.keys(object).map(key => {
const value = object[key];
return {
key,
value: mapper(value),
quoted: true
};
});
if (entries.length > 0) {
return literalMap(entries);
} else {
return null;
}
}
function compileDependencies(deps) {
if (deps === 'invalid') {
return literal('invalid');
} else if (deps === null) {
return literal(null);
} else {
return literalArr(deps.map(compileDependency));
}
}
function compileDependency(dep) {
const depMeta = new DefinitionMap();
depMeta.set('token', dep.token);
if (dep.attributeNameType !== null) {
depMeta.set('attribute', literal(true));
}
if (dep.host) {
depMeta.set('host', literal(true));
}
if (dep.optional) {
depMeta.set('optional', literal(true));
}
if (dep.self) {
depMeta.set('self', literal(true));
}
if (dep.skipSelf) {
depMeta.set('skipSelf', literal(true));
}
return depMeta.toLiteralMap();
}
function compileDeclareDirectiveFromMetadata(meta) {
const definitionMap = createDirectiveDefinitionMap(meta);
const expression = importExpr(Identifiers.declareDirective).callFn([definitionMap.toLiteralMap()]);
const type = createDirectiveType(meta);
return {
expression,
type,
statements: []
};
}
function createDirectiveDefinitionMap(meta) {
const definitionMap = new DefinitionMap();
const minVersion = getMinimumVersionForPartialOutput(meta);
definitionMap.set('minVersion', literal(minVersion));
definitionMap.set('version', literal('21.1.1'));
definitionMap.set('type', meta.type.value);
if (meta.isStandalone !== undefined) {
definitionMap.set('isStandalone', literal(meta.isStandalone));
}
if (meta.isSignal) {
definitionMap.set('isSignal', literal(meta.isSignal));
}
if (meta.selector !== null) {
definitionMap.set('selector', literal(meta.selector));
}
definitionMap.set('inputs', needsNewInputPartialOutput(meta) ? createInputsPartialMetadata(meta.inputs) : legacyInputsPartialMetadata(meta.inputs));
definitionMap.set('outputs', conditionallyCreateDirectiveBindingLiteral(meta.outputs));
definitionMap.set('host', compileHostMetadata(meta.host));
definitionMap.set('providers', meta.providers);
if (meta.queries.length > 0) {
definitionMap.set('queries', literalArr(meta.queries.map(compileQuery)));
}
if (meta.viewQueries.length > 0) {
definitionMap.set('viewQueries', literalArr(meta.viewQueries.map(compileQuery)));
}
if (meta.exportAs !== null) {
definitionMap.set('exportAs', asLiteral(meta.exportAs));
}
if (meta.usesInheritance) {
definitionMap.set('usesInheritance', literal(true));
}
if (meta.lifecycle.usesOnChanges) {
definitionMap.set('usesOnChanges', literal(true));
}
if (meta.hostDirectives?.length) {
definitionMap.set('hostDirectives', createHostDirectives(meta.hostDirectives));
}
definitionMap.set('ngImport', importExpr(Identifiers.core));
return definitionMap;
}
function getMinimumVersionForPartialOutput(meta) {
let minVersion = '14.0.0';
const hasDecoratorTransformFunctions = Object.values(meta.inputs).some(input => input.transformFunction !== null);
if (hasDecoratorTransformFunctions) {
minVersion = '16.1.0';
}
if (needsNewInputPartialOutput(meta)) {
minVersion = '17.1.0';
}
if (meta.queries.some(q => q.isSignal) || meta.viewQueries.some(q => q.isSignal)) {
minVersion = '17.2.0';
}
return minVersion;
}
function needsNewInputPartialOutput(meta) {
return Object.values(meta.inputs).some(input => input.isSignal);
}
function compileQuery(query) {
const meta = new DefinitionMap();
meta.set('propertyName', literal(query.propertyName));
if (query.first) {
meta.set('first', literal(true));
}
meta.set('predicate', Array.isArray(query.predicate) ? asLiteral(query.predicate) : convertFromMaybeForwardRefExpression(query.predicate));
if (!query.emitDistinctChangesOnly) {
meta.set('emitDistinctChangesOnly', literal(false));
}
if (query.descendants) {
meta.set('descendants', literal(true));
}
meta.set('read', query.read);
if (query.static) {
meta.set('static', literal(true));
}
if (query.isSignal) {
meta.set('isSignal', literal(true));
}
return meta.toLiteralMap();
}
function compileHostMetadata(meta) {
const hostMetadata = new DefinitionMap();
hostMetadata.set('attributes', toOptionalLiteralMap(meta.attributes, expression => expression));
hostMetadata.set('listeners', toOptionalLiteralMap(meta.listeners, literal));
hostMetadata.set('properties', toOptionalLiteralMap(meta.properties, literal));
if (meta.specialAttributes.styleAttr) {
hostMetadata.set('styleAttribute', literal(meta.specialAttributes.styleAttr));
}
if (meta.specialAttributes.classAttr) {
hostMetadata.set('classAttribute', literal(meta.specialAttributes.classAttr));
}
if (hostMetadata.values.length > 0) {
return hostMetadata.toLiteralMap();
} else {
return null;
}
}
function createHostDirectives(hostDirectives) {
const expressions = hostDirectives.map(current => {
const keys = [{
key: 'directive',
value: current.isForwardReference ? generateForwardRef(current.directive.type) : current.directive.type,
quoted: false
}];
const inputsLiteral = current.inputs ? createHostDirectivesMappingArray(current.inputs) : null;
const outputsLiteral = current.outputs ? createHostDirectivesMappingArray(current.outputs) : null;
if (inputsLiteral) {
keys.push({
key: 'inputs',
value: inputsLiteral,
quoted: false
});
}
if (outputsLiteral) {
keys.push({
key: 'outputs',
value: outputsLiteral,
quoted: false
});
}
return literalMap(keys);
});
return literalArr(expressions);
}
function createInputsPartialMetadata(inputs) {
const keys = Object.getOwnPropertyNames(inputs);
if (keys.length === 0) {
return null;
}
return literalMap(keys.map(declaredName => {
const value = inputs[declaredName];
return {
key: declaredName,
quoted: UNSAFE_OBJECT_KEY_NAME_REGEXP.test(declaredName),
value: literalMap([{
key: 'classPropertyName',
quoted: false,
value: asLiteral(value.classPropertyName)
}, {
key: 'publicName',
quoted: false,
value: asLiteral(value.bindingPropertyName)
}, {
key: 'isSignal',
quoted: false,
value: asLiteral(value.isSignal)
}, {
key: 'isRequired',
quoted: false,
value: asLiteral(value.required)
}, {
key: 'transformFunction',
quoted: false,
value: value.transformFunction ?? NULL_EXPR
}])
};
}));
}
function legacyInputsPartialMetadata(inputs) {
const keys = Object.getOwnPropertyNames(inputs);
if (keys.length === 0) {
return null;
}
return literalMap(keys.map(declaredName => {
const value = inputs[declaredName];
const publicName = value.bindingPropertyName;
const differentDeclaringName = publicName !== declaredName;
let result;
if (differentDeclaringName || value.transformFunction !== null) {
const values = [asLiteral(publicName), asLiteral(declaredName)];
if (value.transformFunction !== null) {
values.push(value.transformFunction);
}
result = literalArr(values);
} else {
result = asLiteral(publicName);
}
return {
key: declaredName,
quoted: UNSAFE_OBJECT_KEY_NAME_REGEXP.test(declaredName),
value: result
};
}));
}
function compileDeclareComponentFromMetadata(meta, template, additionalTemplateInfo) {
const definitionMap = createComponentDefinitionMap(meta, template, additionalTemplateInfo);
const expression = importExpr(Identifiers.declareComponent).callFn([definitionMap.toLiteralMap()]);
const type = createComponentType(meta);
return {
expression,
type,
statements: []
};
}
function createComponentDefinitionMap(meta, template, templateInfo) {
const definitionMap = createDirectiveDefinitionMap(meta);
const blockVisitor = new BlockPresenceVisitor();
visitAll$1(blockVisitor, template.nodes);
definitionMap.set('template', getTemplateExpression(template, templateInfo));
if (templateInfo.isInline) {
definitionMap.set('isInline', literal(true));
}
if (blockVisitor.hasBlocks) {
definitionMap.set('minVersion', literal('17.0.0'));
}
definitionMap.set('styles', toOptionalLiteralArray(meta.styles, literal));
definitionMap.set('dependencies', compileUsedDependenciesMetadata(meta));
definitionMap.set('viewProviders', meta.viewProviders);
definitionMap.set('animations', meta.animations);
if (meta.changeDetection !== null) {
if (typeof meta.changeDetection === 'object') {
throw new Error('Impossible state! Change detection flag is not resolved!');
}
definitionMap.set('changeDetection', importExpr(Identifiers.ChangeDetectionStrategy).prop(ChangeDetectionStrategy[meta.changeDetection]));
}
if (meta.encapsulation !== ViewEncapsulation$1.Emulated) {
definitionMap.set('encapsulation', importExpr(Identifiers.ViewEncapsulation).prop(ViewEncapsulation$1[meta.encapsulation]));
}
if (template.preserveWhitespaces === true) {
definitionMap.set('preserveWhitespaces', literal(true));
}
if (meta.defer.mode === 0) {
const resolvers = [];
let hasResolvers = false;
for (const deps of meta.defer.blocks.values()) {
if (deps === null) {
resolvers.push(literal(null));
} else {
resolvers.push(deps);
hasResolvers = true;
}
}
if (hasResolvers) {
definitionMap.set('deferBlockDependencies', literalArr(resolvers));
}
} else {
throw new Error('Unsupported defer function emit mode in partial compilation');
}
return definitionMap;
}
function getTemplateExpression(template, templateInfo) {
if (templateInfo.inlineTemplateLiteralExpression !== null) {
return templateInfo.inlineTemplateLiteralExpression;
}
if (templateInfo.isInline) {
return literal(templateInfo.content, null, null);
}
const contents = templateInfo.content;
const file = new ParseSourceFile(contents, templateInfo.sourceUrl);
const start = new ParseLocation(file, 0, 0, 0);
const end = computeEndLocation(file, contents);
const span = new ParseSourceSpan(start, end);
return literal(contents, null, span);
}
function computeEndLocation(file, contents) {
const length = contents.length;
let lineStart = 0;
let lastLineStart = 0;
let line = 0;
do {
lineStart = contents.indexOf('\n', lastLineStart);
if (lineStart !== -1) {
lastLineStart = lineStart + 1;
line++;
}
} while (lineStart !== -1);
return new ParseLocation(file, length, line, length - lastLineStart);
}
function compileUsedDependenciesMetadata(meta) {
const wrapType = meta.declarationListEmitMode !== 0 ? generateForwardRef : expr => expr;
if (meta.declarationListEmitMode === 3) {
throw new Error(`Unsupported emit mode`);
}
return toOptionalLiteralArray(meta.declarations, decl => {
switch (decl.kind) {
case R3TemplateDependencyKind.Directive:
const dirMeta = new DefinitionMap();
dirMeta.set('kind', literal(decl.isComponent ? 'component' : 'directive'));
dirMeta.set('type', wrapType(decl.type));
dirMeta.set('selector', literal(decl.selector));
dirMeta.set('inputs', toOptionalLiteralArray(decl.inputs, literal));
dirMeta.set('outputs', toOptionalLiteralArray(decl.outputs, literal));
dirMeta.set('exportAs', toOptionalLiteralArray(decl.exportAs, literal));
return dirMeta.toLiteralMap();
case R3TemplateDependencyKind.Pipe:
const pipeMeta = new DefinitionMap();
pipeMeta.set('kind', literal('pipe'));
pipeMeta.set('type', wrapType(decl.type));
pipeMeta.set('name', literal(decl.name));
return pipeMeta.toLiteralMap();
case R3TemplateDependencyKind.NgModule:
const ngModuleMeta = new DefinitionMap();
ngModuleMeta.set('kind', literal('ngmodule'));
ngModuleMeta.set('type', wrapType(decl.type));
return ngModuleMeta.toLiteralMap();
}
});
}
class BlockPresenceVisitor extends RecursiveVisitor$1 {
hasBlocks = false;
visitDeferredBlock() {
this.hasBlocks = true;
}
visitDeferredBlockPlaceholder() {
this.hasBlocks = true;
}
visitDeferredBlockLoading() {
this.hasBlocks = true;
}
visitDeferredBlockError() {
this.hasBlocks = true;
}
visitIfBlock() {
this.hasBlocks = true;
}
visitIfBlockBranch() {
this.hasBlocks = true;
}
visitForLoopBlock() {
this.hasBlocks = true;
}
visitForLoopBlockEmpty() {
this.hasBlocks = true;
}
visitSwitchBlock() {
this.hasBlocks = true;
}
visitSwitchBlockCase() {
this.hasBlocks = true;
}
visitSwitchBlockCaseGroup() {
this.hasBlocks = true;
}
}
const MINIMUM_PARTIAL_LINKER_VERSION$4 = '12.0.0';
function compileDeclareFactoryFunction(meta) {
const definitionMap = new DefinitionMap();
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$4));
definitionMap.set('version', literal('21.1.1'));
definitionMap.set('ngImport', importExpr(Identifiers.core));
definitionMap.set('type', meta.type.value);
definitionMap.set('deps', compileDependencies(meta.deps));
definitionMap.set('target', importExpr(Identifiers.FactoryTarget).prop(FactoryTarget[meta.target]));
return {
expression: importExpr(Identifiers.declareFactory).callFn([definitionMap.toLiteralMap()]),
statements: [],
type: createFactoryType(meta)
};
}
const MINIMUM_PARTIAL_LINKER_VERSION$3 = '12.0.0';
function compileDeclareInjectableFromMetadata(meta) {
const definitionMap = createInjectableDefinitionMap(meta);
const expression = importExpr(Identifiers.declareInjectable).callFn([definitionMap.toLiteralMap()]);
const type = createInjectableType(meta);
return {
expression,
type,
statements: []
};
}
function createInjectableDefinitionMap(meta) {
const definitionMap = new DefinitionMap();
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$3));
definitionMap.set('version', literal('21.1.1'));
definitionMap.set('ngImport', importExpr(Identifiers.core));
definitionMap.set('type', meta.type.value);
if (meta.providedIn !== undefined) {
const providedIn = convertFromMaybeForwardRefExpression(meta.providedIn);
if (providedIn.value !== null) {
definitionMap.set('providedIn', providedIn);
}
}
if (meta.useClass !== undefined) {
definitionMap.set('useClass', convertFromMaybeForwardRefExpression(meta.useClass));
}
if (meta.useExisting !== undefined) {
definitionMap.set('useExisting', convertFromMaybeForwardRefExpression(meta.useExisting));
}
if (meta.useValue !== undefined) {
definitionMap.set('useValue', convertFromMaybeForwardRefExpression(meta.useValue));
}
if (meta.useFactory !== undefined) {
definitionMap.set('useFactory', meta.useFactory);
}
if (meta.deps !== undefined) {
definitionMap.set('deps', literalArr(meta.deps.map(compileDependency)));
}
return definitionMap;
}
const MINIMUM_PARTIAL_LINKER_VERSION$2 = '12.0.0';
function compileDeclareInjectorFromMetadata(meta) {
const definitionMap = createInjectorDefinitionMap(meta);
const expression = importExpr(Identifiers.declareInjector).callFn([definitionMap.toLiteralMap()]);
const type = createInjectorType(meta);
return {
expression,
type,
statements: []
};
}
function createInjectorDefinitionMap(meta) {
const definitionMap = new DefinitionMap();
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$2));
definitionMap.set('version', literal('21.1.1'));
definitionMap.set('ngImport', importExpr(Identifiers.core));
definitionMap.set('type', meta.type.value);
definitionMap.set('providers', meta.providers);
if (meta.imports.length > 0) {
definitionMap.set('imports', literalArr(meta.imports));
}
return definitionMap;
}
const MINIMUM_PARTIAL_LINKER_VERSION$1 = '14.0.0';
function compileDeclareNgModuleFromMetadata(meta) {
const definitionMap = createNgModuleDefinitionMap(meta);
const expression = importExpr(Identifiers.declareNgModule).callFn([definitionMap.toLiteralMap()]);
const type = createNgModuleType(meta);
return {
expression,
type,
statements: []
};
}
function createNgModuleDefinitionMap(meta) {
const definitionMap = new DefinitionMap();
if (meta.kind === R3NgModuleMetadataKind.Local) {
throw new Error('Invalid path! Local compilation mode should not get into the partial compilation path');
}
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$1));
definitionMap.set('version', literal('21.1.1'));
definitionMap.set('ngImport', importExpr(Identifiers.core));
definitionMap.set('type', meta.type.value);
if (meta.bootstrap.length > 0) {
definitionMap.set('bootstrap', refsToArray(meta.bootstrap, meta.containsForwardDecls));
}
if (meta.declarations.length > 0) {
definitionMap.set('declarations', refsToArray(meta.declarations, meta.containsForwardDecls));
}
if (meta.imports.length > 0) {
definitionMap.set('imports', refsToArray(meta.imports, meta.containsForwardDecls));
}
if (meta.exports.length > 0) {
definitionMap.set('exports', refsToArray(meta.exports, meta.containsForwardDecls));
}
if (meta.schemas !== null && meta.schemas.length > 0) {
definitionMap.set('schemas', literalArr(meta.schemas.map(ref => ref.value)));
}
if (meta.id !== null) {
definitionMap.set('id', meta.id);
}
return definitionMap;
}
const MINIMUM_PARTIAL_LINKER_VERSION = '14.0.0';
function compileDeclarePipeFromMetadata(meta) {
const definitionMap = createPipeDefinitionMap(meta);
const expression = importExpr(Identifiers.declarePipe).callFn([definitionMap.toLiteralMap()]);
const type = createPipeType(meta);
return {
expression,
type,
statements: []
};
}
function createPipeDefinitionMap(meta) {
const definitionMap = new DefinitionMap();
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION));
definitionMap.set('version', literal('21.1.1'));
definitionMap.set('ngImport', importExpr(Identifiers.core));
definitionMap.set('type', meta.type.value);
if (meta.isStandalone !== undefined) {
definitionMap.set('isStandalone', literal(meta.isStandalone));
}
definitionMap.set('name', literal(meta.pipeName ?? meta.name));
if (meta.pure === false) {
definitionMap.set('pure', literal(meta.pure));
}
return definitionMap;
}
function compileClassDebugInfo(debugInfo) {
const debugInfoObject = {
className: debugInfo.className
};
if (debugInfo.filePath) {
debugInfoObject.filePath = debugInfo.filePath;
debugInfoObject.lineNumber = debugInfo.lineNumber;
}
if (debugInfo.forbidOrphanRendering) {
debugInfoObject.forbidOrphanRendering = literal(true);
}
const fnCall = importExpr(Identifiers.setClassDebugInfo).callFn([debugInfo.type, mapLiteral(debugInfoObject)]);
const iife = arrowFn([], [devOnlyGuardedExpression(fnCall).toStmt()]);
return iife.callFn([]);
}
function compileHmrInitializer(meta) {
const moduleName = 'm';
const dataName = 'd';
const timestampName = 't';
const idName = 'id';
const importCallbackName = `${meta.className}_HmrLoad`;
const namespaces = meta.namespaceDependencies.map(dep => {
return new ExternalExpr({
moduleName: dep.moduleName,
name: null
});
});
const defaultRead = variable(moduleName).prop('default');
const replaceCall = importExpr(Identifiers.replaceMetadata).callFn([meta.type, defaultRead, literalArr(namespaces), literalArr(meta.localDependencies.map(l => l.runtimeRepresentation)), variable('import').prop('meta'), variable(idName)]);
const replaceCallback = arrowFn([new FnParam(moduleName)], defaultRead.and(replaceCall));
const url = importExpr(Identifiers.getReplaceMetadataURL).callFn([variable(idName), variable(timestampName), variable('import').prop('meta').prop('url')]);
const importCallback = new DeclareFunctionStmt(importCallbackName, [new FnParam(timestampName)], [new DynamicImportExpr(url, null, '@vite-ignore').prop('then').callFn([replaceCallback]).toStmt()], null, StmtModifier.Final);
const updateCallback = arrowFn([new FnParam(dataName)], variable(dataName).prop('id').identical(variable(idName)).and(variable(importCallbackName).callFn([variable(dataName).prop('timestamp')])));
const initialCall = variable(importCallbackName).callFn([variable('Date').prop('now').callFn([])]);
const hotRead = variable('import').prop('meta').prop('hot');
const hotListener = hotRead.clone().prop('on').callFn([literal('angular:component-update'), updateCallback]);
return arrowFn([], [new DeclareVarStmt(idName, literal(encodeURIComponent(`${meta.filePath}@${meta.className}`)), null, StmtModifier.Final), importCallback, devOnlyGuardedExpression(initialCall).toStmt(), devOnlyGuardedExpression(hotRead.and(hotListener)).toStmt()]).callFn([]);
}
function compileHmrUpdateCallback(definitions, constantStatements, meta) {
const namespaces = 'ɵɵnamespaces';
const params = [meta.className, namespaces].map(name => new FnParam(name, DYNAMIC_TYPE));
const body = [];
for (const local of meta.localDependencies) {
params.push(new FnParam(local.name));
}
for (let i = 0; i < meta.namespaceDependencies.length; i++) {
body.push(new DeclareVarStmt(meta.namespaceDependencies[i].assignedName, variable(namespaces).key(literal(i)), DYNAMIC_TYPE, StmtModifier.Final));
}
body.push(...constantStatements);
for (const field of definitions) {
if (field.initializer !== null) {
body.push(variable(meta.className).prop(field.name).set(field.initializer).toStmt());
for (const stmt of field.statements) {
body.push(stmt);
}
}
}
return new DeclareFunctionStmt(`${meta.className}_UpdateMetadata`, params, body, null, StmtModifier.Final);
}
const VERSION = new Version('21.1.1');
publishFacade(_global);
export { AST, ASTWithName, ASTWithSource, AbsoluteSourceSpan, ArrayType, ArrowFunctionExpr, Attribute, Binary, BinaryOperator, BinaryOperatorExpr, BindingPipe, BindingPipeType, BindingType, Block, BlockParameter, BoundElementProperty, BuiltinType, BuiltinTypeName, CUSTOM_ELEMENTS_SCHEMA, Call, Chain, ChangeDetectionStrategy, CombinedRecursiveAstVisitor, CommaExpr, Comment, CompilerConfig, CompilerFacadeImpl, Component, Conditional, ConditionalExpr, ConstantPool, CssSelector, DYNAMIC_TYPE, DeclareFunctionStmt, DeclareVarStmt, Directive, DomElementSchemaRegistry, DynamicImportExpr, EOF, Element, ElementSchemaRegistry, EmitterVisitorContext, EmptyExpr$1 as EmptyExpr, Expansion, ExpansionCase, Expression, ExpressionBinding, ExpressionStatement, ExpressionType, ExternalExpr, ExternalReference, FactoryTarget, FunctionExpr, HtmlParser, HtmlTagDefinition, I18NHtmlParser, IfStmt, ImplicitReceiver, InstantiateExpr, Interpolation$1 as Interpolation, InvokeFunctionExpr, JSDocComment, JitEvaluator, KeyedRead, LeadingComment, LetDeclaration, Lexer, LiteralArray, LiteralArrayExpr, LiteralExpr, LiteralMap, LiteralMapExpr, LiteralMapPropertyAssignment, LiteralMapSpreadAssignment, LiteralPrimitive, LocalizedString, MapType, MessageBundle, NONE_TYPE, NO_ERRORS_SCHEMA, NodeWithI18n, NonNullAssert, NotExpr, ParenthesizedExpr, ParenthesizedExpression, ParseError, ParseErrorLevel, ParseLocation, ParseSourceFile, ParseSourceSpan, ParseSpan, ParseTreeResult, ParsedEvent, ParsedEventType, ParsedProperty, ParsedPropertyType, ParsedVariable, Parser, PrefixNot, PropertyRead, Identifiers as R3Identifiers, R3NgModuleMetadataKind, R3SelectorScopeMode, R3TargetBinder, R3TemplateDependencyKind, ReadKeyExpr, ReadPropExpr, ReadVarExpr, RecursiveAstVisitor, RecursiveVisitor, RegularExpressionLiteral, RegularExpressionLiteralExpr, ResourceLoader, ReturnStatement, SCHEMA, SECURITY_SCHEMA, STRING_TYPE, SafeCall, SafeKeyedRead, SafePropertyRead, SelectorContext, SelectorListContext, SelectorMatcher, SelectorlessMatcher, Serializer, SplitInterpolation, SpreadElement, SpreadElementExpr, Statement, StmtModifier, StringToken, StringTokenKind, TagContentType, TaggedTemplateLiteral, TaggedTemplateLiteralExpr, TemplateBindingParseResult, TemplateLiteral, TemplateLiteralElement, TemplateLiteralElementExpr, TemplateLiteralExpr, Text, ThisReceiver, BlockNode as TmplAstBlockNode, BoundAttribute as TmplAstBoundAttribute, BoundDeferredTrigger as TmplAstBoundDeferredTrigger, BoundEvent as TmplAstBoundEvent, BoundText as TmplAstBoundText, Component$1 as TmplAstComponent, Content as TmplAstContent, DeferredBlock as TmplAstDeferredBlock, DeferredBlockError as TmplAstDeferredBlockError, DeferredBlockLoading as TmplAstDeferredBlockLoading, DeferredBlockPlaceholder as TmplAstDeferredBlockPlaceholder, DeferredTrigger as TmplAstDeferredTrigger, Directive$1 as TmplAstDirective, Element$1 as TmplAstElement, ForLoopBlock as TmplAstForLoopBlock, ForLoopBlockEmpty as TmplAstForLoopBlockEmpty, HostElement as TmplAstHostElement, HoverDeferredTrigger as TmplAstHoverDeferredTrigger, Icu$1 as TmplAstIcu, IdleDeferredTrigger as TmplAstIdleDeferredTrigger, IfBlock as TmplAstIfBlock, IfBlockBranch as TmplAstIfBlockBranch, ImmediateDeferredTrigger as TmplAstImmediateDeferredTrigger, InteractionDeferredTrigger as TmplAstInteractionDeferredTrigger, LetDeclaration$1 as TmplAstLetDeclaration, NeverDeferredTrigger as TmplAstNeverDeferredTrigger, RecursiveVisitor$1 as TmplAstRecursiveVisitor, Reference as TmplAstReference, SwitchBlock as TmplAstSwitchBlock, SwitchBlockCase as TmplAstSwitchBlockCase, SwitchBlockCaseGroup as TmplAstSwitchBlockCaseGroup, Template as TmplAstTemplate, Text$3 as TmplAstText, TextAttribute as TmplAstTextAttribute, TimerDeferredTrigger as TmplAstTimerDeferredTrigger, UnknownBlock as TmplAstUnknownBlock, Variable as TmplAstVariable, ViewportDeferredTrigger as TmplAstViewportDeferredTrigger, Token, TokenType, TransplantedType, TreeError, Type, TypeModifier, TypeofExpr, TypeofExpression, Unary, UnaryOperator, UnaryOperatorExpr, VERSION, VariableBinding, Version, ViewEncapsulation$1 as ViewEncapsulation, VoidExpr, VoidExpression, WrappedNodeExpr, Xliff, Xliff2, Xmb, XmlParser, Xtb, _ATTR_TO_PROP, compileClassDebugInfo, compileClassMetadata, compileComponentClassMetadata, compileComponentDeclareClassMetadata, compileComponentFromMetadata, compileDeclareClassMetadata, compileDeclareComponentFromMetadata, compileDeclareDirectiveFromMetadata, compileDeclareFactoryFunction, compileDeclareInjectableFromMetadata, compileDeclareInjectorFromMetadata, compileDeclareNgModuleFromMetadata, compileDeclarePipeFromMetadata, compileDeferResolverFunction, compileDirectiveFromMetadata, compileFactoryFunction, compileHmrInitializer, compileHmrUpdateCallback, compileInjectable, compileInjector, compileNgModule, compileOpaqueAsyncClassMetadata, compilePipeFromMetadata, computeMsgId, core, createCssSelectorFromNode, createInjectableType, createMayBeForwardRefExpression, devOnlyGuardedExpression, emitDistinctChangesOnlyDefaultValue, encapsulateStyle, escapeRegExp, findMatchingDirectivesAndPipes, getHtmlTagDefinition, getNsPrefix, getSafePropertyAccessString, identifierName, isNgContainer, isNgContent, isNgTemplate, jsDocComment, leadingComment, literal, literalMap, makeBindingParser, mergeNsAndName, output_ast as outputAst, parseHostBindings, parseTemplate, preserveWhitespacesDefault, publishFacade, r3JitTypeSourceSpan, sanitizeIdentifier, setEnableTemplateSourceLocations, splitNsName, visitAll$1 as tmplAstVisitAll, verifyHostBindings, visitAll };
//# sourceMappingURL=compiler.mjs.map