@angular/core
Version:
Angular - the core framework
1,413 lines (1,406 loc) • 1.99 MB
JavaScript
'use strict';
/**
* @license Angular v19.2.10
* (c) 2010-2025 Google LLC. https://angular.io/
* License: MIT
*/
'use strict';
var ts = require('typescript');
require('os');
var fs$1 = require('fs');
var module$1 = require('module');
var p = require('path');
var url = require('url');
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
function _interopNamespaceDefault(e) {
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n.default = e;
return Object.freeze(n);
}
var p__namespace = /*#__PURE__*/_interopNamespaceDefault(p);
const _SELECTOR_REGEXP = new RegExp('(\\:not\\()|' + // 1: ":not("
'(([\\.\\#]?)[-\\w]+)|' + // 2: "tag"; 3: "."/"#";
// "-" should appear first in the regexp below as FF31 parses "[.-\w]" as a range
// 4: attribute; 5: attribute_string; 6: attribute_value
'(?:\\[([-.\\w*\\\\$]+)(?:=(["\']?)([^\\]"\']*)\\5)?\\])|' + // "[name]", "[name=value]",
// "[name="value"]",
// "[name='value']"
'(\\))|' + // 7: ")"
'(\\s*,\\s*)', // 8: ","
'g');
/**
* A css selector contains an element name,
* css classes and attribute/value pairs with the purpose
* of selecting subsets out of them.
*/
class CssSelector {
element = null;
classNames = [];
/**
* The selectors are encoded in pairs where:
* - even locations are attribute names
* - odd locations are attribute values.
*
* Example:
* Selector: `[key1=value1][key2]` would parse to:
* ```
* ['key1', 'value1', 'key2', '']
* ```
*/
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 /* SelectorRegexp.NOT */]) {
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 /* SelectorRegexp.TAG */];
if (tag) {
const prefix = match[3 /* SelectorRegexp.PREFIX */];
if (prefix === '#') {
// #hash
current.addAttribute('id', tag.slice(1));
}
else if (prefix === '.') {
// Class
current.addClassName(tag.slice(1));
}
else {
// Element
current.setElement(tag);
}
}
const attribute = match[4 /* SelectorRegexp.ATTRIBUTE */];
if (attribute) {
current.addAttribute(current.unescapeAttribute(attribute), match[6 /* SelectorRegexp.ATTRIBUTE_VALUE */]);
}
if (match[7 /* SelectorRegexp.NOT_END */]) {
inNot = false;
current = cssSelector;
}
if (match[8 /* SelectorRegexp.SEPARATOR */]) {
if (inNot) {
throw new Error('Multiple selectors in :not are not supported');
}
_addResult(results, cssSelector);
cssSelector = current = new CssSelector();
}
}
_addResult(results, cssSelector);
return results;
}
/**
* Unescape `\$` sequences from the CSS attribute selector.
*
* This is needed because `$` can have a special meaning in CSS selectors,
* but we might want to match an attribute that contains `$`.
* [MDN web link for more
* info](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors).
* @param attr the attribute to unescape.
* @returns the unescaped string.
*/
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;
}
/**
* Escape `$` sequences from the CSS attribute selector.
*
* This is needed because `$` can have a special meaning in CSS selectors,
* with this method we are escaping `$` with `\$'.
* [MDN web link for more
* info](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors).
* @param attr the attribute to escape.
* @returns the escaped string.
*/
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;
}
}
/**
* Reads a list of CssSelectors and allows to calculate which ones
* are contained in a given CssSelector.
*/
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);
}
}
/**
* Add an object that can be found later on by calling `match`.
* @param cssSelector A css selector
* @param callbackCtxt An opaque object that will be given to the callback of the `match` function
*/
_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;
}
/**
* Find the objects that have been added via `addSelectable`
* whose css selector is contained in the given css selector.
* @param cssSelector A css selector
* @param matchedCallback This callback will be called with the object handed into `addSelectable`
* @return boolean true if a match was found
*/
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;
}
/** @internal */
_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;
}
/** @internal */
_matchPartial(map, name, cssSelector, matchedCallback) {
if (!map || typeof name !== 'string') {
return false;
}
const nestedSelector = map.get(name);
if (!nestedSelector) {
return false;
}
// TODO(perf): get rid of recursion and measure again
// TODO(perf): don't pass the whole selector into the recursion,
// but only the not processed parts
return nestedSelector.match(cssSelector, matchedCallback);
}
}
class SelectorListContext {
selectors;
alreadyMatched = false;
constructor(selectors) {
this.selectors = selectors;
}
}
// Store context to pass back selector and context when a selector is matched
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;
}
}
// Attention:
// This file duplicates types and values from @angular/core
// so that we are able to make @angular/compiler independent of @angular/core.
// This is important to prevent a build cycle, as @angular/core needs to
// be compiled with the compiler.
// Stores the default value of `emitDistinctChangesOnly` when the `emitDistinctChangesOnly` is not
// explicitly set.
const emitDistinctChangesOnlyDefaultValue = true;
exports.ViewEncapsulation = void 0;
(function (ViewEncapsulation) {
ViewEncapsulation[ViewEncapsulation["Emulated"] = 0] = "Emulated";
// Historically the 1 value was for `Native` encapsulation which has been removed as of v11.
ViewEncapsulation[ViewEncapsulation["None"] = 2] = "None";
ViewEncapsulation[ViewEncapsulation["ShadowDom"] = 3] = "ShadowDom";
})(exports.ViewEncapsulation || (exports.ViewEncapsulation = {}));
exports.ChangeDetectionStrategy = void 0;
(function (ChangeDetectionStrategy) {
ChangeDetectionStrategy[ChangeDetectionStrategy["OnPush"] = 0] = "OnPush";
ChangeDetectionStrategy[ChangeDetectionStrategy["Default"] = 1] = "Default";
})(exports.ChangeDetectionStrategy || (exports.ChangeDetectionStrategy = {}));
/** Flags describing an input for a directive. */
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',
};
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 = {}));
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 /* SelectorFlags.CLASS */, ...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 /* SelectorFlags.CLASS */, ...selector.classNames]
: [];
if (selector.element) {
return [
1 /* SelectorFlags.NOT */ | 4 /* SelectorFlags.ELEMENT */,
selector.element,
...selector.attrs,
...classes,
];
}
else if (selector.attrs.length) {
return [1 /* SelectorFlags.NOT */ | 2 /* SelectorFlags.ATTRIBUTE */, ...selector.attrs, ...classes];
}
else {
return selector.classNames && selector.classNames.length
? [1 /* SelectorFlags.NOT */ | 8 /* SelectorFlags.CLASS */, ...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) : [];
}
/**
* A lazily created TextEncoder instance for converting strings into UTF-8 bytes
*/
let textEncoder;
/**
* Return the message id or compute it using the XLIFF1 digest.
*/
function digest$1(message) {
return message.id || computeDigest(message);
}
/**
* Compute the message id using the XLIFF1 digest.
*/
function computeDigest(message) {
return sha1(serializeNodes(message.nodes).join('') + `[${message.meaning}]`);
}
/**
* Return the message id or compute it using the XLIFF2/XMB/$localize digest.
*/
function decimalDigest(message) {
return message.id || computeDecimalDigest(message);
}
/**
* Compute the message id using the XLIFF2/XMB/$localize digest.
*/
function computeDecimalDigest(message) {
const visitor = new _SerializerIgnoreIcuExpVisitor();
const parts = message.nodes.map((a) => a.visit(visitor, null));
return computeMsgId(parts.join(''), message.meaning);
}
/**
* Serialize the i18n ast to something xml-like in order to generate an UID.
*
* The visitor is also used in the i18n parser tests
*
* @internal
*/
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));
}
/**
* Serialize the i18n ast to something xml-like in order to generate an UID.
*
* Ignore the ICU expressions so that message IDs stays identical if only the expression changes.
*
* @internal
*/
class _SerializerIgnoreIcuExpVisitor extends _SerializerVisitor {
visitIcu(icu) {
let strCases = Object.keys(icu.cases).map((k) => `${k} {${icu.cases[k].visit(this)}}`);
// Do not take the expression into account
return `{${icu.type}, ${strCases.join(', ')}}`;
}
}
/**
* Compute the SHA1 of the given string
*
* see https://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
*
* WARNING: this function has not been designed not tested with security in mind.
* DO NOT USE IT IN A SECURITY SENSITIVE CONTEXT.
*/
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);
}
// Convert the output parts to a 160-bit hexadecimal string
return toHexU32(a) + toHexU32(b) + toHexU32(c) + toHexU32(d) + toHexU32(e);
}
/**
* Convert and format a number as a string representing a 32-bit unsigned hexadecimal number.
* @param value The value to format as a string.
* @returns A hexadecimal string representing the value.
*/
function toHexU32(value) {
// unsigned right shift of zero ensures an unsigned 32-bit number
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];
}
/**
* Compute the fingerprint of the given string
*
* The output is 64 bit number encoded as a decimal string
*
* based on:
* https://github.com/google/closure-compiler/blob/master/src/com/google/javascript/jscomp/GoogleJsMessageIdGenerator.java
*/
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 ^ -1801410264;
}
return (BigInt.asUintN(32, BigInt(hi)) << BigInt(32)) | BigInt.asUintN(32, BigInt(lo));
}
function computeMsgId(msg, meaning = '') {
let msgFingerprint = fingerprint(msg);
if (meaning) {
// Rotate the 64-bit message fingerprint one bit to the left and then add the meaning
// fingerprint.
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;
// the first byte of c is reserved for the length
c += length;
if (remainder >= 4) {
a += view.getUint32(index, true);
index += 4;
if (remainder >= 8) {
b += view.getUint32(index, true);
index += 4;
// Partial 32-bit word for c
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 {
// Partial 32-bit word for b
if (remainder >= 5) {
b += view.getUint8(index++);
}
if (remainder >= 6) {
b += view.getUint8(index++) << 8;
}
if (remainder === 7) {
b += view.getUint8(index++) << 16;
}
}
}
else {
// Partial 32-bit word for a
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];
}
// Utils
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)];
}
// Rotate a 32b number left `count` position
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;
}
//// Types
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 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);
new BuiltinType(BuiltinTypeName.Int);
const NUMBER_TYPE = new BuiltinType(BuiltinTypeName.Number);
const STRING_TYPE = new BuiltinType(BuiltinTypeName.String);
new BuiltinType(BuiltinTypeName.Function);
const NONE_TYPE = new BuiltinType(BuiltinTypeName.None);
///// Expressions
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["Identical"] = 2] = "Identical";
BinaryOperator[BinaryOperator["NotIdentical"] = 3] = "NotIdentical";
BinaryOperator[BinaryOperator["Minus"] = 4] = "Minus";
BinaryOperator[BinaryOperator["Plus"] = 5] = "Plus";
BinaryOperator[BinaryOperator["Divide"] = 6] = "Divide";
BinaryOperator[BinaryOperator["Multiply"] = 7] = "Multiply";
BinaryOperator[BinaryOperator["Modulo"] = 8] = "Modulo";
BinaryOperator[BinaryOperator["And"] = 9] = "And";
BinaryOperator[BinaryOperator["Or"] = 10] = "Or";
BinaryOperator[BinaryOperator["BitwiseOr"] = 11] = "BitwiseOr";
BinaryOperator[BinaryOperator["BitwiseAnd"] = 12] = "BitwiseAnd";
BinaryOperator[BinaryOperator["Lower"] = 13] = "Lower";
BinaryOperator[BinaryOperator["LowerEquals"] = 14] = "LowerEquals";
BinaryOperator[BinaryOperator["Bigger"] = 15] = "Bigger";
BinaryOperator[BinaryOperator["BiggerEquals"] = 16] = "BiggerEquals";
BinaryOperator[BinaryOperator["NullishCoalesce"] = 17] = "NullishCoalesce";
})(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);
}
and(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.And, this, rhs, null, sourceSpan);
}
bitwiseOr(rhs, sourceSpan, parens = true) {
return new BinaryOperatorExpr(BinaryOperator.BitwiseOr, this, rhs, null, sourceSpan, parens);
}
bitwiseAnd(rhs, sourceSpan, parens = true) {
return new BinaryOperatorExpr(BinaryOperator.BitwiseAnd, this, rhs, null, sourceSpan, parens);
}
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) {
// Note: We use equals by purpose here to compare to null and undefined in JS.
// We use the typed null to allow strictNullChecks to narrow types.
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 WriteVarExpr(this.name, 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 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 WriteVarExpr extends Expression {
name;
value;
constructor(name, value, type, sourceSpan) {
super(type || value.type, sourceSpan);
this.name = name;
this.value = value;
}
isEquivalent(e) {
return e instanceof WriteVarExpr && this.name === e.name && this.value.isEquivalent(e.value);
}
isConstant() {
return false;
}
visitExpression(visitor, context) {
return visitor.visitWriteVarExpr(this, context);
}
clone() {
return new WriteVarExpr(this.name, this.value.clone(), this.type, this.sourceSpan);
}
toDeclStmt(type, modifiers) {
return new DeclareVarStmt(this.name, this.value, type, modifiers, this.sourceSpan);
}
toConstDecl() {
return this.toDeclStmt(INFERRED_TYPE, exports.StmtModifier.Final);
}
}
class WriteKeyExpr extends Expression {
receiver;
index;
value;
constructor(receiver, index, value, type, sourceSpan) {
super(type || value.type, sourceSpan);
this.receiver = receiver;
this.index = index;
this.value = value;
}
isEquivalent(e) {
return (e instanceof WriteKeyExpr &&
this.receiver.isEquivalent(e.receiver) &&
this.index.isEquivalent(e.index) &&
this.value.isEquivalent(e.value));
}
isConstant() {
return false;
}
visitExpression(visitor, context) {
return visitor.visitWriteKeyExpr(this, context);
}
clone() {
return new WriteKeyExpr(this.receiver.clone(), this.index.clone(), this.value.clone(), this.type, this.sourceSpan);
}
}
class WritePropExpr extends Expression {
receiver;
name;
value;
constructor(receiver, name, value, type, sourceSpan) {
super(type || value.type, sourceSpan);
this.receiver = receiver;
this.name = name;
this.value = value;
}
isEquivalent(e) {
return (e instanceof WritePropExpr &&
this.receiver.isEquivalent(e.receiver) &&
this.name === e.name &&
this.value.isEquivalent(e.value));
}
isConstant() {
return false;
}
visitExpression(visitor, context) {
return visitor.visitWritePropExpr(this, context);
}
clone() {
return new WritePropExpr(this.receiver.clone(), this.name, this.value.clone(), 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;
}
// An alias for fn, which allows other logic to handle calls and property reads together.
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 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;
// If `rawText` is not provided, "fake" the raw string by escaping the following sequences:
// - "\" would otherwise indicate that the next character is a control character.
// - "`" and "${" are template string control sequences that would otherwise prematurely
// indicate the end of the template literal element.
// Note that we can't rely on the `sourceSpan` here, because it may be incorrect (see
// https://github.com/angular/angular/pull/60267#discussion_r1986402524).
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;
/**
* Create a new instance of a `PlaceholderPiece`.
*
* @param text the name of this placeholder (e.g. `PH_1`).
* @param sourceSpan the location of this placeholder in its localized message the source code.
* @param associatedMessage reference to another message that this placeholder is associated with.
* The `associatedMessage` is mainly used to provide a relationship to an ICU message that has
* been extracted out from the message containing the placeholder.
*/
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 e instanceof LocalizedString && this.message === e.message;
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);
}
/**
* Serialize the given `meta` and `messagePart` into "cooked" and "raw" strings that can be used
* in a `$localize` tagged string. The format of the metadata is the same as that parsed by
* `parseI18nMeta()`.
*
* @param meta The metadata to serialize
* @param messagePart The first part of the tagged string
*/
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);
}
/**
* Serialize the given `placeholderName` and `messagePart` into "cooked" and "raw" strings that
* can be used in a `$localize` tagged string.
*
* The format is `:<placeholder-name>[@@<associated-id>]:`.
*
* The `associated-id` is the message id of the (usually an ICU) message to which this placeholder
* refers.
*
* @param partIndex The index of the message part to serialize.
*/
serializeI18nTemplatePart(partIndex) {
const placeholder = this.placeHolderNames[partIndex - 1];
const messagePart = this.messageParts[partIndex];
let metaBlock = plac