UNPKG

@angular/compiler

Version:

Angular - the compiler library

1,545 lines (1,538 loc) 1.01 MB
/** * @license Angular v21.0.5 * (c) 2010-2025 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 LiteralMapEntry { 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() {