UNPKG

@angular/compiler

Version:

Angular - the compiler library

1,235 lines (1,229 loc) 1.36 MB
/** * @license Angular v13.0.0-rc.0 * (c) 2010-2021 Google LLC. https://angular.io/ * License: MIT */ /** * @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.io/license */ 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) { if (elementName[0] != ':') { return [null, elementName]; } const colonIndex = elementName.indexOf(':', 1); if (colonIndex === -1) { throw new Error(`Unsupported format "${elementName}" expecting ":namespace:name"`); } return [elementName.slice(1, colonIndex), elementName.slice(colonIndex + 1)]; } // `<ng-container>` tags work the same regardless the namespace function isNgContainer(tagName) { return splitNsName(tagName)[1] === 'ng-container'; } // `<ng-content>` tags work the same regardless the namespace function isNgContent(tagName) { return splitNsName(tagName)[1] === 'ng-content'; } // `<ng-template>` tags work the same regardless the namespace 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; } /** * @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.io/license */ class HtmlTagDefinition { constructor({ closedByChildren, implicitNamespacePrefix, contentType = TagContentType.PARSABLE_DATA, closedByParent = false, isVoid = false, ignoreFirstLf = false, preventNamespaceInheritance = false } = {}) { this.closedByChildren = {}; this.closedByParent = false; this.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; } 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; // see https://www.w3.org/TR/html51/syntax.html#optional-tags // This implementation does not fully conform to the HTML5 spec. let TAG_DEFINITIONS; function getHtmlTagDefinition(tagName) { if (!TAG_DEFINITIONS) { _DEFAULT_TAG_DEFINITION = new HtmlTagDefinition(); TAG_DEFINITIONS = { '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({ // Usually the implicit namespace here would be redundant since it will be inherited from // the parent `svg`, but we have to do it for `foreignObject`, because the way the parser // works is that the parent node of an end tag is its own start tag which means that // the `preventNamespaceInheritance` on `foreignObject` would have it default to the // implicit namespace which is `html`, unless specified otherwise. implicitNamespacePrefix: 'svg', // We want to prevent children of foreignObject from inheriting its namespace, because // the point of the element is to allow nodes from other namespaces to be inserted. 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({ // The browser supports two separate `title` tags which have to use // a different content type: `HTMLTitleElement` and `SVGTitleElement` contentType: { default: TagContentType.ESCAPABLE_RAW_TEXT, svg: TagContentType.PARSABLE_DATA } }), 'textarea': new HtmlTagDefinition({ contentType: TagContentType.ESCAPABLE_RAW_TEXT, ignoreFirstLf: true }), }; } // We have to make both a case-sensitive and a case-insesitive lookup, because // HTML tag names are case insensitive, whereas some SVG tags are case sensitive. return TAG_DEFINITIONS[tagName] ?? TAG_DEFINITIONS[tagName.toLowerCase()] ?? _DEFAULT_TAG_DEFINITION; } /** * @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.io/license */ 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 { constructor() { this.element = null; this.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', ''] * ``` */ this.attrs = []; this.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 /* 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 /* TAG */]; if (tag) { const prefix = match[3 /* PREFIX */]; if (prefix === '#') { // #hash current.addAttribute('id', tag.substr(1)); } else if (prefix === '.') { // Class current.addClassName(tag.substr(1)); } else { // Element current.setElement(tag); } } const attribute = match[4 /* ATTRIBUTE */]; if (attribute) { current.addAttribute(current.unescapeAttribute(attribute), match[6 /* ATTRIBUTE_VALUE */]); } if (match[7 /* NOT_END */]) { inNot = false; current = cssSelector; } if (match[8 /* 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; } /** Gets a template string for an element that matches the selector. */ getMatchingElementTemplate() { const tagName = this.element || 'div'; const classAttr = this.classNames.length > 0 ? ` class="${this.classNames.join(' ')}"` : ''; let attrs = ''; for (let i = 0; i < this.attrs.length; i += 2) { const attrName = this.attrs[i]; const attrValue = this.attrs[i + 1] !== '' ? `="${this.attrs[i + 1]}"` : ''; attrs += ` ${attrName}${attrValue}`; } return getHtmlTagDefinition(tagName).isVoid ? `<${tagName}${classAttr}${attrs}/>` : `<${tagName}${classAttr}${attrs}></${tagName}>`; } 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 { constructor() { this._elementMap = new Map(); this._elementPartialMap = new Map(); this._classMap = new Map(); this._classPartialMap = new Map(); this._attrValueMap = new Map(); this._attrValuePartialMap = new Map(); this._listContexts = []; } static createNotMatcher(notSelectors) { const notMatcher = new SelectorMatcher(); notMatcher.addSelectables(notSelectors, null); return notMatcher; } 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 { constructor(selectors) { this.selectors = selectors; this.alreadyMatched = false; } } // Store context to pass back selector and context when a selector is matched class SelectorContext { 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; } } /** * @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.io/license */ const createInject = makeMetadataFactory('Inject', (token) => ({ token })); const createInjectionToken = makeMetadataFactory('InjectionToken', (desc) => ({ _desc: desc, ɵprov: undefined })); const createAttribute = makeMetadataFactory('Attribute', (attributeName) => ({ attributeName })); // Stores the default value of `emitDistinctChangesOnly` when the `emitDistinctChangesOnly` is not // explicitly set. const emitDistinctChangesOnlyDefaultValue = true; const createContentChildren = makeMetadataFactory('ContentChildren', (selector, data = {}) => ({ selector, first: false, isViewQuery: false, descendants: false, emitDistinctChangesOnly: emitDistinctChangesOnlyDefaultValue, ...data })); const createContentChild = makeMetadataFactory('ContentChild', (selector, data = {}) => ({ selector, first: true, isViewQuery: false, descendants: true, ...data })); const createViewChildren = makeMetadataFactory('ViewChildren', (selector, data = {}) => ({ selector, first: false, isViewQuery: true, descendants: true, emitDistinctChangesOnly: emitDistinctChangesOnlyDefaultValue, ...data })); const createViewChild = makeMetadataFactory('ViewChild', (selector, data) => ({ selector, first: true, isViewQuery: true, descendants: true, ...data })); const createDirective = makeMetadataFactory('Directive', (dir = {}) => dir); var ViewEncapsulation; (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"; })(ViewEncapsulation || (ViewEncapsulation = {})); var ChangeDetectionStrategy; (function (ChangeDetectionStrategy) { ChangeDetectionStrategy[ChangeDetectionStrategy["OnPush"] = 0] = "OnPush"; ChangeDetectionStrategy[ChangeDetectionStrategy["Default"] = 1] = "Default"; })(ChangeDetectionStrategy || (ChangeDetectionStrategy = {})); const createComponent = makeMetadataFactory('Component', (c = {}) => ({ changeDetection: ChangeDetectionStrategy.Default, ...c })); const createPipe = makeMetadataFactory('Pipe', (p) => ({ pure: true, ...p })); const createInput = makeMetadataFactory('Input', (bindingPropertyName) => ({ bindingPropertyName })); const createOutput = makeMetadataFactory('Output', (bindingPropertyName) => ({ bindingPropertyName })); const createHostBinding = makeMetadataFactory('HostBinding', (hostPropertyName) => ({ hostPropertyName })); const createHostListener = makeMetadataFactory('HostListener', (eventName, args) => ({ eventName, args })); const createNgModule = makeMetadataFactory('NgModule', (ngModule) => ngModule); const createInjectable = makeMetadataFactory('Injectable', (injectable = {}) => injectable); const CUSTOM_ELEMENTS_SCHEMA = { name: 'custom-elements' }; const NO_ERRORS_SCHEMA = { name: 'no-errors-schema' }; const createOptional = makeMetadataFactory('Optional'); const createSelf = makeMetadataFactory('Self'); const createSkipSelf = makeMetadataFactory('SkipSelf'); const createHost = makeMetadataFactory('Host'); 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 = {})); var MissingTranslationStrategy; (function (MissingTranslationStrategy) { MissingTranslationStrategy[MissingTranslationStrategy["Error"] = 0] = "Error"; MissingTranslationStrategy[MissingTranslationStrategy["Warning"] = 1] = "Warning"; MissingTranslationStrategy[MissingTranslationStrategy["Ignore"] = 2] = "Ignore"; })(MissingTranslationStrategy || (MissingTranslationStrategy = {})); function makeMetadataFactory(name, props) { // This must be declared as a function, not a fat arrow, so that ES2015 devmode produces code // that works with the static_reflector.ts in the ViewEngine compiler. // In particular, `_registerDecoratorOrConstructor` assumes that the value returned here can be // new'ed. function factory(...args) { const values = props ? props(...args) : {}; return { ngMetadataName: name, ...values, }; } factory.isTypeOf = (obj) => obj && obj.ngMetadataName === name; factory.ngMetadataName = name; return factory; } function parserSelectorToSimpleSelector(selector) { const classes = selector.classNames && selector.classNames.length ? [8 /* 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 /* CLASS */, ...selector.classNames] : []; if (selector.element) { return [ 1 /* NOT */ | 4 /* ELEMENT */, selector.element, ...selector.attrs, ...classes ]; } else if (selector.attrs.length) { return [1 /* NOT */ | 2 /* ATTRIBUTE */, ...selector.attrs, ...classes]; } else { return selector.classNames && selector.classNames.length ? [1 /* NOT */ | 8 /* 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) : []; } var core = /*#__PURE__*/Object.freeze({ __proto__: null, createInject: createInject, createInjectionToken: createInjectionToken, createAttribute: createAttribute, emitDistinctChangesOnlyDefaultValue: emitDistinctChangesOnlyDefaultValue, createContentChildren: createContentChildren, createContentChild: createContentChild, createViewChildren: createViewChildren, createViewChild: createViewChild, createDirective: createDirective, get ViewEncapsulation () { return ViewEncapsulation; }, get ChangeDetectionStrategy () { return ChangeDetectionStrategy; }, createComponent: createComponent, createPipe: createPipe, createInput: createInput, createOutput: createOutput, createHostBinding: createHostBinding, createHostListener: createHostListener, createNgModule: createNgModule, createInjectable: createInjectable, CUSTOM_ELEMENTS_SCHEMA: CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA: NO_ERRORS_SCHEMA, createOptional: createOptional, createSelf: createSelf, createSkipSelf: createSkipSelf, createHost: createHost, Type: Type$1, get SecurityContext () { return SecurityContext; }, get MissingTranslationStrategy () { return MissingTranslationStrategy; }, parseSelectorToR3Selector: parseSelectorToR3Selector }); /** * @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.io/license */ //// Types var TypeModifier; (function (TypeModifier) { TypeModifier[TypeModifier["Const"] = 0] = "Const"; })(TypeModifier || (TypeModifier = {})); class Type { constructor(modifiers = []) { this.modifiers = modifiers; } hasModifier(modifier) { return this.modifiers.indexOf(modifier) !== -1; } } 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 { constructor(name, modifiers) { super(modifiers); this.name = name; } visitType(visitor, context) { return visitor.visitBuiltinType(this, context); } } class ExpressionType extends Type { 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 { constructor(of, modifiers) { super(modifiers); this.of = of; } visitType(visitor, context) { return visitor.visitArrayType(this, context); } } class MapType extends Type { constructor(valueType, modifiers) { super(modifiers); this.valueType = valueType || null; } visitType(visitor, context) { return visitor.visitMapType(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); ///// 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["BitwiseAnd"] = 11] = "BitwiseAnd"; BinaryOperator[BinaryOperator["Lower"] = 12] = "Lower"; BinaryOperator[BinaryOperator["LowerEquals"] = 13] = "LowerEquals"; BinaryOperator[BinaryOperator["Bigger"] = 14] = "Bigger"; BinaryOperator[BinaryOperator["BiggerEquals"] = 15] = "BiggerEquals"; BinaryOperator[BinaryOperator["NullishCoalesce"] = 16] = "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 { 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); } 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); } cast(type, sourceSpan) { return new CastExpr(this, type, sourceSpan); } nullishCoalesce(rhs, sourceSpan) { return new BinaryOperatorExpr(BinaryOperator.NullishCoalesce, this, rhs, null, sourceSpan); } toStmt() { return new ExpressionStatement(this, null); } } var BuiltinVar; (function (BuiltinVar) { BuiltinVar[BuiltinVar["This"] = 0] = "This"; BuiltinVar[BuiltinVar["Super"] = 1] = "Super"; BuiltinVar[BuiltinVar["CatchError"] = 2] = "CatchError"; BuiltinVar[BuiltinVar["CatchStack"] = 3] = "CatchStack"; })(BuiltinVar || (BuiltinVar = {})); class ReadVarExpr extends Expression { constructor(name, type, sourceSpan) { super(type, sourceSpan); if (typeof name === 'string') { this.name = name; this.builtin = null; } else { this.name = null; this.builtin = name; } } isEquivalent(e) { return e instanceof ReadVarExpr && this.name === e.name && this.builtin === e.builtin; } isConstant() { return false; } visitExpression(visitor, context) { return visitor.visitReadVarExpr(this, context); } set(value) { if (!this.name) { throw new Error(`Built in variable ${this.builtin} can not be assigned to.`); } return new WriteVarExpr(this.name, value, null, this.sourceSpan); } } class TypeofExpr extends Expression { 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(); } } class WrappedNodeExpr extends Expression { 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); } } class WriteVarExpr extends Expression { 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); } toDeclStmt(type, modifiers) { return new DeclareVarStmt(this.name, this.value, type, modifiers, this.sourceSpan); } toConstDecl() { return this.toDeclStmt(INFERRED_TYPE, [StmtModifier.Final]); } } class WriteKeyExpr extends Expression { 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); } } class WritePropExpr extends Expression { 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); } } var BuiltinMethod; (function (BuiltinMethod) { BuiltinMethod[BuiltinMethod["ConcatArray"] = 0] = "ConcatArray"; BuiltinMethod[BuiltinMethod["SubscribeObservable"] = 1] = "SubscribeObservable"; BuiltinMethod[BuiltinMethod["Bind"] = 2] = "Bind"; })(BuiltinMethod || (BuiltinMethod = {})); class InvokeFunctionExpr extends Expression { constructor(fn, args, type, sourceSpan, pure = false) { super(type, sourceSpan); this.fn = fn; this.args = args; this.pure = pure; } 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); } } class TaggedTemplateExpr extends Expression { constructor(tag, template, type, sourceSpan) { super(type, sourceSpan); this.tag = tag; this.template = template; } isEquivalent(e) { return e instanceof TaggedTemplateExpr && this.tag.isEquivalent(e.tag) && areAllEquivalentPredicate(this.template.elements, e.template.elements, (a, b) => a.text === b.text) && areAllEquivalent(this.template.expressions, e.template.expressions); } isConstant() { return false; } visitExpression(visitor, context) { return visitor.visitTaggedTemplateExpr(this, context); } } class InstantiateExpr extends Expression { 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); } } class LiteralExpr extends Expression { 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); } } class TemplateLiteral { constructor(elements, expressions) { this.elements = elements; this.expressions = expressions; } } class TemplateLiteralElement { constructor(text, sourceSpan, rawText) { this.text = text; this.sourceSpan = sourceSpan; // If `rawText` is not provided, try to extract the raw string from its // associated `sourceSpan`. If that is also not available, "fake" the raw // string instead by escaping the following control 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. this.rawText = rawText ?? sourceSpan?.toString() ?? escapeForTemplateLiteral(escapeSlashes(text)); } } class MessagePiece { constructor(text, sourceSpan) { this.text = text; this.sourceSpan = sourceSpan; } } class LiteralPiece extends MessagePiece { } class PlaceholderPiece extends MessagePiece { } class LocalizedString extends Expression { 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); } /** * 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() { const MEANING_SEPARATOR = '|'; const ID_SEPARATOR = '@@'; const LEGACY_ID_INDICATOR = '␟'; let metaBlock = this.metaBlock.description || ''; if (this.metaBlock.meaning) { metaBlock = `${this.metaBlock.meaning}${MEANING_SEPARATOR}${metaBlock}`; } if (this.metaBlock.customId) { metaBlock = `${metaBlock}${ID_SEPARATOR}${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. * * @param placeholderName The placeholder name to serialize * @param messagePart The following message string after this placeholder */ serializeI18nTemplatePart(partIndex) { const placeholderName = this.placeHolderNames[partIndex - 1].text; const messagePart = this.messageParts[partIndex]; return createCookedRawString(placeholderName, 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, '$\\{'); /** * Creates a `{cooked, raw}` object from the `metaBlock` and `messagePart`. * * The `