{"version":3,"file":"compiler.mjs","sources":["../../../../../../packages/compiler/src/selector.ts","../../../../../../packages/compiler/src/core.ts","../../../../../../packages/compiler/src/i18n/digest.ts","../../../../../../packages/compiler/src/output/output_ast.ts","../../../../../../packages/compiler/src/constant_pool.ts","../../../../../../packages/compiler/src/render3/r3_identifiers.ts","../../../../../../packages/compiler/src/util.ts","../../../../../../packages/compiler/src/output/source_map.ts","../../../../../../packages/compiler/src/output/abstract_emitter.ts","../../../../../../packages/compiler/src/render3/util.ts","../../../../../../packages/compiler/src/render3/r3_factory.ts","../../../../../../packages/compiler/src/ml_parser/tags.ts","../../../../../../packages/compiler/src/render3/r3_ast.ts","../../../../../../packages/compiler/src/i18n/i18n_ast.ts","../../../../../../packages/compiler/src/i18n/serializers/serializer.ts","../../../../../../packages/compiler/src/i18n/serializers/xml_helper.ts","../../../../../../packages/compiler/src/i18n/serializers/xmb.ts","../../../../../../packages/compiler/src/render3/view/i18n/util.ts","../../../../../../packages/compiler/src/render3/view/util.ts","../../../../../../packages/compiler/src/injectable_compiler_2.ts","../../../../../../packages/compiler/src/assertions.ts","../../../../../../packages/compiler/src/ml_parser/defaults.ts","../../../../../../packages/compiler/src/chars.ts","../../../../../../packages/compiler/src/parse_util.ts","../../../../../../packages/compiler/src/output/abstract_js_emitter.ts","../../../../../../packages/compiler/src/output/output_jit_trusted_types.ts","../../../../../../packages/compiler/src/output/output_jit.ts","../../../../../../packages/compiler/src/render3/r3_injector_compiler.ts","../../../../../../packages/compiler/src/render3/r3_jit.ts","../../../../../../packages/compiler/src/render3/r3_module_compiler.ts","../../../../../../packages/compiler/src/render3/r3_pipe_compiler.ts","../../../../../../packages/compiler/src/render3/view/api.ts","../../../../../../packages/compiler/src/expression_parser/ast.ts","../../../../../../packages/compiler/src/compiler_util/expression_converter.ts","../../../../../../packages/compiler/src/schema/dom_security_schema.ts","../../../../../../packages/compiler/src/shadow_css.ts","../../../../../../packages/compiler/src/template/pipeline/ir/src/enums.ts","../../../../../../packages/compiler/src/template/pipeline/ir/src/traits.ts","../../../../../../packages/compiler/src/template/pipeline/ir/src/ops/shared.ts","../../../../../../packages/compiler/src/template/pipeline/ir/src/ops/update.ts","../../../../../../packages/compiler/src/template/pipeline/ir/src/expression.ts","../../../../../../packages/compiler/src/template/pipeline/ir/src/operations.ts","../../../../../../packages/compiler/src/template/pipeline/ir/src/handle.ts","../../../../../../packages/compiler/src/template/pipeline/ir/src/ops/create.ts","../../../../../../packages/compiler/src/template/pipeline/ir/src/ops/host.ts","../../../../../../packages/compiler/src/template/pipeline/ir/src/variable.ts","../../../../../../packages/compiler/src/template/pipeline/src/compilation.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/any_cast.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/apply_i18n_expressions.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/assign_i18n_slot_dependencies.ts","../../../../../../packages/compiler/src/template/pipeline/src/util/elements.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/attribute_extraction.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/binding_specialization.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/chaining.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/collapse_singleton_interpolations.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/conditionals.ts","../../../../../../packages/compiler/src/template/pipeline/src/conversion.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/const_collection.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/convert_i18n_bindings.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/create_defer_deps_fns.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/create_i18n_contexts.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/deduplicate_text_bindings.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/defer_configs.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/defer_resolve_targets.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/empty_elements.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/expand_safe_reads.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/extract_i18n_messages.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/generate_advance.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/generate_projection_def.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/generate_variables.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/has_const_expression_collection.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/host_style_property_parsing.ts","../../../../../../packages/compiler/src/output/map_util.ts","../../../../../../packages/compiler/src/render3/view/i18n/icu_serializer.ts","../../../../../../packages/compiler/src/expression_parser/lexer.ts","../../../../../../packages/compiler/src/expression_parser/parser.ts","../../../../../../packages/compiler/src/ml_parser/ast.ts","../../../../../../packages/compiler/src/schema/element_schema_registry.ts","../../../../../../packages/compiler/src/schema/dom_element_schema_registry.ts","../../../../../../packages/compiler/src/ml_parser/html_tags.ts","../../../../../../packages/compiler/src/i18n/serializers/placeholder.ts","../../../../../../packages/compiler/src/i18n/i18n_parser.ts","../../../../../../packages/compiler/src/i18n/parse_util.ts","../../../../../../packages/compiler/src/ml_parser/entities.ts","../../../../../../packages/compiler/src/ml_parser/lexer.ts","../../../../../../packages/compiler/src/ml_parser/parser.ts","../../../../../../packages/compiler/src/schema/trusted_types_sinks.ts","../../../../../../packages/compiler/src/render3/view/i18n/meta.ts","../../../../../../packages/compiler/src/render3/view/i18n/get_msg_utils.ts","../../../../../../packages/compiler/src/render3/view/i18n/localize_utils.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/i18n_const_collection.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/i18n_text_extraction.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/local_refs.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/namespace.ts","../../../../../../packages/compiler/src/render3/view/style_parser.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/naming.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/next_context_merging.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/ng_container.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/nonbindable.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/nullish_coalescing.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/ordering.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/parse_extracted_styles.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/phase_remove_content_selectors.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/pipe_creation.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/pipe_variadic.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/propagate_i18n_blocks.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/pure_function_extraction.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/pure_literal_structures.ts","../../../../../../packages/compiler/src/template/pipeline/src/instruction.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/reify.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/remove_empty_bindings.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/remove_i18n_contexts.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/remove_unused_i18n_attrs.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/resolve_contexts.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/resolve_dollar_event.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/resolve_i18n_element_placeholders.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/resolve_i18n_expression_placeholders.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/resolve_names.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/resolve_sanitizers.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/save_restore_view.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/slot_allocation.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/style_binding_specialization.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/temporary_variables.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/track_fn_generation.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/track_fn_optimization.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/track_variables.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/var_counting.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/variable_optimization.ts","../../../../../../packages/compiler/src/template/pipeline/src/phases/wrap_icus.ts","../../../../../../packages/compiler/src/template/pipeline/src/emit.ts","../../../../../../packages/compiler/src/template/pipeline/src/ingest.ts","../../../../../../packages/compiler/src/template/pipeline/switch/index.ts","../../../../../../packages/compiler/src/render3/view/styling_builder.ts","../../../../../../packages/compiler/src/ml_parser/html_parser.ts","../../../../../../packages/compiler/src/ml_parser/html_whitespaces.ts","../../../../../../packages/compiler/src/template_parser/binding_parser.ts","../../../../../../packages/compiler/src/style_url_resolver.ts","../../../../../../packages/compiler/src/template_parser/template_preparser.ts","../../../../../../packages/compiler/src/render3/r3_control_flow.ts","../../../../../../packages/compiler/src/render3/r3_deferred_triggers.ts","../../../../../../packages/compiler/src/render3/r3_deferred_blocks.ts","../../../../../../packages/compiler/src/render3/r3_template_transform.ts","../../../../../../packages/compiler/src/render3/view/i18n/context.ts","../../../../../../packages/compiler/src/render3/view/template.ts","../../../../../../packages/compiler/src/render3/view/compiler.ts","../../../../../../packages/compiler/src/render3/view/t2_binder.ts","../../../../../../packages/compiler/src/resource_loader.ts","../../../../../../packages/compiler/src/jit_compiler_facade.ts","../../../../../../packages/compiler/src/version.ts","../../../../../../packages/compiler/src/config.ts","../../../../../../packages/compiler/src/i18n/extractor_merger.ts","../../../../../../packages/compiler/src/ml_parser/xml_tags.ts","../../../../../../packages/compiler/src/ml_parser/xml_parser.ts","../../../../../../packages/compiler/src/i18n/serializers/xliff.ts","../../../../../../packages/compiler/src/i18n/serializers/xliff2.ts","../../../../../../packages/compiler/src/i18n/serializers/xtb.ts","../../../../../../packages/compiler/src/i18n/translation_bundle.ts","../../../../../../packages/compiler/src/i18n/i18n_html_parser.ts","../../../../../../packages/compiler/src/i18n/message_bundle.ts","../../../../../../packages/compiler/src/render3/partial/api.ts","../../../../../../packages/compiler/src/render3/r3_class_metadata_compiler.ts","../../../../../../packages/compiler/src/render3/r3_class_debug_info_compiler.ts","../../../../../../packages/compiler/src/render3/partial/class_metadata.ts","../../../../../../packages/compiler/src/render3/partial/util.ts","../../../../../../packages/compiler/src/render3/partial/directive.ts","../../../../../../packages/compiler/src/render3/partial/component.ts","../../../../../../packages/compiler/src/render3/partial/factory.ts","../../../../../../packages/compiler/src/render3/partial/injectable.ts","../../../../../../packages/compiler/src/render3/partial/injector.ts","../../../../../../packages/compiler/src/render3/partial/ng_module.ts","../../../../../../packages/compiler/src/render3/partial/pipe.ts","../../../../../../packages/compiler/src/compiler.ts","../../../../../../packages/compiler/public_api.ts","../../../../../../packages/compiler/compiler.ts","../../../../../../packages/compiler/index.ts"],"sourcesContent":["/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nconst _SELECTOR_REGEXP = new RegExp(\n '(\\\\:not\\\\()|' + // 1: \":not(\"\n '(([\\\\.\\\\#]?)[-\\\\w]+)|' + // 2: \"tag\"; 3: \".\"/\"#\";\n // \"-\" should appear first in the regexp below as FF31 parses \"[.-\\w]\" as a range\n // 4: attribute; 5: attribute_string; 6: attribute_value\n '(?:\\\\[([-.\\\\w*\\\\\\\\$]+)(?:=([\\\"\\']?)([^\\\\]\\\"\\']*)\\\\5)?\\\\])|' + // \"[name]\", \"[name=value]\",\n // \"[name=\"value\"]\",\n // \"[name='value']\"\n '(\\\\))|' + // 7: \")\"\n '(\\\\s*,\\\\s*)', // 8: \",\"\n 'g');\n\n/**\n * These offsets should match the match-groups in `_SELECTOR_REGEXP` offsets.\n */\nconst enum SelectorRegexp {\n ALL = 0, // The whole match\n NOT = 1,\n TAG = 2,\n PREFIX = 3,\n ATTRIBUTE = 4,\n ATTRIBUTE_STRING = 5,\n ATTRIBUTE_VALUE = 6,\n NOT_END = 7,\n SEPARATOR = 8,\n}\n/**\n * A css selector contains an element name,\n * css classes and attribute/value pairs with the purpose\n * of selecting subsets out of them.\n */\nexport class CssSelector {\n element: string|null = null;\n classNames: string[] = [];\n /**\n * The selectors are encoded in pairs where:\n * - even locations are attribute names\n * - odd locations are attribute values.\n *\n * Example:\n * Selector: `[key1=value1][key2]` would parse to:\n * ```\n * ['key1', 'value1', 'key2', '']\n * ```\n */\n attrs: string[] = [];\n notSelectors: CssSelector[] = [];\n\n static parse(selector: string): CssSelector[] {\n const results: CssSelector[] = [];\n const _addResult = (res: CssSelector[], cssSel: CssSelector) => {\n if (cssSel.notSelectors.length > 0 && !cssSel.element && cssSel.classNames.length == 0 &&\n cssSel.attrs.length == 0) {\n cssSel.element = '*';\n }\n res.push(cssSel);\n };\n let cssSelector = new CssSelector();\n let match: string[]|null;\n let current = cssSelector;\n let inNot = false;\n _SELECTOR_REGEXP.lastIndex = 0;\n while (match = _SELECTOR_REGEXP.exec(selector)) {\n if (match[SelectorRegexp.NOT]) {\n if (inNot) {\n throw new Error('Nesting :not in a selector is not allowed');\n }\n inNot = true;\n current = new CssSelector();\n cssSelector.notSelectors.push(current);\n }\n const tag = match[SelectorRegexp.TAG];\n if (tag) {\n const prefix = match[SelectorRegexp.PREFIX];\n if (prefix === '#') {\n // #hash\n current.addAttribute('id', tag.slice(1));\n } else if (prefix === '.') {\n // Class\n current.addClassName(tag.slice(1));\n } else {\n // Element\n current.setElement(tag);\n }\n }\n const attribute = match[SelectorRegexp.ATTRIBUTE];\n\n if (attribute) {\n current.addAttribute(\n current.unescapeAttribute(attribute), match[SelectorRegexp.ATTRIBUTE_VALUE]);\n }\n if (match[SelectorRegexp.NOT_END]) {\n inNot = false;\n current = cssSelector;\n }\n if (match[SelectorRegexp.SEPARATOR]) {\n if (inNot) {\n throw new Error('Multiple selectors in :not are not supported');\n }\n _addResult(results, cssSelector);\n cssSelector = current = new CssSelector();\n }\n }\n _addResult(results, cssSelector);\n return results;\n }\n\n /**\n * Unescape `\\$` sequences from the CSS attribute selector.\n *\n * This is needed because `$` can have a special meaning in CSS selectors,\n * but we might want to match an attribute that contains `$`.\n * [MDN web link for more\n * info](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors).\n * @param attr the attribute to unescape.\n * @returns the unescaped string.\n */\n unescapeAttribute(attr: string): string {\n let result = '';\n let escaping = false;\n for (let i = 0; i < attr.length; i++) {\n const char = attr.charAt(i);\n if (char === '\\\\') {\n escaping = true;\n continue;\n }\n if (char === '$' && !escaping) {\n throw new Error(\n `Error in attribute selector \"${attr}\". ` +\n `Unescaped \"$\" is not supported. Please escape with \"\\\\$\".`);\n }\n escaping = false;\n result += char;\n }\n return result;\n }\n\n /**\n * Escape `$` sequences from the CSS attribute selector.\n *\n * This is needed because `$` can have a special meaning in CSS selectors,\n * with this method we are escaping `$` with `\\$'.\n * [MDN web link for more\n * info](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors).\n * @param attr the attribute to escape.\n * @returns the escaped string. \n */\n escapeAttribute(attr: string): string {\n return attr.replace(/\\\\/g, '\\\\\\\\').replace(/\\$/g, '\\\\$');\n }\n\n isElementSelector(): boolean {\n return this.hasElementSelector() && this.classNames.length == 0 && this.attrs.length == 0 &&\n this.notSelectors.length === 0;\n }\n\n hasElementSelector(): boolean {\n return !!this.element;\n }\n\n setElement(element: string|null = null) {\n this.element = element;\n }\n\n getAttrs(): string[] {\n const result: string[] = [];\n if (this.classNames.length > 0) {\n result.push('class', this.classNames.join(' '));\n }\n return result.concat(this.attrs);\n }\n\n addAttribute(name: string, value: string = '') {\n this.attrs.push(name, value && value.toLowerCase() || '');\n }\n\n addClassName(name: string) {\n this.classNames.push(name.toLowerCase());\n }\n\n toString(): string {\n let res: string = this.element || '';\n if (this.classNames) {\n this.classNames.forEach(klass => res += `.${klass}`);\n }\n if (this.attrs) {\n for (let i = 0; i < this.attrs.length; i += 2) {\n const name = this.escapeAttribute(this.attrs[i]);\n const value = this.attrs[i + 1];\n res += `[${name}${value ? '=' + value : ''}]`;\n }\n }\n this.notSelectors.forEach(notSelector => res += `:not(${notSelector})`);\n return res;\n }\n}\n\n/**\n * Reads a list of CssSelectors and allows to calculate which ones\n * are contained in a given CssSelector.\n */\nexport class SelectorMatcher {\n static createNotMatcher(notSelectors: CssSelector[]): SelectorMatcher {\n const notMatcher = new SelectorMatcher();\n notMatcher.addSelectables(notSelectors, null);\n return notMatcher;\n }\n\n private _elementMap = new Map[]>();\n private _elementPartialMap = new Map>();\n private _classMap = new Map[]>();\n private _classPartialMap = new Map>();\n private _attrValueMap = new Map[]>>();\n private _attrValuePartialMap = new Map>>();\n private _listContexts: SelectorListContext[] = [];\n\n addSelectables(cssSelectors: CssSelector[], callbackCtxt?: T) {\n let listContext: SelectorListContext = null!;\n if (cssSelectors.length > 1) {\n listContext = new SelectorListContext(cssSelectors);\n this._listContexts.push(listContext);\n }\n for (let i = 0; i < cssSelectors.length; i++) {\n this._addSelectable(cssSelectors[i], callbackCtxt as T, listContext);\n }\n }\n\n /**\n * Add an object that can be found later on by calling `match`.\n * @param cssSelector A css selector\n * @param callbackCtxt An opaque object that will be given to the callback of the `match` function\n */\n private _addSelectable(\n cssSelector: CssSelector, callbackCtxt: T, listContext: SelectorListContext) {\n let matcher: SelectorMatcher = this;\n const element = cssSelector.element;\n const classNames = cssSelector.classNames;\n const attrs = cssSelector.attrs;\n const selectable = new SelectorContext(cssSelector, callbackCtxt, listContext);\n\n if (element) {\n const isTerminal = attrs.length === 0 && classNames.length === 0;\n if (isTerminal) {\n this._addTerminal(matcher._elementMap, element, selectable);\n } else {\n matcher = this._addPartial(matcher._elementPartialMap, element);\n }\n }\n\n if (classNames) {\n for (let i = 0; i < classNames.length; i++) {\n const isTerminal = attrs.length === 0 && i === classNames.length - 1;\n const className = classNames[i];\n if (isTerminal) {\n this._addTerminal(matcher._classMap, className, selectable);\n } else {\n matcher = this._addPartial(matcher._classPartialMap, className);\n }\n }\n }\n\n if (attrs) {\n for (let i = 0; i < attrs.length; i += 2) {\n const isTerminal = i === attrs.length - 2;\n const name = attrs[i];\n const value = attrs[i + 1];\n if (isTerminal) {\n const terminalMap = matcher._attrValueMap;\n let terminalValuesMap = terminalMap.get(name);\n if (!terminalValuesMap) {\n terminalValuesMap = new Map[]>();\n terminalMap.set(name, terminalValuesMap);\n }\n this._addTerminal(terminalValuesMap, value, selectable);\n } else {\n const partialMap = matcher._attrValuePartialMap;\n let partialValuesMap = partialMap.get(name);\n if (!partialValuesMap) {\n partialValuesMap = new Map>();\n partialMap.set(name, partialValuesMap);\n }\n matcher = this._addPartial(partialValuesMap, value);\n }\n }\n }\n }\n\n private _addTerminal(\n map: Map[]>, name: string, selectable: SelectorContext) {\n let terminalList = map.get(name);\n if (!terminalList) {\n terminalList = [];\n map.set(name, terminalList);\n }\n terminalList.push(selectable);\n }\n\n private _addPartial(map: Map>, name: string): SelectorMatcher {\n let matcher = map.get(name);\n if (!matcher) {\n matcher = new SelectorMatcher();\n map.set(name, matcher);\n }\n return matcher;\n }\n\n /**\n * Find the objects that have been added via `addSelectable`\n * whose css selector is contained in the given css selector.\n * @param cssSelector A css selector\n * @param matchedCallback This callback will be called with the object handed into `addSelectable`\n * @return boolean true if a match was found\n */\n match(cssSelector: CssSelector, matchedCallback: ((c: CssSelector, a: T) => void)|null): boolean {\n let result = false;\n const element = cssSelector.element!;\n const classNames = cssSelector.classNames;\n const attrs = cssSelector.attrs;\n\n for (let i = 0; i < this._listContexts.length; i++) {\n this._listContexts[i].alreadyMatched = false;\n }\n\n result = this._matchTerminal(this._elementMap, element, cssSelector, matchedCallback) || result;\n result = this._matchPartial(this._elementPartialMap, element, cssSelector, matchedCallback) ||\n result;\n\n if (classNames) {\n for (let i = 0; i < classNames.length; i++) {\n const className = classNames[i];\n result =\n this._matchTerminal(this._classMap, className, cssSelector, matchedCallback) || result;\n result =\n this._matchPartial(this._classPartialMap, className, cssSelector, matchedCallback) ||\n result;\n }\n }\n\n if (attrs) {\n for (let i = 0; i < attrs.length; i += 2) {\n const name = attrs[i];\n const value = attrs[i + 1];\n\n const terminalValuesMap = this._attrValueMap.get(name)!;\n if (value) {\n result =\n this._matchTerminal(terminalValuesMap, '', cssSelector, matchedCallback) || result;\n }\n result =\n this._matchTerminal(terminalValuesMap, value, cssSelector, matchedCallback) || result;\n\n const partialValuesMap = this._attrValuePartialMap.get(name)!;\n if (value) {\n result = this._matchPartial(partialValuesMap, '', cssSelector, matchedCallback) || result;\n }\n result =\n this._matchPartial(partialValuesMap, value, cssSelector, matchedCallback) || result;\n }\n }\n return result;\n }\n\n /** @internal */\n _matchTerminal(\n map: Map[]>, name: string, cssSelector: CssSelector,\n matchedCallback: ((c: CssSelector, a: any) => void)|null): boolean {\n if (!map || typeof name !== 'string') {\n return false;\n }\n\n let selectables: SelectorContext[] = map.get(name) || [];\n const starSelectables: SelectorContext[] = map.get('*')!;\n if (starSelectables) {\n selectables = selectables.concat(starSelectables);\n }\n if (selectables.length === 0) {\n return false;\n }\n let selectable: SelectorContext;\n let result = false;\n for (let i = 0; i < selectables.length; i++) {\n selectable = selectables[i];\n result = selectable.finalize(cssSelector, matchedCallback) || result;\n }\n return result;\n }\n\n /** @internal */\n _matchPartial(\n map: Map>, name: string, cssSelector: CssSelector,\n matchedCallback: ((c: CssSelector, a: any) => void)|null): boolean {\n if (!map || typeof name !== 'string') {\n return false;\n }\n\n const nestedSelector = map.get(name);\n if (!nestedSelector) {\n return false;\n }\n // TODO(perf): get rid of recursion and measure again\n // TODO(perf): don't pass the whole selector into the recursion,\n // but only the not processed parts\n return nestedSelector.match(cssSelector, matchedCallback);\n }\n}\n\n\nexport class SelectorListContext {\n alreadyMatched: boolean = false;\n\n constructor(public selectors: CssSelector[]) {}\n}\n\n// Store context to pass back selector and context when a selector is matched\nexport class SelectorContext {\n notSelectors: CssSelector[];\n\n constructor(\n public selector: CssSelector, public cbContext: T, public listContext: SelectorListContext) {\n this.notSelectors = selector.notSelectors;\n }\n\n finalize(cssSelector: CssSelector, callback: ((c: CssSelector, a: T) => void)|null): boolean {\n let result = true;\n if (this.notSelectors.length > 0 && (!this.listContext || !this.listContext.alreadyMatched)) {\n const notMatcher = SelectorMatcher.createNotMatcher(this.notSelectors);\n result = !notMatcher.match(cssSelector, null);\n }\n if (result && callback && (!this.listContext || !this.listContext.alreadyMatched)) {\n if (this.listContext) {\n this.listContext.alreadyMatched = true;\n }\n callback(this.selector, this.cbContext);\n }\n return result;\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n// Attention:\n// This file duplicates types and values from @angular/core\n// so that we are able to make @angular/compiler independent of @angular/core.\n// This is important to prevent a build cycle, as @angular/core needs to\n// be compiled with the compiler.\n\nimport {CssSelector} from './selector';\n\n// Stores the default value of `emitDistinctChangesOnly` when the `emitDistinctChangesOnly` is not\n// explicitly set.\nexport const emitDistinctChangesOnlyDefaultValue = true;\n\nexport enum ViewEncapsulation {\n Emulated = 0,\n // Historically the 1 value was for `Native` encapsulation which has been removed as of v11.\n None = 2,\n ShadowDom = 3\n}\n\nexport enum ChangeDetectionStrategy {\n OnPush = 0,\n Default = 1\n}\n\nexport interface Input {\n alias?: string;\n required?: boolean;\n transform?: (value: any) => any;\n // Note: This field is marked as `internal` in `@angular/core`, but in the compiler\n // we rely on it for JIT processing at runtime.\n isSignal: boolean;\n}\n\n/** Flags describing an input for a directive. */\nexport enum InputFlags {\n None = 0,\n SignalBased = 1 << 0,\n HasDecoratorInputTransform = 1 << 1,\n}\n\nexport interface Output {\n alias?: string;\n}\n\nexport interface HostBinding {\n hostPropertyName?: string;\n}\n\nexport interface HostListener {\n eventName?: string;\n args?: string[];\n}\n\nexport interface SchemaMetadata {\n name: string;\n}\n\nexport const CUSTOM_ELEMENTS_SCHEMA: SchemaMetadata = {\n name: 'custom-elements'\n};\n\nexport const NO_ERRORS_SCHEMA: SchemaMetadata = {\n name: 'no-errors-schema'\n};\n\nexport interface Type extends Function {\n new(...args: any[]): any;\n}\nexport const Type = Function;\n\nexport enum SecurityContext {\n NONE = 0,\n HTML = 1,\n STYLE = 2,\n SCRIPT = 3,\n URL = 4,\n RESOURCE_URL = 5,\n}\n\n/**\n * Injection flags for DI.\n */\nexport const enum InjectFlags {\n Default = 0,\n\n /**\n * Specifies that an injector should retrieve a dependency from any injector until reaching the\n * host element of the current component. (Only used with Element Injector)\n */\n Host = 1 << 0,\n /** Don't descend into ancestors of the node requesting injection. */\n Self = 1 << 1,\n /** Skip the node that is requesting injection. */\n SkipSelf = 1 << 2,\n /** Inject `defaultValue` instead if token not found. */\n Optional = 1 << 3,\n /**\n * This token is being injected into a pipe.\n * @internal\n */\n ForPipe = 1 << 4,\n}\n\nexport enum MissingTranslationStrategy {\n Error = 0,\n Warning = 1,\n Ignore = 2,\n}\n\n/**\n * Flags used to generate R3-style CSS Selectors. They are pasted from\n * core/src/render3/projection.ts because they cannot be referenced directly.\n */\nexport const enum SelectorFlags {\n /** Indicates this is the beginning of a new negative selector */\n NOT = 0b0001,\n\n /** Mode for matching attributes */\n ATTRIBUTE = 0b0010,\n\n /** Mode for matching tag names */\n ELEMENT = 0b0100,\n\n /** Mode for matching class names */\n CLASS = 0b1000,\n}\n\n// These are a copy the CSS types from core/src/render3/interfaces/projection.ts\n// They are duplicated here as they cannot be directly referenced from core.\nexport type R3CssSelector = (string|SelectorFlags)[];\nexport type R3CssSelectorList = R3CssSelector[];\n\nfunction parserSelectorToSimpleSelector(selector: CssSelector): R3CssSelector {\n const classes = selector.classNames && selector.classNames.length ?\n [SelectorFlags.CLASS, ...selector.classNames] :\n [];\n const elementName = selector.element && selector.element !== '*' ? selector.element : '';\n return [elementName, ...selector.attrs, ...classes];\n}\n\nfunction parserSelectorToNegativeSelector(selector: CssSelector): R3CssSelector {\n const classes = selector.classNames && selector.classNames.length ?\n [SelectorFlags.CLASS, ...selector.classNames] :\n [];\n\n if (selector.element) {\n return [\n SelectorFlags.NOT | SelectorFlags.ELEMENT, selector.element, ...selector.attrs, ...classes\n ];\n } else if (selector.attrs.length) {\n return [SelectorFlags.NOT | SelectorFlags.ATTRIBUTE, ...selector.attrs, ...classes];\n } else {\n return selector.classNames && selector.classNames.length ?\n [SelectorFlags.NOT | SelectorFlags.CLASS, ...selector.classNames] :\n [];\n }\n}\n\nfunction parserSelectorToR3Selector(selector: CssSelector): R3CssSelector {\n const positive = parserSelectorToSimpleSelector(selector);\n\n const negative: R3CssSelectorList = selector.notSelectors && selector.notSelectors.length ?\n selector.notSelectors.map(notSelector => parserSelectorToNegativeSelector(notSelector)) :\n [];\n\n return positive.concat(...negative);\n}\n\nexport function parseSelectorToR3Selector(selector: string|null): R3CssSelectorList {\n return selector ? CssSelector.parse(selector).map(parserSelectorToR3Selector) : [];\n}\n\n// Pasted from render3/interfaces/definition since it cannot be referenced directly\n/**\n * Flags passed into template functions to determine which blocks (i.e. creation, update)\n * should be executed.\n *\n * Typically, a template runs both the creation block and the update block on initialization and\n * subsequent runs only execute the update block. However, dynamically created views require that\n * the creation block be executed separately from the update block (for backwards compat).\n */\nexport const enum RenderFlags {\n /* Whether to run the creation block (e.g. create elements and directives) */\n Create = 0b01,\n\n /* Whether to run the update block (e.g. refresh bindings) */\n Update = 0b10\n}\n\n// Pasted from render3/interfaces/node.ts\n/**\n * A set of marker values to be used in the attributes arrays. These markers indicate that some\n * items are not regular attributes and the processing should be adapted accordingly.\n */\nexport const enum AttributeMarker {\n /**\n * Marker indicates that the following 3 values in the attributes array are:\n * namespaceUri, attributeName, attributeValue\n * in that order.\n */\n NamespaceURI = 0,\n\n /**\n * Signals class declaration.\n *\n * Each value following `Classes` designates a class name to include on the element.\n * ## Example:\n *\n * Given:\n * ```\n *
...\n * ```\n *\n * the generated code is:\n * ```\n * var _c1 = [AttributeMarker.Classes, 'foo', 'bar', 'baz'];\n * ```\n */\n Classes = 1,\n\n /**\n * Signals style declaration.\n *\n * Each pair of values following `Styles` designates a style name and value to include on the\n * element.\n * ## Example:\n *\n * Given:\n * ```\n *
...
\n * ```\n *\n * the generated code is:\n * ```\n * var _c1 = [AttributeMarker.Styles, 'width', '100px', 'height'. '200px', 'color', 'red'];\n * ```\n */\n Styles = 2,\n\n /**\n * Signals that the following attribute names were extracted from input or output bindings.\n *\n * For example, given the following HTML:\n *\n * ```\n *
\n * ```\n *\n * the generated code is:\n *\n * ```\n * var _c1 = ['moo', 'car', AttributeMarker.Bindings, 'foo', 'bar'];\n * ```\n */\n Bindings = 3,\n\n /**\n * Signals that the following attribute names were hoisted from an inline-template declaration.\n *\n * For example, given the following HTML:\n *\n * ```\n *
\n * ```\n *\n * the generated code for the `template()` instruction would include:\n *\n * ```\n * ['dirA', '', AttributeMarker.Bindings, 'dirB', AttributeMarker.Template, 'ngFor', 'ngForOf',\n * 'ngForTrackBy', 'let-value']\n * ```\n *\n * while the generated code for the `element()` instruction inside the template function would\n * include:\n *\n * ```\n * ['dirA', '', AttributeMarker.Bindings, 'dirB']\n * ```\n */\n Template = 4,\n\n /**\n * Signals that the following attribute is `ngProjectAs` and its value is a parsed `CssSelector`.\n *\n * For example, given the following HTML:\n *\n * ```\n *

\n * ```\n *\n * the generated code for the `element()` instruction would include:\n *\n * ```\n * ['attr', 'value', AttributeMarker.ProjectAs, ['', 'title', '']]\n * ```\n */\n ProjectAs = 5,\n\n /**\n * Signals that the following attribute will be translated by runtime i18n\n *\n * For example, given the following HTML:\n *\n * ```\n *
\n * ```\n *\n * the generated code is:\n *\n * ```\n * var _c1 = ['moo', 'car', AttributeMarker.I18n, 'foo', 'bar'];\n */\n I18n = 6,\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Byte} from '../util';\n\nimport * as i18n from './i18n_ast';\n\n/**\n * A lazily created TextEncoder instance for converting strings into UTF-8 bytes\n */\nlet textEncoder: TextEncoder|undefined;\n\n/**\n * Return the message id or compute it using the XLIFF1 digest.\n */\nexport function digest(message: i18n.Message): string {\n return message.id || computeDigest(message);\n}\n\n/**\n * Compute the message id using the XLIFF1 digest.\n */\nexport function computeDigest(message: i18n.Message): string {\n return sha1(serializeNodes(message.nodes).join('') + `[${message.meaning}]`);\n}\n\n/**\n * Return the message id or compute it using the XLIFF2/XMB/$localize digest.\n */\nexport function decimalDigest(message: i18n.Message): string {\n return message.id || computeDecimalDigest(message);\n}\n\n/**\n * Compute the message id using the XLIFF2/XMB/$localize digest.\n */\nexport function computeDecimalDigest(message: i18n.Message): string {\n const visitor = new _SerializerIgnoreIcuExpVisitor();\n const parts = message.nodes.map(a => a.visit(visitor, null));\n return computeMsgId(parts.join(''), message.meaning);\n}\n\n/**\n * Serialize the i18n ast to something xml-like in order to generate an UID.\n *\n * The visitor is also used in the i18n parser tests\n *\n * @internal\n */\nclass _SerializerVisitor implements i18n.Visitor {\n visitText(text: i18n.Text, context: any): any {\n return text.value;\n }\n\n visitContainer(container: i18n.Container, context: any): any {\n return `[${container.children.map(child => child.visit(this)).join(', ')}]`;\n }\n\n visitIcu(icu: i18n.Icu, context: any): any {\n const strCases =\n Object.keys(icu.cases).map((k: string) => `${k} {${icu.cases[k].visit(this)}}`);\n return `{${icu.expression}, ${icu.type}, ${strCases.join(', ')}}`;\n }\n\n visitTagPlaceholder(ph: i18n.TagPlaceholder, context: any): any {\n return ph.isVoid ?\n `` :\n `${\n ph.children.map(child => child.visit(this)).join(', ')}`;\n }\n\n visitPlaceholder(ph: i18n.Placeholder, context: any): any {\n return ph.value ? `${ph.value}` : ``;\n }\n\n visitIcuPlaceholder(ph: i18n.IcuPlaceholder, context?: any): any {\n return `${ph.value.visit(this)}`;\n }\n\n visitBlockPlaceholder(ph: i18n.BlockPlaceholder, context: any): any {\n return `${\n ph.children.map(child => child.visit(this)).join(', ')}`;\n }\n}\n\nconst serializerVisitor = new _SerializerVisitor();\n\nexport function serializeNodes(nodes: i18n.Node[]): string[] {\n return nodes.map(a => a.visit(serializerVisitor, null));\n}\n\n/**\n * Serialize the i18n ast to something xml-like in order to generate an UID.\n *\n * Ignore the ICU expressions so that message IDs stays identical if only the expression changes.\n *\n * @internal\n */\nclass _SerializerIgnoreIcuExpVisitor extends _SerializerVisitor {\n override visitIcu(icu: i18n.Icu, context: any): any {\n let strCases = Object.keys(icu.cases).map((k: string) => `${k} {${icu.cases[k].visit(this)}}`);\n // Do not take the expression into account\n return `{${icu.type}, ${strCases.join(', ')}}`;\n }\n}\n\n/**\n * Compute the SHA1 of the given string\n *\n * see https://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf\n *\n * WARNING: this function has not been designed not tested with security in mind.\n * DO NOT USE IT IN A SECURITY SENSITIVE CONTEXT.\n */\nexport function sha1(str: string): string {\n textEncoder ??= new TextEncoder();\n const utf8 = [...textEncoder.encode(str)];\n const words32 = bytesToWords32(utf8, Endian.Big);\n const len = utf8.length * 8;\n\n const w = new Uint32Array(80);\n let a = 0x67452301, b = 0xefcdab89, c = 0x98badcfe, d = 0x10325476, e = 0xc3d2e1f0;\n\n words32[len >> 5] |= 0x80 << (24 - len % 32);\n words32[((len + 64 >> 9) << 4) + 15] = len;\n\n for (let i = 0; i < words32.length; i += 16) {\n const h0 = a, h1 = b, h2 = c, h3 = d, h4 = e;\n\n for (let j = 0; j < 80; j++) {\n if (j < 16) {\n w[j] = words32[i + j];\n } else {\n w[j] = rol32(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1);\n }\n\n const fkVal = fk(j, b, c, d);\n const f = fkVal[0];\n const k = fkVal[1];\n const temp = [rol32(a, 5), f, e, k, w[j]].reduce(add32);\n e = d;\n d = c;\n c = rol32(b, 30);\n b = a;\n a = temp;\n }\n a = add32(a, h0);\n b = add32(b, h1);\n c = add32(c, h2);\n d = add32(d, h3);\n e = add32(e, h4);\n }\n\n // Convert the output parts to a 160-bit hexadecimal string\n return toHexU32(a) + toHexU32(b) + toHexU32(c) + toHexU32(d) + toHexU32(e);\n}\n\n/**\n * Convert and format a number as a string representing a 32-bit unsigned hexadecimal number.\n * @param value The value to format as a string.\n * @returns A hexadecimal string representing the value.\n */\nfunction toHexU32(value: number): string {\n // unsigned right shift of zero ensures an unsigned 32-bit number\n return (value >>> 0).toString(16).padStart(8, '0');\n}\n\nfunction fk(index: number, b: number, c: number, d: number): [number, number] {\n if (index < 20) {\n return [(b & c) | (~b & d), 0x5a827999];\n }\n\n if (index < 40) {\n return [b ^ c ^ d, 0x6ed9eba1];\n }\n\n if (index < 60) {\n return [(b & c) | (b & d) | (c & d), 0x8f1bbcdc];\n }\n\n return [b ^ c ^ d, 0xca62c1d6];\n}\n\n/**\n * Compute the fingerprint of the given string\n *\n * The output is 64 bit number encoded as a decimal string\n *\n * based on:\n * https://github.com/google/closure-compiler/blob/master/src/com/google/javascript/jscomp/GoogleJsMessageIdGenerator.java\n */\nexport function fingerprint(str: string): bigint {\n textEncoder ??= new TextEncoder();\n const utf8 = textEncoder.encode(str);\n const view = new DataView(utf8.buffer, utf8.byteOffset, utf8.byteLength);\n\n let hi = hash32(view, utf8.length, 0);\n let lo = hash32(view, utf8.length, 102072);\n\n if (hi == 0 && (lo == 0 || lo == 1)) {\n hi = hi ^ 0x130f9bef;\n lo = lo ^ -0x6b5f56d8;\n }\n\n return (BigInt.asUintN(32, BigInt(hi)) << BigInt(32)) | BigInt.asUintN(32, BigInt(lo));\n}\n\nexport function computeMsgId(msg: string, meaning: string = ''): string {\n let msgFingerprint = fingerprint(msg);\n\n if (meaning) {\n // Rotate the 64-bit message fingerprint one bit to the left and then add the meaning\n // fingerprint.\n msgFingerprint = BigInt.asUintN(64, msgFingerprint << BigInt(1)) |\n ((msgFingerprint >> BigInt(63)) & BigInt(1));\n msgFingerprint += fingerprint(meaning);\n }\n\n return BigInt.asUintN(63, msgFingerprint).toString();\n}\n\nfunction hash32(view: DataView, length: number, c: number): number {\n let a = 0x9e3779b9, b = 0x9e3779b9;\n let index = 0;\n\n const end = length - 12;\n for (; index <= end; index += 12) {\n a += view.getUint32(index, true);\n b += view.getUint32(index + 4, true);\n c += view.getUint32(index + 8, true);\n const res = mix(a, b, c);\n a = res[0], b = res[1], c = res[2];\n }\n\n const remainder = length - index;\n\n // the first byte of c is reserved for the length\n c += length;\n\n if (remainder >= 4) {\n a += view.getUint32(index, true);\n index += 4;\n\n if (remainder >= 8) {\n b += view.getUint32(index, true);\n index += 4;\n\n // Partial 32-bit word for c\n if (remainder >= 9) {\n c += view.getUint8(index++) << 8;\n }\n if (remainder >= 10) {\n c += view.getUint8(index++) << 16;\n }\n if (remainder === 11) {\n c += view.getUint8(index++) << 24;\n }\n } else {\n // Partial 32-bit word for b\n if (remainder >= 5) {\n b += view.getUint8(index++);\n }\n if (remainder >= 6) {\n b += view.getUint8(index++) << 8;\n }\n if (remainder === 7) {\n b += view.getUint8(index++) << 16;\n }\n }\n } else {\n // Partial 32-bit word for a\n if (remainder >= 1) {\n a += view.getUint8(index++);\n }\n if (remainder >= 2) {\n a += view.getUint8(index++) << 8;\n }\n if (remainder === 3) {\n a += view.getUint8(index++) << 16;\n }\n }\n\n return mix(a, b, c)[2];\n}\n\n// clang-format off\nfunction mix(a: number, b: number, c: number): [number, number, number] {\n a -= b; a -= c; a ^= c >>> 13;\n b -= c; b -= a; b ^= a << 8;\n c -= a; c -= b; c ^= b >>> 13;\n a -= b; a -= c; a ^= c >>> 12;\n b -= c; b -= a; b ^= a << 16;\n c -= a; c -= b; c ^= b >>> 5;\n a -= b; a -= c; a ^= c >>> 3;\n b -= c; b -= a; b ^= a << 10;\n c -= a; c -= b; c ^= b >>> 15;\n return [a, b, c];\n}\n// clang-format on\n\n// Utils\n\nenum Endian {\n Little,\n Big,\n}\n\nfunction add32(a: number, b: number): number {\n return add32to64(a, b)[1];\n}\n\nfunction add32to64(a: number, b: number): [number, number] {\n const low = (a & 0xffff) + (b & 0xffff);\n const high = (a >>> 16) + (b >>> 16) + (low >>> 16);\n return [high >>> 16, (high << 16) | (low & 0xffff)];\n}\n\n// Rotate a 32b number left `count` position\nfunction rol32(a: number, count: number): number {\n return (a << count) | (a >>> (32 - count));\n}\n\nfunction bytesToWords32(bytes: Byte[], endian: Endian): number[] {\n const size = (bytes.length + 3) >>> 2;\n const words32 = [];\n\n for (let i = 0; i < size; i++) {\n words32[i] = wordAt(bytes, i * 4, endian);\n }\n\n return words32;\n}\n\nfunction byteAt(bytes: Byte[], index: number): Byte {\n return index >= bytes.length ? 0 : bytes[index];\n}\n\nfunction wordAt(bytes: Byte[], index: number, endian: Endian): number {\n let word = 0;\n if (endian === Endian.Big) {\n for (let i = 0; i < 4; i++) {\n word += byteAt(bytes, index + i) << (24 - 8 * i);\n }\n } else {\n for (let i = 0; i < 4; i++) {\n word += byteAt(bytes, index + i) << 8 * i;\n }\n }\n return word;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {computeMsgId} from '../i18n/digest';\nimport {Message} from '../i18n/i18n_ast';\nimport {ParseSourceSpan} from '../parse_util';\nimport {I18nMeta} from '../render3/view/i18n/meta';\n\n//// Types\nexport enum TypeModifier {\n None = 0,\n Const = 1 << 0,\n}\n\nexport abstract class Type {\n constructor(public modifiers: TypeModifier = TypeModifier.None) {}\n abstract visitType(visitor: TypeVisitor, context: any): any;\n\n hasModifier(modifier: TypeModifier): boolean {\n return (this.modifiers & modifier) !== 0;\n }\n}\n\nexport enum BuiltinTypeName {\n Dynamic,\n Bool,\n String,\n Int,\n Number,\n Function,\n Inferred,\n None,\n}\n\nexport class BuiltinType extends Type {\n constructor(public name: BuiltinTypeName, modifiers?: TypeModifier) {\n super(modifiers);\n }\n override visitType(visitor: TypeVisitor, context: any): any {\n return visitor.visitBuiltinType(this, context);\n }\n}\n\nexport class ExpressionType extends Type {\n constructor(\n public value: Expression, modifiers?: TypeModifier, public typeParams: Type[]|null = null) {\n super(modifiers);\n }\n override visitType(visitor: TypeVisitor, context: any): any {\n return visitor.visitExpressionType(this, context);\n }\n}\n\n\nexport class ArrayType extends Type {\n constructor(public of: Type, modifiers?: TypeModifier) {\n super(modifiers);\n }\n override visitType(visitor: TypeVisitor, context: any): any {\n return visitor.visitArrayType(this, context);\n }\n}\n\n\nexport class MapType extends Type {\n public valueType: Type|null;\n constructor(valueType: Type|null|undefined, modifiers?: TypeModifier) {\n super(modifiers);\n this.valueType = valueType || null;\n }\n override visitType(visitor: TypeVisitor, context: any): any {\n return visitor.visitMapType(this, context);\n }\n}\n\n\nexport class TransplantedType extends Type {\n constructor(readonly type: T, modifiers?: TypeModifier) {\n super(modifiers);\n }\n override visitType(visitor: TypeVisitor, context: any): any {\n return visitor.visitTransplantedType(this, context);\n }\n}\n\n\nexport const DYNAMIC_TYPE = new BuiltinType(BuiltinTypeName.Dynamic);\nexport const INFERRED_TYPE = new BuiltinType(BuiltinTypeName.Inferred);\nexport const BOOL_TYPE = new BuiltinType(BuiltinTypeName.Bool);\nexport const INT_TYPE = new BuiltinType(BuiltinTypeName.Int);\nexport const NUMBER_TYPE = new BuiltinType(BuiltinTypeName.Number);\nexport const STRING_TYPE = new BuiltinType(BuiltinTypeName.String);\nexport const FUNCTION_TYPE = new BuiltinType(BuiltinTypeName.Function);\nexport const NONE_TYPE = new BuiltinType(BuiltinTypeName.None);\n\nexport interface TypeVisitor {\n visitBuiltinType(type: BuiltinType, context: any): any;\n visitExpressionType(type: ExpressionType, context: any): any;\n visitArrayType(type: ArrayType, context: any): any;\n visitMapType(type: MapType, context: any): any;\n visitTransplantedType(type: TransplantedType, context: any): any;\n}\n\n///// Expressions\n\nexport enum UnaryOperator {\n Minus,\n Plus,\n}\n\nexport enum BinaryOperator {\n Equals,\n NotEquals,\n Identical,\n NotIdentical,\n Minus,\n Plus,\n Divide,\n Multiply,\n Modulo,\n And,\n Or,\n BitwiseOr,\n BitwiseAnd,\n Lower,\n LowerEquals,\n Bigger,\n BiggerEquals,\n NullishCoalesce,\n}\n\nexport function nullSafeIsEquivalent(\n base: T|null, other: T|null) {\n if (base == null || other == null) {\n return base == other;\n }\n return base.isEquivalent(other);\n}\n\nfunction areAllEquivalentPredicate(\n base: T[], other: T[], equivalentPredicate: (baseElement: T, otherElement: T) => boolean) {\n const len = base.length;\n if (len !== other.length) {\n return false;\n }\n for (let i = 0; i < len; i++) {\n if (!equivalentPredicate(base[i], other[i])) {\n return false;\n }\n }\n return true;\n}\n\nexport function areAllEquivalent(\n base: T[], other: T[]) {\n return areAllEquivalentPredicate(\n base, other, (baseElement: T, otherElement: T) => baseElement.isEquivalent(otherElement));\n}\n\nexport abstract class Expression {\n public type: Type|null;\n public sourceSpan: ParseSourceSpan|null;\n\n constructor(type: Type|null|undefined, sourceSpan?: ParseSourceSpan|null) {\n this.type = type || null;\n this.sourceSpan = sourceSpan || null;\n }\n\n abstract visitExpression(visitor: ExpressionVisitor, context: any): any;\n\n /**\n * Calculates whether this expression produces the same value as the given expression.\n * Note: We don't check Types nor ParseSourceSpans nor function arguments.\n */\n abstract isEquivalent(e: Expression): boolean;\n\n /**\n * Return true if the expression is constant.\n */\n abstract isConstant(): boolean;\n\n abstract clone(): Expression;\n\n prop(name: string, sourceSpan?: ParseSourceSpan|null): ReadPropExpr {\n return new ReadPropExpr(this, name, null, sourceSpan);\n }\n\n key(index: Expression, type?: Type|null, sourceSpan?: ParseSourceSpan|null): ReadKeyExpr {\n return new ReadKeyExpr(this, index, type, sourceSpan);\n }\n\n callFn(params: Expression[], sourceSpan?: ParseSourceSpan|null, pure?: boolean):\n InvokeFunctionExpr {\n return new InvokeFunctionExpr(this, params, null, sourceSpan, pure);\n }\n\n instantiate(params: Expression[], type?: Type|null, sourceSpan?: ParseSourceSpan|null):\n InstantiateExpr {\n return new InstantiateExpr(this, params, type, sourceSpan);\n }\n\n conditional(\n trueCase: Expression, falseCase: Expression|null = null,\n sourceSpan?: ParseSourceSpan|null): ConditionalExpr {\n return new ConditionalExpr(this, trueCase, falseCase, null, sourceSpan);\n }\n\n equals(rhs: Expression, sourceSpan?: ParseSourceSpan|null): BinaryOperatorExpr {\n return new BinaryOperatorExpr(BinaryOperator.Equals, this, rhs, null, sourceSpan);\n }\n notEquals(rhs: Expression, sourceSpan?: ParseSourceSpan|null): BinaryOperatorExpr {\n return new BinaryOperatorExpr(BinaryOperator.NotEquals, this, rhs, null, sourceSpan);\n }\n identical(rhs: Expression, sourceSpan?: ParseSourceSpan|null): BinaryOperatorExpr {\n return new BinaryOperatorExpr(BinaryOperator.Identical, this, rhs, null, sourceSpan);\n }\n notIdentical(rhs: Expression, sourceSpan?: ParseSourceSpan|null): BinaryOperatorExpr {\n return new BinaryOperatorExpr(BinaryOperator.NotIdentical, this, rhs, null, sourceSpan);\n }\n minus(rhs: Expression, sourceSpan?: ParseSourceSpan|null): BinaryOperatorExpr {\n return new BinaryOperatorExpr(BinaryOperator.Minus, this, rhs, null, sourceSpan);\n }\n plus(rhs: Expression, sourceSpan?: ParseSourceSpan|null): BinaryOperatorExpr {\n return new BinaryOperatorExpr(BinaryOperator.Plus, this, rhs, null, sourceSpan);\n }\n divide(rhs: Expression, sourceSpan?: ParseSourceSpan|null): BinaryOperatorExpr {\n return new BinaryOperatorExpr(BinaryOperator.Divide, this, rhs, null, sourceSpan);\n }\n multiply(rhs: Expression, sourceSpan?: ParseSourceSpan|null): BinaryOperatorExpr {\n return new BinaryOperatorExpr(BinaryOperator.Multiply, this, rhs, null, sourceSpan);\n }\n modulo(rhs: Expression, sourceSpan?: ParseSourceSpan|null): BinaryOperatorExpr {\n return new BinaryOperatorExpr(BinaryOperator.Modulo, this, rhs, null, sourceSpan);\n }\n and(rhs: Expression, sourceSpan?: ParseSourceSpan|null): BinaryOperatorExpr {\n return new BinaryOperatorExpr(BinaryOperator.And, this, rhs, null, sourceSpan);\n }\n bitwiseOr(rhs: Expression, sourceSpan?: ParseSourceSpan|null, parens: boolean = true):\n BinaryOperatorExpr {\n return new BinaryOperatorExpr(BinaryOperator.BitwiseOr, this, rhs, null, sourceSpan, parens);\n }\n bitwiseAnd(rhs: Expression, sourceSpan?: ParseSourceSpan|null, parens: boolean = true):\n BinaryOperatorExpr {\n return new BinaryOperatorExpr(BinaryOperator.BitwiseAnd, this, rhs, null, sourceSpan, parens);\n }\n or(rhs: Expression, sourceSpan?: ParseSourceSpan|null): BinaryOperatorExpr {\n return new BinaryOperatorExpr(BinaryOperator.Or, this, rhs, null, sourceSpan);\n }\n lower(rhs: Expression, sourceSpan?: ParseSourceSpan|null): BinaryOperatorExpr {\n return new BinaryOperatorExpr(BinaryOperator.Lower, this, rhs, null, sourceSpan);\n }\n lowerEquals(rhs: Expression, sourceSpan?: ParseSourceSpan|null): BinaryOperatorExpr {\n return new BinaryOperatorExpr(BinaryOperator.LowerEquals, this, rhs, null, sourceSpan);\n }\n bigger(rhs: Expression, sourceSpan?: ParseSourceSpan|null): BinaryOperatorExpr {\n return new BinaryOperatorExpr(BinaryOperator.Bigger, this, rhs, null, sourceSpan);\n }\n biggerEquals(rhs: Expression, sourceSpan?: ParseSourceSpan|null): BinaryOperatorExpr {\n return new BinaryOperatorExpr(BinaryOperator.BiggerEquals, this, rhs, null, sourceSpan);\n }\n isBlank(sourceSpan?: ParseSourceSpan|null): Expression {\n // Note: We use equals by purpose here to compare to null and undefined in JS.\n // We use the typed null to allow strictNullChecks to narrow types.\n return this.equals(TYPED_NULL_EXPR, sourceSpan);\n }\n nullishCoalesce(rhs: Expression, sourceSpan?: ParseSourceSpan|null): BinaryOperatorExpr {\n return new BinaryOperatorExpr(BinaryOperator.NullishCoalesce, this, rhs, null, sourceSpan);\n }\n\n toStmt(): Statement {\n return new ExpressionStatement(this, null);\n }\n}\n\nexport class ReadVarExpr extends Expression {\n constructor(public name: string, type?: Type|null, sourceSpan?: ParseSourceSpan|null) {\n super(type, sourceSpan);\n }\n\n override isEquivalent(e: Expression): boolean {\n return e instanceof ReadVarExpr && this.name === e.name;\n }\n\n override isConstant() {\n return false;\n }\n\n override visitExpression(visitor: ExpressionVisitor, context: any): any {\n return visitor.visitReadVarExpr(this, context);\n }\n\n override clone(): ReadVarExpr {\n return new ReadVarExpr(this.name, this.type, this.sourceSpan);\n }\n\n set(value: Expression): WriteVarExpr {\n return new WriteVarExpr(this.name, value, null, this.sourceSpan);\n }\n}\n\nexport class TypeofExpr extends Expression {\n constructor(public expr: Expression, type?: Type|null, sourceSpan?: ParseSourceSpan|null) {\n super(type, sourceSpan);\n }\n\n override visitExpression(visitor: ExpressionVisitor, context: any) {\n return visitor.visitTypeofExpr(this, context);\n }\n\n override isEquivalent(e: Expression): boolean {\n return e instanceof TypeofExpr && e.expr.isEquivalent(this.expr);\n }\n\n override isConstant(): boolean {\n return this.expr.isConstant();\n }\n\n override clone(): TypeofExpr {\n return new TypeofExpr(this.expr.clone());\n }\n}\n\nexport class WrappedNodeExpr extends Expression {\n constructor(public node: T, type?: Type|null, sourceSpan?: ParseSourceSpan|null) {\n super(type, sourceSpan);\n }\n\n override isEquivalent(e: Expression): boolean {\n return e instanceof WrappedNodeExpr && this.node === e.node;\n }\n\n override isConstant() {\n return false;\n }\n\n override visitExpression(visitor: ExpressionVisitor, context: any): any {\n return visitor.visitWrappedNodeExpr(this, context);\n }\n\n override clone(): WrappedNodeExpr {\n return new WrappedNodeExpr(this.node, this.type, this.sourceSpan);\n }\n}\n\nexport class WriteVarExpr extends Expression {\n public value: Expression;\n constructor(\n public name: string, value: Expression, type?: Type|null, sourceSpan?: ParseSourceSpan|null) {\n super(type || value.type, sourceSpan);\n this.value = value;\n }\n\n override isEquivalent(e: Expression): boolean {\n return e instanceof WriteVarExpr && this.name === e.name && this.value.isEquivalent(e.value);\n }\n\n override isConstant() {\n return false;\n }\n\n override visitExpression(visitor: ExpressionVisitor, context: any): any {\n return visitor.visitWriteVarExpr(this, context);\n }\n\n override clone(): WriteVarExpr {\n return new WriteVarExpr(this.name, this.value.clone(), this.type, this.sourceSpan);\n }\n\n toDeclStmt(type?: Type|null, modifiers?: StmtModifier): DeclareVarStmt {\n return new DeclareVarStmt(this.name, this.value, type, modifiers, this.sourceSpan);\n }\n\n toConstDecl(): DeclareVarStmt {\n return this.toDeclStmt(INFERRED_TYPE, StmtModifier.Final);\n }\n}\n\n\nexport class WriteKeyExpr extends Expression {\n public value: Expression;\n constructor(\n public receiver: Expression, public index: Expression, value: Expression, type?: Type|null,\n sourceSpan?: ParseSourceSpan|null) {\n super(type || value.type, sourceSpan);\n this.value = value;\n }\n\n override isEquivalent(e: Expression): boolean {\n return e instanceof WriteKeyExpr && this.receiver.isEquivalent(e.receiver) &&\n this.index.isEquivalent(e.index) && this.value.isEquivalent(e.value);\n }\n\n override isConstant() {\n return false;\n }\n\n override visitExpression(visitor: ExpressionVisitor, context: any): any {\n return visitor.visitWriteKeyExpr(this, context);\n }\n\n override clone(): WriteKeyExpr {\n return new WriteKeyExpr(\n this.receiver.clone(), this.index.clone(), this.value.clone(), this.type, this.sourceSpan);\n }\n}\n\n\nexport class WritePropExpr extends Expression {\n public value: Expression;\n constructor(\n public receiver: Expression, public name: string, value: Expression, type?: Type|null,\n sourceSpan?: ParseSourceSpan|null) {\n super(type || value.type, sourceSpan);\n this.value = value;\n }\n\n override isEquivalent(e: Expression): boolean {\n return e instanceof WritePropExpr && this.receiver.isEquivalent(e.receiver) &&\n this.name === e.name && this.value.isEquivalent(e.value);\n }\n\n override isConstant() {\n return false;\n }\n\n override visitExpression(visitor: ExpressionVisitor, context: any): any {\n return visitor.visitWritePropExpr(this, context);\n }\n\n override clone(): WritePropExpr {\n return new WritePropExpr(\n this.receiver.clone(), this.name, this.value.clone(), this.type, this.sourceSpan);\n }\n}\n\nexport class InvokeFunctionExpr extends Expression {\n constructor(\n public fn: Expression, public args: Expression[], type?: Type|null,\n sourceSpan?: ParseSourceSpan|null, public pure = false) {\n super(type, sourceSpan);\n }\n\n // An alias for fn, which allows other logic to handle calls and property reads together.\n get receiver(): Expression {\n return this.fn;\n }\n\n override isEquivalent(e: Expression): boolean {\n return e instanceof InvokeFunctionExpr && this.fn.isEquivalent(e.fn) &&\n areAllEquivalent(this.args, e.args) && this.pure === e.pure;\n }\n\n override isConstant() {\n return false;\n }\n\n override visitExpression(visitor: ExpressionVisitor, context: any): any {\n return visitor.visitInvokeFunctionExpr(this, context);\n }\n\n override clone(): InvokeFunctionExpr {\n return new InvokeFunctionExpr(\n this.fn.clone(), this.args.map(arg => arg.clone()), this.type, this.sourceSpan, this.pure);\n }\n}\n\n\nexport class TaggedTemplateExpr extends Expression {\n constructor(\n public tag: Expression, public template: TemplateLiteral, type?: Type|null,\n sourceSpan?: ParseSourceSpan|null) {\n super(type, sourceSpan);\n }\n\n override isEquivalent(e: Expression): boolean {\n return e instanceof TaggedTemplateExpr && this.tag.isEquivalent(e.tag) &&\n areAllEquivalentPredicate(\n this.template.elements, e.template.elements, (a, b) => a.text === b.text) &&\n areAllEquivalent(this.template.expressions, e.template.expressions);\n }\n\n override isConstant() {\n return false;\n }\n\n override visitExpression(visitor: ExpressionVisitor, context: any): any {\n return visitor.visitTaggedTemplateExpr(this, context);\n }\n\n override clone(): TaggedTemplateExpr {\n return new TaggedTemplateExpr(\n this.tag.clone(), this.template.clone(), this.type, this.sourceSpan);\n }\n}\n\n\nexport class InstantiateExpr extends Expression {\n constructor(\n public classExpr: Expression, public args: Expression[], type?: Type|null,\n sourceSpan?: ParseSourceSpan|null) {\n super(type, sourceSpan);\n }\n\n override isEquivalent(e: Expression): boolean {\n return e instanceof InstantiateExpr && this.classExpr.isEquivalent(e.classExpr) &&\n areAllEquivalent(this.args, e.args);\n }\n\n override isConstant() {\n return false;\n }\n\n override visitExpression(visitor: ExpressionVisitor, context: any): any {\n return visitor.visitInstantiateExpr(this, context);\n }\n\n override clone(): InstantiateExpr {\n return new InstantiateExpr(\n this.classExpr.clone(), this.args.map(arg => arg.clone()), this.type, this.sourceSpan);\n }\n}\n\n\nexport class LiteralExpr extends Expression {\n constructor(\n public value: number|string|boolean|null|undefined, type?: Type|null,\n sourceSpan?: ParseSourceSpan|null) {\n super(type, sourceSpan);\n }\n\n override isEquivalent(e: Expression): boolean {\n return e instanceof LiteralExpr && this.value === e.value;\n }\n\n override isConstant() {\n return true;\n }\n\n override visitExpression(visitor: ExpressionVisitor, context: any): any {\n return visitor.visitLiteralExpr(this, context);\n }\n\n override clone(): LiteralExpr {\n return new LiteralExpr(this.value, this.type, this.sourceSpan);\n }\n}\n\nexport class TemplateLiteral {\n constructor(public elements: TemplateLiteralElement[], public expressions: Expression[]) {}\n\n clone(): TemplateLiteral {\n return new TemplateLiteral(\n this.elements.map(el => el.clone()), this.expressions.map(expr => expr.clone()));\n }\n}\nexport class TemplateLiteralElement {\n rawText: string;\n constructor(public text: string, public sourceSpan?: ParseSourceSpan, rawText?: string) {\n // If `rawText` is not provided, try to extract the raw string from its\n // associated `sourceSpan`. If that is also not available, \"fake\" the raw\n // string instead by escaping the following control sequences:\n // - \"\\\" would otherwise indicate that the next character is a control character.\n // - \"`\" and \"${\" are template string control sequences that would otherwise prematurely\n // indicate the end of the template literal element.\n this.rawText =\n rawText ?? sourceSpan?.toString() ?? escapeForTemplateLiteral(escapeSlashes(text));\n }\n\n clone(): TemplateLiteralElement {\n return new TemplateLiteralElement(this.text, this.sourceSpan, this.rawText);\n }\n}\n\nexport class LiteralPiece {\n constructor(public text: string, public sourceSpan: ParseSourceSpan) {}\n}\nexport class PlaceholderPiece {\n /**\n * Create a new instance of a `PlaceholderPiece`.\n *\n * @param text the name of this placeholder (e.g. `PH_1`).\n * @param sourceSpan the location of this placeholder in its localized message the source code.\n * @param associatedMessage reference to another message that this placeholder is associated with.\n * The `associatedMessage` is mainly used to provide a relationship to an ICU message that has\n * been extracted out from the message containing the placeholder.\n */\n constructor(\n public text: string, public sourceSpan: ParseSourceSpan, public associatedMessage?: Message) {\n }\n}\n\nexport type MessagePiece = LiteralPiece|PlaceholderPiece;\n\nconst MEANING_SEPARATOR = '|';\nconst ID_SEPARATOR = '@@';\nconst LEGACY_ID_INDICATOR = '␟';\n\nexport class LocalizedString extends Expression {\n constructor(\n readonly metaBlock: I18nMeta, readonly messageParts: LiteralPiece[],\n readonly placeHolderNames: PlaceholderPiece[], readonly expressions: Expression[],\n sourceSpan?: ParseSourceSpan|null) {\n super(STRING_TYPE, sourceSpan);\n }\n\n override isEquivalent(e: Expression): boolean {\n // return e instanceof LocalizedString && this.message === e.message;\n return false;\n }\n\n override isConstant() {\n return false;\n }\n\n override visitExpression(visitor: ExpressionVisitor, context: any): any {\n return visitor.visitLocalizedString(this, context);\n }\n\n override clone(): LocalizedString {\n return new LocalizedString(\n this.metaBlock, this.messageParts, this.placeHolderNames,\n this.expressions.map(expr => expr.clone()), this.sourceSpan);\n }\n\n /**\n * Serialize the given `meta` and `messagePart` into \"cooked\" and \"raw\" strings that can be used\n * in a `$localize` tagged string. The format of the metadata is the same as that parsed by\n * `parseI18nMeta()`.\n *\n * @param meta The metadata to serialize\n * @param messagePart The first part of the tagged string\n */\n serializeI18nHead(): CookedRawString {\n let metaBlock = this.metaBlock.description || '';\n if (this.metaBlock.meaning) {\n metaBlock = `${this.metaBlock.meaning}${MEANING_SEPARATOR}${metaBlock}`;\n }\n if (this.metaBlock.customId) {\n metaBlock = `${metaBlock}${ID_SEPARATOR}${this.metaBlock.customId}`;\n }\n if (this.metaBlock.legacyIds) {\n this.metaBlock.legacyIds.forEach(legacyId => {\n metaBlock = `${metaBlock}${LEGACY_ID_INDICATOR}${legacyId}`;\n });\n }\n return createCookedRawString(\n metaBlock, this.messageParts[0].text, this.getMessagePartSourceSpan(0));\n }\n\n getMessagePartSourceSpan(i: number): ParseSourceSpan|null {\n return this.messageParts[i]?.sourceSpan ?? this.sourceSpan;\n }\n\n getPlaceholderSourceSpan(i: number): ParseSourceSpan {\n return this.placeHolderNames[i]?.sourceSpan ?? this.expressions[i]?.sourceSpan ??\n this.sourceSpan;\n }\n\n /**\n * Serialize the given `placeholderName` and `messagePart` into \"cooked\" and \"raw\" strings that\n * can be used in a `$localize` tagged string.\n *\n * The format is `:[@@]:`.\n *\n * The `associated-id` is the message id of the (usually an ICU) message to which this placeholder\n * refers.\n *\n * @param partIndex The index of the message part to serialize.\n */\n serializeI18nTemplatePart(partIndex: number): CookedRawString {\n const placeholder = this.placeHolderNames[partIndex - 1];\n const messagePart = this.messageParts[partIndex];\n let metaBlock = placeholder.text;\n if (placeholder.associatedMessage?.legacyIds.length === 0) {\n metaBlock += `${ID_SEPARATOR}${\n computeMsgId(\n placeholder.associatedMessage.messageString, placeholder.associatedMessage.meaning)}`;\n }\n return createCookedRawString(\n metaBlock, messagePart.text, this.getMessagePartSourceSpan(partIndex));\n }\n}\n\n/**\n * A structure to hold the cooked and raw strings of a template literal element, along with its\n * source-span range.\n */\nexport interface CookedRawString {\n cooked: string;\n raw: string;\n range: ParseSourceSpan|null;\n}\n\nconst escapeSlashes = (str: string): string => str.replace(/\\\\/g, '\\\\\\\\');\nconst escapeStartingColon = (str: string): string => str.replace(/^:/, '\\\\:');\nconst escapeColons = (str: string): string => str.replace(/:/g, '\\\\:');\nconst escapeForTemplateLiteral = (str: string): string =>\n str.replace(/`/g, '\\\\`').replace(/\\${/g, '$\\\\{');\n\n/**\n * Creates a `{cooked, raw}` object from the `metaBlock` and `messagePart`.\n *\n * The `raw` text must have various character sequences escaped:\n * * \"\\\" would otherwise indicate that the next character is a control character.\n * * \"`\" and \"${\" are template string control sequences that would otherwise prematurely indicate\n * the end of a message part.\n * * \":\" inside a metablock would prematurely indicate the end of the metablock.\n * * \":\" at the start of a messagePart with no metablock would erroneously indicate the start of a\n * metablock.\n *\n * @param metaBlock Any metadata that should be prepended to the string\n * @param messagePart The message part of the string\n */\nfunction createCookedRawString(\n metaBlock: string, messagePart: string, range: ParseSourceSpan|null): CookedRawString {\n if (metaBlock === '') {\n return {\n cooked: messagePart,\n raw: escapeForTemplateLiteral(escapeStartingColon(escapeSlashes(messagePart))),\n range,\n };\n } else {\n return {\n cooked: `:${metaBlock}:${messagePart}`,\n raw: escapeForTemplateLiteral(\n `:${escapeColons(escapeSlashes(metaBlock))}:${escapeSlashes(messagePart)}`),\n range,\n };\n }\n}\n\nexport class ExternalExpr extends Expression {\n constructor(\n public value: ExternalReference, type?: Type|null, public typeParams: Type[]|null = null,\n sourceSpan?: ParseSourceSpan|null) {\n super(type, sourceSpan);\n }\n\n override isEquivalent(e: Expression): boolean {\n return e instanceof ExternalExpr && this.value.name === e.value.name &&\n this.value.moduleName === e.value.moduleName && this.value.runtime === e.value.runtime;\n }\n\n override isConstant() {\n return false;\n }\n\n override visitExpression(visitor: ExpressionVisitor, context: any): any {\n return visitor.visitExternalExpr(this, context);\n }\n\n override clone(): ExternalExpr {\n return new ExternalExpr(this.value, this.type, this.typeParams, this.sourceSpan);\n }\n}\n\nexport class ExternalReference {\n constructor(public moduleName: string|null, public name: string|null, public runtime?: any|null) {\n }\n // Note: no isEquivalent method here as we use this as an interface too.\n}\n\nexport class ConditionalExpr extends Expression {\n public trueCase: Expression;\n\n constructor(\n public condition: Expression, trueCase: Expression, public falseCase: Expression|null = null,\n type?: Type|null, sourceSpan?: ParseSourceSpan|null) {\n super(type || trueCase.type, sourceSpan);\n this.trueCase = trueCase;\n }\n\n override isEquivalent(e: Expression): boolean {\n return e instanceof ConditionalExpr && this.condition.isEquivalent(e.condition) &&\n this.trueCase.isEquivalent(e.trueCase) && nullSafeIsEquivalent(this.falseCase, e.falseCase);\n }\n\n override isConstant() {\n return false;\n }\n\n override visitExpression(visitor: ExpressionVisitor, context: any): any {\n return visitor.visitConditionalExpr(this, context);\n }\n\n override clone(): ConditionalExpr {\n return new ConditionalExpr(\n this.condition.clone(), this.trueCase.clone(), this.falseCase?.clone(), this.type,\n this.sourceSpan);\n }\n}\n\nexport class DynamicImportExpr extends Expression {\n constructor(public url: string, sourceSpan?: ParseSourceSpan|null) {\n super(null, sourceSpan);\n }\n\n override isEquivalent(e: Expression): boolean {\n return e instanceof DynamicImportExpr && this.url === e.url;\n }\n\n override isConstant() {\n return false;\n }\n\n override visitExpression(visitor: ExpressionVisitor, context: any): any {\n return visitor.visitDynamicImportExpr(this, context);\n }\n\n override clone(): DynamicImportExpr {\n return new DynamicImportExpr(this.url, this.sourceSpan);\n }\n}\n\nexport class NotExpr extends Expression {\n constructor(public condition: Expression, sourceSpan?: ParseSourceSpan|null) {\n super(BOOL_TYPE, sourceSpan);\n }\n\n override isEquivalent(e: Expression): boolean {\n return e instanceof NotExpr && this.condition.isEquivalent(e.condition);\n }\n\n override isConstant() {\n return false;\n }\n\n override visitExpression(visitor: ExpressionVisitor, context: any): any {\n return visitor.visitNotExpr(this, context);\n }\n\n override clone(): NotExpr {\n return new NotExpr(this.condition.clone(), this.sourceSpan);\n }\n}\n\nexport class FnParam {\n constructor(public name: string, public type: Type|null = null) {}\n\n isEquivalent(param: FnParam): boolean {\n return this.name === param.name;\n }\n\n clone(): FnParam {\n return new FnParam(this.name, this.type);\n }\n}\n\n\nexport class FunctionExpr extends Expression {\n constructor(\n public params: FnParam[], public statements: Statement[], type?: Type|null,\n sourceSpan?: ParseSourceSpan|null, public name?: string|null) {\n super(type, sourceSpan);\n }\n\n override isEquivalent(e: Expression|Statement): boolean {\n return (e instanceof FunctionExpr || e instanceof DeclareFunctionStmt) &&\n areAllEquivalent(this.params, e.params) && areAllEquivalent(this.statements, e.statements);\n }\n\n override isConstant() {\n return false;\n }\n\n override visitExpression(visitor: ExpressionVisitor, context: any): any {\n return visitor.visitFunctionExpr(this, context);\n }\n\n toDeclStmt(name: string, modifiers?: StmtModifier): DeclareFunctionStmt {\n return new DeclareFunctionStmt(\n name, this.params, this.statements, this.type, modifiers, this.sourceSpan);\n }\n\n override clone(): FunctionExpr {\n // TODO: Should we deep clone statements?\n return new FunctionExpr(\n this.params.map(p => p.clone()), this.statements, this.type, this.sourceSpan, this.name);\n }\n}\n\nexport class ArrowFunctionExpr extends Expression {\n // Note that `body: Expression` represents `() => expr` whereas\n // `body: Statement[]` represents `() => { expr }`.\n\n constructor(\n public params: FnParam[], public body: Expression|Statement[], type?: Type|null,\n sourceSpan?: ParseSourceSpan|null) {\n super(type, sourceSpan);\n }\n\n override isEquivalent(e: Expression): boolean {\n if (!(e instanceof ArrowFunctionExpr) || !areAllEquivalent(this.params, e.params)) {\n return false;\n }\n\n if (this.body instanceof Expression && e.body instanceof Expression) {\n return this.body.isEquivalent(e.body);\n }\n\n if (Array.isArray(this.body) && Array.isArray(e.body)) {\n return areAllEquivalent(this.body, e.body);\n }\n\n return false;\n }\n\n override isConstant(): boolean {\n return false;\n }\n\n override visitExpression(visitor: ExpressionVisitor, context: any) {\n return visitor.visitArrowFunctionExpr(this, context);\n }\n\n override clone(): Expression {\n // TODO: Should we deep clone statements?\n return new ArrowFunctionExpr(\n this.params.map(p => p.clone()), Array.isArray(this.body) ? this.body : this.body.clone(),\n this.type, this.sourceSpan);\n }\n\n toDeclStmt(name: string, modifiers?: StmtModifier): DeclareVarStmt {\n return new DeclareVarStmt(name, this, INFERRED_TYPE, modifiers, this.sourceSpan);\n }\n}\n\n\nexport class UnaryOperatorExpr extends Expression {\n constructor(\n public operator: UnaryOperator, public expr: Expression, type?: Type|null,\n sourceSpan?: ParseSourceSpan|null, public parens: boolean = true) {\n super(type || NUMBER_TYPE, sourceSpan);\n }\n\n override isEquivalent(e: Expression): boolean {\n return e instanceof UnaryOperatorExpr && this.operator === e.operator &&\n this.expr.isEquivalent(e.expr);\n }\n\n override isConstant() {\n return false;\n }\n\n override visitExpression(visitor: ExpressionVisitor, context: any): any {\n return visitor.visitUnaryOperatorExpr(this, context);\n }\n\n override clone(): UnaryOperatorExpr {\n return new UnaryOperatorExpr(\n this.operator, this.expr.clone(), this.type, this.sourceSpan, this.parens);\n }\n}\n\n\nexport class BinaryOperatorExpr extends Expression {\n public lhs: Expression;\n constructor(\n public operator: BinaryOperator, lhs: Expression, public rhs: Expression, type?: Type|null,\n sourceSpan?: ParseSourceSpan|null, public parens: boolean = true) {\n super(type || lhs.type, sourceSpan);\n this.lhs = lhs;\n }\n\n override isEquivalent(e: Expression): boolean {\n return e instanceof BinaryOperatorExpr && this.operator === e.operator &&\n this.lhs.isEquivalent(e.lhs) && this.rhs.isEquivalent(e.rhs);\n }\n\n override isConstant() {\n return false;\n }\n\n override visitExpression(visitor: ExpressionVisitor, context: any): any {\n return visitor.visitBinaryOperatorExpr(this, context);\n }\n\n override clone(): BinaryOperatorExpr {\n return new BinaryOperatorExpr(\n this.operator, this.lhs.clone(), this.rhs.clone(), this.type, this.sourceSpan, this.parens);\n }\n}\n\n\nexport class ReadPropExpr extends Expression {\n constructor(\n public receiver: Expression, public name: string, type?: Type|null,\n sourceSpan?: ParseSourceSpan|null) {\n super(type, sourceSpan);\n }\n\n // An alias for name, which allows other logic to handle property reads and keyed reads together.\n get index() {\n return this.name;\n }\n\n override isEquivalent(e: Expression): boolean {\n return e instanceof ReadPropExpr && this.receiver.isEquivalent(e.receiver) &&\n this.name === e.name;\n }\n\n override isConstant() {\n return false;\n }\n\n override visitExpression(visitor: ExpressionVisitor, context: any): any {\n return visitor.visitReadPropExpr(this, context);\n }\n\n set(value: Expression): WritePropExpr {\n return new WritePropExpr(this.receiver, this.name, value, null, this.sourceSpan);\n }\n\n override clone(): ReadPropExpr {\n return new ReadPropExpr(this.receiver.clone(), this.name, this.type, this.sourceSpan);\n }\n}\n\n\nexport class ReadKeyExpr extends Expression {\n constructor(\n public receiver: Expression, public index: Expression, type?: Type|null,\n sourceSpan?: ParseSourceSpan|null) {\n super(type, sourceSpan);\n }\n\n override isEquivalent(e: Expression): boolean {\n return e instanceof ReadKeyExpr && this.receiver.isEquivalent(e.receiver) &&\n this.index.isEquivalent(e.index);\n }\n\n override isConstant() {\n return false;\n }\n\n override visitExpression(visitor: ExpressionVisitor, context: any): any {\n return visitor.visitReadKeyExpr(this, context);\n }\n\n set(value: Expression): WriteKeyExpr {\n return new WriteKeyExpr(this.receiver, this.index, value, null, this.sourceSpan);\n }\n\n override clone(): ReadKeyExpr {\n return new ReadKeyExpr(this.receiver.clone(), this.index.clone(), this.type, this.sourceSpan);\n }\n}\n\n\nexport class LiteralArrayExpr extends Expression {\n public entries: Expression[];\n constructor(entries: Expression[], type?: Type|null, sourceSpan?: ParseSourceSpan|null) {\n super(type, sourceSpan);\n this.entries = entries;\n }\n\n override isConstant() {\n return this.entries.every(e => e.isConstant());\n }\n\n override isEquivalent(e: Expression): boolean {\n return e instanceof LiteralArrayExpr && areAllEquivalent(this.entries, e.entries);\n }\n override visitExpression(visitor: ExpressionVisitor, context: any): any {\n return visitor.visitLiteralArrayExpr(this, context);\n }\n\n override clone(): LiteralArrayExpr {\n return new LiteralArrayExpr(this.entries.map(e => e.clone()), this.type, this.sourceSpan);\n }\n}\n\nexport class LiteralMapEntry {\n constructor(public key: string, public value: Expression, public quoted: boolean) {}\n isEquivalent(e: LiteralMapEntry): boolean {\n return this.key === e.key && this.value.isEquivalent(e.value);\n }\n\n clone(): LiteralMapEntry {\n return new LiteralMapEntry(this.key, this.value.clone(), this.quoted);\n }\n}\n\nexport class LiteralMapExpr extends Expression {\n public valueType: Type|null = null;\n constructor(\n public entries: LiteralMapEntry[], type?: MapType|null, sourceSpan?: ParseSourceSpan|null) {\n super(type, sourceSpan);\n if (type) {\n this.valueType = type.valueType;\n }\n }\n\n override isEquivalent(e: Expression): boolean {\n return e instanceof LiteralMapExpr && areAllEquivalent(this.entries, e.entries);\n }\n\n override isConstant() {\n return this.entries.every(e => e.value.isConstant());\n }\n\n override visitExpression(visitor: ExpressionVisitor, context: any): any {\n return visitor.visitLiteralMapExpr(this, context);\n }\n\n override clone(): LiteralMapExpr {\n const entriesClone = this.entries.map(entry => entry.clone());\n return new LiteralMapExpr(entriesClone, this.type as MapType | null, this.sourceSpan);\n }\n}\n\nexport class CommaExpr extends Expression {\n constructor(public parts: Expression[], sourceSpan?: ParseSourceSpan|null) {\n super(parts[parts.length - 1].type, sourceSpan);\n }\n\n override isEquivalent(e: Expression): boolean {\n return e instanceof CommaExpr && areAllEquivalent(this.parts, e.parts);\n }\n\n override isConstant() {\n return false;\n }\n\n override visitExpression(visitor: ExpressionVisitor, context: any): any {\n return visitor.visitCommaExpr(this, context);\n }\n\n override clone(): CommaExpr {\n return new CommaExpr(this.parts.map(p => p.clone()));\n }\n}\n\nexport interface ExpressionVisitor {\n visitReadVarExpr(ast: ReadVarExpr, context: any): any;\n visitWriteVarExpr(expr: WriteVarExpr, context: any): any;\n visitWriteKeyExpr(expr: WriteKeyExpr, context: any): any;\n visitWritePropExpr(expr: WritePropExpr, context: any): any;\n visitInvokeFunctionExpr(ast: InvokeFunctionExpr, context: any): any;\n visitTaggedTemplateExpr(ast: TaggedTemplateExpr, context: any): any;\n visitInstantiateExpr(ast: InstantiateExpr, context: any): any;\n visitLiteralExpr(ast: LiteralExpr, context: any): any;\n visitLocalizedString(ast: LocalizedString, context: any): any;\n visitExternalExpr(ast: ExternalExpr, context: any): any;\n visitConditionalExpr(ast: ConditionalExpr, context: any): any;\n visitDynamicImportExpr(ast: DynamicImportExpr, context: any): any;\n visitNotExpr(ast: NotExpr, context: any): any;\n visitFunctionExpr(ast: FunctionExpr, context: any): any;\n visitUnaryOperatorExpr(ast: UnaryOperatorExpr, context: any): any;\n visitBinaryOperatorExpr(ast: BinaryOperatorExpr, context: any): any;\n visitReadPropExpr(ast: ReadPropExpr, context: any): any;\n visitReadKeyExpr(ast: ReadKeyExpr, context: any): any;\n visitLiteralArrayExpr(ast: LiteralArrayExpr, context: any): any;\n visitLiteralMapExpr(ast: LiteralMapExpr, context: any): any;\n visitCommaExpr(ast: CommaExpr, context: any): any;\n visitWrappedNodeExpr(ast: WrappedNodeExpr, context: any): any;\n visitTypeofExpr(ast: TypeofExpr, context: any): any;\n visitArrowFunctionExpr(ast: ArrowFunctionExpr, context: any): any;\n}\n\nexport const NULL_EXPR = new LiteralExpr(null, null, null);\nexport const TYPED_NULL_EXPR = new LiteralExpr(null, INFERRED_TYPE, null);\n\n//// Statements\nexport enum StmtModifier {\n None = 0,\n Final = 1 << 0,\n Private = 1 << 1,\n Exported = 1 << 2,\n Static = 1 << 3,\n}\n\nexport class LeadingComment {\n constructor(public text: string, public multiline: boolean, public trailingNewline: boolean) {}\n toString() {\n return this.multiline ? ` ${this.text} ` : this.text;\n }\n}\nexport class JSDocComment extends LeadingComment {\n constructor(public tags: JSDocTag[]) {\n super('', /* multiline */ true, /* trailingNewline */ true);\n }\n override toString(): string {\n return serializeTags(this.tags);\n }\n}\n\nexport abstract class Statement {\n constructor(\n public modifiers: StmtModifier = StmtModifier.None,\n public sourceSpan: ParseSourceSpan|null = null, public leadingComments?: LeadingComment[]) {}\n /**\n * Calculates whether this statement produces the same value as the given statement.\n * Note: We don't check Types nor ParseSourceSpans nor function arguments.\n */\n abstract isEquivalent(stmt: Statement): boolean;\n\n abstract visitStatement(visitor: StatementVisitor, context: any): any;\n\n hasModifier(modifier: StmtModifier): boolean {\n return (this.modifiers & modifier) !== 0;\n }\n\n addLeadingComment(leadingComment: LeadingComment): void {\n this.leadingComments = this.leadingComments ?? [];\n this.leadingComments.push(leadingComment);\n }\n}\n\n\nexport class DeclareVarStmt extends Statement {\n public type: Type|null;\n constructor(\n public name: string, public value?: Expression, type?: Type|null, modifiers?: StmtModifier,\n sourceSpan?: ParseSourceSpan|null, leadingComments?: LeadingComment[]) {\n super(modifiers, sourceSpan, leadingComments);\n this.type = type || (value && value.type) || null;\n }\n override isEquivalent(stmt: Statement): boolean {\n return stmt instanceof DeclareVarStmt && this.name === stmt.name &&\n (this.value ? !!stmt.value && this.value.isEquivalent(stmt.value) : !stmt.value);\n }\n override visitStatement(visitor: StatementVisitor, context: any): any {\n return visitor.visitDeclareVarStmt(this, context);\n }\n}\n\nexport class DeclareFunctionStmt extends Statement {\n public type: Type|null;\n constructor(\n public name: string, public params: FnParam[], public statements: Statement[],\n type?: Type|null, modifiers?: StmtModifier, sourceSpan?: ParseSourceSpan|null,\n leadingComments?: LeadingComment[]) {\n super(modifiers, sourceSpan, leadingComments);\n this.type = type || null;\n }\n override isEquivalent(stmt: Statement): boolean {\n return stmt instanceof DeclareFunctionStmt && areAllEquivalent(this.params, stmt.params) &&\n areAllEquivalent(this.statements, stmt.statements);\n }\n override visitStatement(visitor: StatementVisitor, context: any): any {\n return visitor.visitDeclareFunctionStmt(this, context);\n }\n}\n\nexport class ExpressionStatement extends Statement {\n constructor(\n public expr: Expression, sourceSpan?: ParseSourceSpan|null,\n leadingComments?: LeadingComment[]) {\n super(StmtModifier.None, sourceSpan, leadingComments);\n }\n override isEquivalent(stmt: Statement): boolean {\n return stmt instanceof ExpressionStatement && this.expr.isEquivalent(stmt.expr);\n }\n override visitStatement(visitor: StatementVisitor, context: any): any {\n return visitor.visitExpressionStmt(this, context);\n }\n}\n\n\nexport class ReturnStatement extends Statement {\n constructor(\n public value: Expression, sourceSpan: ParseSourceSpan|null = null,\n leadingComments?: LeadingComment[]) {\n super(StmtModifier.None, sourceSpan, leadingComments);\n }\n override isEquivalent(stmt: Statement): boolean {\n return stmt instanceof ReturnStatement && this.value.isEquivalent(stmt.value);\n }\n override visitStatement(visitor: StatementVisitor, context: any): any {\n return visitor.visitReturnStmt(this, context);\n }\n}\n\nexport class IfStmt extends Statement {\n constructor(\n public condition: Expression, public trueCase: Statement[],\n public falseCase: Statement[] = [], sourceSpan?: ParseSourceSpan|null,\n leadingComments?: LeadingComment[]) {\n super(StmtModifier.None, sourceSpan, leadingComments);\n }\n override isEquivalent(stmt: Statement): boolean {\n return stmt instanceof IfStmt && this.condition.isEquivalent(stmt.condition) &&\n areAllEquivalent(this.trueCase, stmt.trueCase) &&\n areAllEquivalent(this.falseCase, stmt.falseCase);\n }\n override visitStatement(visitor: StatementVisitor, context: any): any {\n return visitor.visitIfStmt(this, context);\n }\n}\n\nexport interface StatementVisitor {\n visitDeclareVarStmt(stmt: DeclareVarStmt, context: any): any;\n visitDeclareFunctionStmt(stmt: DeclareFunctionStmt, context: any): any;\n visitExpressionStmt(stmt: ExpressionStatement, context: any): any;\n visitReturnStmt(stmt: ReturnStatement, context: any): any;\n visitIfStmt(stmt: IfStmt, context: any): any;\n}\n\nexport class RecursiveAstVisitor implements StatementVisitor, ExpressionVisitor {\n visitType(ast: Type, context: any): any {\n return ast;\n }\n visitExpression(ast: Expression, context: any): any {\n if (ast.type) {\n ast.type.visitType(this, context);\n }\n return ast;\n }\n visitBuiltinType(type: BuiltinType, context: any): any {\n return this.visitType(type, context);\n }\n visitExpressionType(type: ExpressionType, context: any): any {\n type.value.visitExpression(this, context);\n if (type.typeParams !== null) {\n type.typeParams.forEach(param => this.visitType(param, context));\n }\n return this.visitType(type, context);\n }\n visitArrayType(type: ArrayType, context: any): any {\n return this.visitType(type, context);\n }\n visitMapType(type: MapType, context: any): any {\n return this.visitType(type, context);\n }\n visitTransplantedType(type: TransplantedType, context: any): any {\n return type;\n }\n visitWrappedNodeExpr(ast: WrappedNodeExpr, context: any): any {\n return ast;\n }\n visitTypeofExpr(ast: TypeofExpr, context: any): any {\n return this.visitExpression(ast, context);\n }\n visitReadVarExpr(ast: ReadVarExpr, context: any): any {\n return this.visitExpression(ast, context);\n }\n visitWriteVarExpr(ast: WriteVarExpr, context: any): any {\n ast.value.visitExpression(this, context);\n return this.visitExpression(ast, context);\n }\n visitWriteKeyExpr(ast: WriteKeyExpr, context: any): any {\n ast.receiver.visitExpression(this, context);\n ast.index.visitExpression(this, context);\n ast.value.visitExpression(this, context);\n return this.visitExpression(ast, context);\n }\n visitWritePropExpr(ast: WritePropExpr, context: any): any {\n ast.receiver.visitExpression(this, context);\n ast.value.visitExpression(this, context);\n return this.visitExpression(ast, context);\n }\n visitDynamicImportExpr(ast: DynamicImportExpr, context: any) {\n return this.visitExpression(ast, context);\n }\n visitInvokeFunctionExpr(ast: InvokeFunctionExpr, context: any): any {\n ast.fn.visitExpression(this, context);\n this.visitAllExpressions(ast.args, context);\n return this.visitExpression(ast, context);\n }\n visitTaggedTemplateExpr(ast: TaggedTemplateExpr, context: any): any {\n ast.tag.visitExpression(this, context);\n this.visitAllExpressions(ast.template.expressions, context);\n return this.visitExpression(ast, context);\n }\n visitInstantiateExpr(ast: InstantiateExpr, context: any): any {\n ast.classExpr.visitExpression(this, context);\n this.visitAllExpressions(ast.args, context);\n return this.visitExpression(ast, context);\n }\n visitLiteralExpr(ast: LiteralExpr, context: any): any {\n return this.visitExpression(ast, context);\n }\n visitLocalizedString(ast: LocalizedString, context: any): any {\n return this.visitExpression(ast, context);\n }\n visitExternalExpr(ast: ExternalExpr, context: any): any {\n if (ast.typeParams) {\n ast.typeParams.forEach(type => type.visitType(this, context));\n }\n return this.visitExpression(ast, context);\n }\n visitConditionalExpr(ast: ConditionalExpr, context: any): any {\n ast.condition.visitExpression(this, context);\n ast.trueCase.visitExpression(this, context);\n ast.falseCase!.visitExpression(this, context);\n return this.visitExpression(ast, context);\n }\n visitNotExpr(ast: NotExpr, context: any): any {\n ast.condition.visitExpression(this, context);\n return this.visitExpression(ast, context);\n }\n visitFunctionExpr(ast: FunctionExpr, context: any): any {\n this.visitAllStatements(ast.statements, context);\n return this.visitExpression(ast, context);\n }\n visitArrowFunctionExpr(ast: ArrowFunctionExpr, context: any): any {\n if (Array.isArray(ast.body)) {\n this.visitAllStatements(ast.body, context);\n } else {\n this.visitExpression(ast.body, context);\n }\n\n return this.visitExpression(ast, context);\n }\n visitUnaryOperatorExpr(ast: UnaryOperatorExpr, context: any): any {\n ast.expr.visitExpression(this, context);\n return this.visitExpression(ast, context);\n }\n visitBinaryOperatorExpr(ast: BinaryOperatorExpr, context: any): any {\n ast.lhs.visitExpression(this, context);\n ast.rhs.visitExpression(this, context);\n return this.visitExpression(ast, context);\n }\n visitReadPropExpr(ast: ReadPropExpr, context: any): any {\n ast.receiver.visitExpression(this, context);\n return this.visitExpression(ast, context);\n }\n visitReadKeyExpr(ast: ReadKeyExpr, context: any): any {\n ast.receiver.visitExpression(this, context);\n ast.index.visitExpression(this, context);\n return this.visitExpression(ast, context);\n }\n visitLiteralArrayExpr(ast: LiteralArrayExpr, context: any): any {\n this.visitAllExpressions(ast.entries, context);\n return this.visitExpression(ast, context);\n }\n visitLiteralMapExpr(ast: LiteralMapExpr, context: any): any {\n ast.entries.forEach((entry) => entry.value.visitExpression(this, context));\n return this.visitExpression(ast, context);\n }\n visitCommaExpr(ast: CommaExpr, context: any): any {\n this.visitAllExpressions(ast.parts, context);\n return this.visitExpression(ast, context);\n }\n visitAllExpressions(exprs: Expression[], context: any): void {\n exprs.forEach(expr => expr.visitExpression(this, context));\n }\n\n visitDeclareVarStmt(stmt: DeclareVarStmt, context: any): any {\n if (stmt.value) {\n stmt.value.visitExpression(this, context);\n }\n if (stmt.type) {\n stmt.type.visitType(this, context);\n }\n return stmt;\n }\n visitDeclareFunctionStmt(stmt: DeclareFunctionStmt, context: any): any {\n this.visitAllStatements(stmt.statements, context);\n if (stmt.type) {\n stmt.type.visitType(this, context);\n }\n return stmt;\n }\n visitExpressionStmt(stmt: ExpressionStatement, context: any): any {\n stmt.expr.visitExpression(this, context);\n return stmt;\n }\n visitReturnStmt(stmt: ReturnStatement, context: any): any {\n stmt.value.visitExpression(this, context);\n return stmt;\n }\n visitIfStmt(stmt: IfStmt, context: any): any {\n stmt.condition.visitExpression(this, context);\n this.visitAllStatements(stmt.trueCase, context);\n this.visitAllStatements(stmt.falseCase, context);\n return stmt;\n }\n visitAllStatements(stmts: Statement[], context: any): void {\n stmts.forEach(stmt => stmt.visitStatement(this, context));\n }\n}\n\nexport function leadingComment(\n text: string, multiline: boolean = false, trailingNewline: boolean = true): LeadingComment {\n return new LeadingComment(text, multiline, trailingNewline);\n}\n\nexport function jsDocComment(tags: JSDocTag[] = []): JSDocComment {\n return new JSDocComment(tags);\n}\n\nexport function variable(\n name: string, type?: Type|null, sourceSpan?: ParseSourceSpan|null): ReadVarExpr {\n return new ReadVarExpr(name, type, sourceSpan);\n}\n\nexport function importExpr(\n id: ExternalReference, typeParams: Type[]|null = null,\n sourceSpan?: ParseSourceSpan|null): ExternalExpr {\n return new ExternalExpr(id, null, typeParams, sourceSpan);\n}\n\nexport function importType(\n id: ExternalReference, typeParams?: Type[]|null, typeModifiers?: TypeModifier): ExpressionType|\n null {\n return id != null ? expressionType(importExpr(id, typeParams, null), typeModifiers) : null;\n}\n\nexport function expressionType(\n expr: Expression, typeModifiers?: TypeModifier, typeParams?: Type[]|null): ExpressionType {\n return new ExpressionType(expr, typeModifiers, typeParams);\n}\n\nexport function transplantedType(type: T, typeModifiers?: TypeModifier): TransplantedType {\n return new TransplantedType(type, typeModifiers);\n}\n\nexport function typeofExpr(expr: Expression) {\n return new TypeofExpr(expr);\n}\n\nexport function literalArr(\n values: Expression[], type?: Type|null, sourceSpan?: ParseSourceSpan|null): LiteralArrayExpr {\n return new LiteralArrayExpr(values, type, sourceSpan);\n}\n\nexport function literalMap(\n values: {key: string, quoted: boolean, value: Expression}[],\n type: MapType|null = null): LiteralMapExpr {\n return new LiteralMapExpr(\n values.map(e => new LiteralMapEntry(e.key, e.value, e.quoted)), type, null);\n}\n\nexport function unary(\n operator: UnaryOperator, expr: Expression, type?: Type,\n sourceSpan?: ParseSourceSpan|null): UnaryOperatorExpr {\n return new UnaryOperatorExpr(operator, expr, type, sourceSpan);\n}\n\nexport function not(expr: Expression, sourceSpan?: ParseSourceSpan|null): NotExpr {\n return new NotExpr(expr, sourceSpan);\n}\n\nexport function fn(\n params: FnParam[], body: Statement[], type?: Type|null, sourceSpan?: ParseSourceSpan|null,\n name?: string|null): FunctionExpr {\n return new FunctionExpr(params, body, type, sourceSpan, name);\n}\n\nexport function arrowFn(\n params: FnParam[], body: Expression|Statement[], type?: Type|null,\n sourceSpan?: ParseSourceSpan|null) {\n return new ArrowFunctionExpr(params, body, type, sourceSpan);\n}\n\nexport function ifStmt(\n condition: Expression, thenClause: Statement[], elseClause?: Statement[],\n sourceSpan?: ParseSourceSpan, leadingComments?: LeadingComment[]) {\n return new IfStmt(condition, thenClause, elseClause, sourceSpan, leadingComments);\n}\n\nexport function taggedTemplate(\n tag: Expression, template: TemplateLiteral, type?: Type|null,\n sourceSpan?: ParseSourceSpan|null): TaggedTemplateExpr {\n return new TaggedTemplateExpr(tag, template, type, sourceSpan);\n}\n\nexport function literal(\n value: any, type?: Type|null, sourceSpan?: ParseSourceSpan|null): LiteralExpr {\n return new LiteralExpr(value, type, sourceSpan);\n}\n\nexport function localizedString(\n metaBlock: I18nMeta, messageParts: LiteralPiece[], placeholderNames: PlaceholderPiece[],\n expressions: Expression[], sourceSpan?: ParseSourceSpan|null): LocalizedString {\n return new LocalizedString(metaBlock, messageParts, placeholderNames, expressions, sourceSpan);\n}\n\nexport function isNull(exp: Expression): boolean {\n return exp instanceof LiteralExpr && exp.value === null;\n}\n\n// The list of JSDoc tags that we currently support. Extend it if needed.\nexport const enum JSDocTagName {\n Desc = 'desc',\n Id = 'id',\n Meaning = 'meaning',\n Suppress = 'suppress',\n}\n\n/*\n * TypeScript has an API for JSDoc already, but it's not exposed.\n * https://github.com/Microsoft/TypeScript/issues/7393\n * For now we create types that are similar to theirs so that migrating\n * to their API will be easier. See e.g. `ts.JSDocTag` and `ts.JSDocComment`.\n */\nexport type JSDocTag = {\n // `tagName` is e.g. \"param\" in an `@param` declaration\n tagName: JSDocTagName|string,\n // Any remaining text on the tag, e.g. the description\n text?: string,\n}|{\n // no `tagName` for plain text documentation that occurs before any `@param` lines\n tagName?: undefined, text: string,\n};\n\n/*\n * Serializes a `Tag` into a string.\n * Returns a string like \" @foo {bar} baz\" (note the leading whitespace before `@foo`).\n */\nfunction tagToString(tag: JSDocTag): string {\n let out = '';\n if (tag.tagName) {\n out += ` @${tag.tagName}`;\n }\n if (tag.text) {\n if (tag.text.match(/\\/\\*|\\*\\//)) {\n throw new Error('JSDoc text cannot contain \"/*\" and \"*/\"');\n }\n out += ' ' + tag.text.replace(/@/g, '\\\\@');\n }\n return out;\n}\n\nfunction serializeTags(tags: JSDocTag[]): string {\n if (tags.length === 0) return '';\n\n if (tags.length === 1 && tags[0].tagName && !tags[0].text) {\n // The JSDOC comment is a single simple tag: e.g `/** @tagname */`.\n return `*${tagToString(tags[0])} `;\n }\n\n let out = '*\\n';\n for (const tag of tags) {\n out += ' *';\n // If the tagToString is multi-line, insert \" * \" prefixes on lines.\n out += tagToString(tag).replace(/\\n/g, '\\n * ');\n out += '\\n';\n }\n out += ' ';\n return out;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport * as o from './output/output_ast';\n\nconst CONSTANT_PREFIX = '_c';\n\n/**\n * `ConstantPool` tries to reuse literal factories when two or more literals are identical.\n * We determine whether literals are identical by creating a key out of their AST using the\n * `KeyVisitor`. This constant is used to replace dynamic expressions which can't be safely\n * converted into a key. E.g. given an expression `{foo: bar()}`, since we don't know what\n * the result of `bar` will be, we create a key that looks like `{foo: }`. Note\n * that we use a variable, rather than something like `null` in order to avoid collisions.\n */\nconst UNKNOWN_VALUE_KEY = o.variable('');\n\n/**\n * Context to use when producing a key.\n *\n * This ensures we see the constant not the reference variable when producing\n * a key.\n */\nconst KEY_CONTEXT = {};\n\n/**\n * Generally all primitive values are excluded from the `ConstantPool`, but there is an exclusion\n * for strings that reach a certain length threshold. This constant defines the length threshold for\n * strings.\n */\nconst POOL_INCLUSION_LENGTH_THRESHOLD_FOR_STRINGS = 50;\n\n/**\n * A node that is a place-holder that allows the node to be replaced when the actual\n * node is known.\n *\n * This allows the constant pool to change an expression from a direct reference to\n * a constant to a shared constant. It returns a fix-up node that is later allowed to\n * change the referenced expression.\n */\nclass FixupExpression extends o.Expression {\n private original: o.Expression;\n\n shared = false;\n\n constructor(public resolved: o.Expression) {\n super(resolved.type);\n this.original = resolved;\n }\n\n override visitExpression(visitor: o.ExpressionVisitor, context: any): any {\n if (context === KEY_CONTEXT) {\n // When producing a key we want to traverse the constant not the\n // variable used to refer to it.\n return this.original.visitExpression(visitor, context);\n } else {\n return this.resolved.visitExpression(visitor, context);\n }\n }\n\n override isEquivalent(e: o.Expression): boolean {\n return e instanceof FixupExpression && this.resolved.isEquivalent(e.resolved);\n }\n\n override isConstant() {\n return true;\n }\n\n override clone(): FixupExpression {\n throw new Error(`Not supported.`);\n }\n\n fixup(expression: o.Expression) {\n this.resolved = expression;\n this.shared = true;\n }\n}\n\n/**\n * A constant pool allows a code emitter to share constant in an output context.\n *\n * The constant pool also supports sharing access to ivy definitions references.\n */\nexport class ConstantPool {\n statements: o.Statement[] = [];\n private literals = new Map();\n private literalFactories = new Map();\n private sharedConstants = new Map();\n\n /**\n * Constant pool also tracks claimed names from {@link uniqueName}.\n * This is useful to avoid collisions if variables are intended to be\n * named a certain way- but may conflict. We wouldn't want to always suffix\n * them with unique numbers.\n */\n private _claimedNames = new Map();\n\n private nextNameIndex = 0;\n\n constructor(private readonly isClosureCompilerEnabled: boolean = false) {}\n\n getConstLiteral(literal: o.Expression, forceShared?: boolean): o.Expression {\n if ((literal instanceof o.LiteralExpr && !isLongStringLiteral(literal)) ||\n literal instanceof FixupExpression) {\n // Do no put simple literals into the constant pool or try to produce a constant for a\n // reference to a constant.\n return literal;\n }\n const key = GenericKeyFn.INSTANCE.keyOf(literal);\n let fixup = this.literals.get(key);\n let newValue = false;\n if (!fixup) {\n fixup = new FixupExpression(literal);\n this.literals.set(key, fixup);\n newValue = true;\n }\n\n if ((!newValue && !fixup.shared) || (newValue && forceShared)) {\n // Replace the expression with a variable\n const name = this.freshName();\n let definition: o.WriteVarExpr;\n let usage: o.Expression;\n if (this.isClosureCompilerEnabled && isLongStringLiteral(literal)) {\n // For string literals, Closure will **always** inline the string at\n // **all** usages, duplicating it each time. For large strings, this\n // unnecessarily bloats bundle size. To work around this restriction, we\n // wrap the string in a function, and call that function for each usage.\n // This tricks Closure into using inline logic for functions instead of\n // string literals. Function calls are only inlined if the body is small\n // enough to be worth it. By doing this, very large strings will be\n // shared across multiple usages, rather than duplicating the string at\n // each usage site.\n //\n // const myStr = function() { return \"very very very long string\"; };\n // const usage1 = myStr();\n // const usage2 = myStr();\n definition = o.variable(name).set(new o.FunctionExpr(\n [], // Params.\n [\n // Statements.\n new o.ReturnStatement(literal),\n ],\n ));\n usage = o.variable(name).callFn([]);\n } else {\n // Just declare and use the variable directly, without a function call\n // indirection. This saves a few bytes and avoids an unnecessary call.\n definition = o.variable(name).set(literal);\n usage = o.variable(name);\n }\n\n this.statements.push(definition.toDeclStmt(o.INFERRED_TYPE, o.StmtModifier.Final));\n fixup.fixup(usage);\n }\n\n return fixup;\n }\n\n getSharedConstant(def: SharedConstantDefinition, expr: o.Expression): o.Expression {\n const key = def.keyOf(expr);\n if (!this.sharedConstants.has(key)) {\n const id = this.freshName();\n this.sharedConstants.set(key, o.variable(id));\n this.statements.push(def.toSharedConstantDeclaration(id, expr));\n }\n return this.sharedConstants.get(key)!;\n }\n\n getLiteralFactory(literal: o.LiteralArrayExpr|o.LiteralMapExpr):\n {literalFactory: o.Expression, literalFactoryArguments: o.Expression[]} {\n // Create a pure function that builds an array of a mix of constant and variable expressions\n if (literal instanceof o.LiteralArrayExpr) {\n const argumentsForKey = literal.entries.map(e => e.isConstant() ? e : UNKNOWN_VALUE_KEY);\n const key = GenericKeyFn.INSTANCE.keyOf(o.literalArr(argumentsForKey));\n return this._getLiteralFactory(key, literal.entries, entries => o.literalArr(entries));\n } else {\n const expressionForKey = o.literalMap(\n literal.entries.map(e => ({\n key: e.key,\n value: e.value.isConstant() ? e.value : UNKNOWN_VALUE_KEY,\n quoted: e.quoted\n })));\n const key = GenericKeyFn.INSTANCE.keyOf(expressionForKey);\n return this._getLiteralFactory(\n key, literal.entries.map(e => e.value),\n entries => o.literalMap(entries.map((value, index) => ({\n key: literal.entries[index].key,\n value,\n quoted: literal.entries[index].quoted\n }))));\n }\n }\n\n // TODO: useUniqueName(false) is necessary for naming compatibility with\n // TemplateDefinitionBuilder, but should be removed once Template Pipeline is the default.\n getSharedFunctionReference(\n fn: o.FunctionExpr|o.ArrowFunctionExpr, prefix: string,\n useUniqueName: boolean = true): o.Expression {\n const isArrow = fn instanceof o.ArrowFunctionExpr;\n\n for (const current of this.statements) {\n // Arrow functions are saved as variables so we check if the\n // value of the variable is the same as the arrow function.\n if (isArrow && current instanceof o.DeclareVarStmt && current.value?.isEquivalent(fn)) {\n return o.variable(current.name);\n }\n\n // Function declarations are saved as function statements\n // so we compare them directly to the passed-in function.\n if (!isArrow && current instanceof o.DeclareFunctionStmt && fn.isEquivalent(current)) {\n return o.variable(current.name);\n }\n }\n\n // Otherwise declare the function.\n const name = useUniqueName ? this.uniqueName(prefix) : prefix;\n this.statements.push(fn.toDeclStmt(name, o.StmtModifier.Final));\n return o.variable(name);\n }\n\n private _getLiteralFactory(\n key: string, values: o.Expression[], resultMap: (parameters: o.Expression[]) => o.Expression):\n {literalFactory: o.Expression, literalFactoryArguments: o.Expression[]} {\n let literalFactory = this.literalFactories.get(key);\n const literalFactoryArguments = values.filter((e => !e.isConstant()));\n if (!literalFactory) {\n const resultExpressions = values.map(\n (e, index) => e.isConstant() ? this.getConstLiteral(e, true) : o.variable(`a${index}`));\n const parameters =\n resultExpressions.filter(isVariable).map(e => new o.FnParam(e.name!, o.DYNAMIC_TYPE));\n const pureFunctionDeclaration =\n o.arrowFn(parameters, resultMap(resultExpressions), o.INFERRED_TYPE);\n const name = this.freshName();\n this.statements.push(o.variable(name)\n .set(pureFunctionDeclaration)\n .toDeclStmt(o.INFERRED_TYPE, o.StmtModifier.Final));\n literalFactory = o.variable(name);\n this.literalFactories.set(key, literalFactory);\n }\n return {literalFactory, literalFactoryArguments};\n }\n\n /**\n * Produce a unique name in the context of this pool.\n *\n * The name might be unique among different prefixes if any of the prefixes end in\n * a digit so the prefix should be a constant string (not based on user input) and\n * must not end in a digit.\n */\n uniqueName(name: string, alwaysIncludeSuffix = true): string {\n const count = this._claimedNames.get(name) ?? 0;\n const result = count === 0 && !alwaysIncludeSuffix ? `${name}` : `${name}${count}`;\n\n this._claimedNames.set(name, count + 1);\n return result;\n }\n\n private freshName(): string {\n return this.uniqueName(CONSTANT_PREFIX);\n }\n}\n\nexport interface ExpressionKeyFn {\n keyOf(expr: o.Expression): string;\n}\n\nexport interface SharedConstantDefinition extends ExpressionKeyFn {\n toSharedConstantDeclaration(declName: string, keyExpr: o.Expression): o.Statement;\n}\n\nexport class GenericKeyFn implements ExpressionKeyFn {\n static readonly INSTANCE = new GenericKeyFn();\n\n keyOf(expr: o.Expression): string {\n if (expr instanceof o.LiteralExpr && typeof expr.value === 'string') {\n return `\"${expr.value}\"`;\n } else if (expr instanceof o.LiteralExpr) {\n return String(expr.value);\n } else if (expr instanceof o.LiteralArrayExpr) {\n const entries: string[] = [];\n for (const entry of expr.entries) {\n entries.push(this.keyOf(entry));\n }\n return `[${entries.join(',')}]`;\n } else if (expr instanceof o.LiteralMapExpr) {\n const entries: string[] = [];\n for (const entry of expr.entries) {\n let key = entry.key;\n if (entry.quoted) {\n key = `\"${key}\"`;\n }\n entries.push(key + ':' + this.keyOf(entry.value));\n }\n return `{${entries.join(',')}}`;\n } else if (expr instanceof o.ExternalExpr) {\n return `import(\"${expr.value.moduleName}\", ${expr.value.name})`;\n } else if (expr instanceof o.ReadVarExpr) {\n return `read(${expr.name})`;\n } else if (expr instanceof o.TypeofExpr) {\n return `typeof(${this.keyOf(expr.expr)})`;\n } else {\n throw new Error(\n `${this.constructor.name} does not handle expressions of type ${expr.constructor.name}`);\n }\n }\n}\n\nfunction isVariable(e: o.Expression): e is o.ReadVarExpr {\n return e instanceof o.ReadVarExpr;\n}\n\nfunction isLongStringLiteral(expr: o.Expression): boolean {\n return expr instanceof o.LiteralExpr && typeof expr.value === 'string' &&\n expr.value.length >= POOL_INCLUSION_LENGTH_THRESHOLD_FOR_STRINGS;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport * as o from '../output/output_ast';\n\nconst CORE = '@angular/core';\n\nexport class Identifiers {\n /* Methods */\n static NEW_METHOD = 'factory';\n static TRANSFORM_METHOD = 'transform';\n static PATCH_DEPS = 'patchedDeps';\n\n static core: o.ExternalReference = {name: null, moduleName: CORE};\n\n /* Instructions */\n static namespaceHTML: o.ExternalReference = {name: 'ɵɵnamespaceHTML', moduleName: CORE};\n\n static namespaceMathML: o.ExternalReference = {name: 'ɵɵnamespaceMathML', moduleName: CORE};\n\n static namespaceSVG: o.ExternalReference = {name: 'ɵɵnamespaceSVG', moduleName: CORE};\n\n static element: o.ExternalReference = {name: 'ɵɵelement', moduleName: CORE};\n\n static elementStart: o.ExternalReference = {name: 'ɵɵelementStart', moduleName: CORE};\n\n static elementEnd: o.ExternalReference = {name: 'ɵɵelementEnd', moduleName: CORE};\n\n static advance: o.ExternalReference = {name: 'ɵɵadvance', moduleName: CORE};\n\n static syntheticHostProperty:\n o.ExternalReference = {name: 'ɵɵsyntheticHostProperty', moduleName: CORE};\n\n static syntheticHostListener:\n o.ExternalReference = {name: 'ɵɵsyntheticHostListener', moduleName: CORE};\n\n static attribute: o.ExternalReference = {name: 'ɵɵattribute', moduleName: CORE};\n\n static attributeInterpolate1:\n o.ExternalReference = {name: 'ɵɵattributeInterpolate1', moduleName: CORE};\n static attributeInterpolate2:\n o.ExternalReference = {name: 'ɵɵattributeInterpolate2', moduleName: CORE};\n static attributeInterpolate3:\n o.ExternalReference = {name: 'ɵɵattributeInterpolate3', moduleName: CORE};\n static attributeInterpolate4:\n o.ExternalReference = {name: 'ɵɵattributeInterpolate4', moduleName: CORE};\n static attributeInterpolate5:\n o.ExternalReference = {name: 'ɵɵattributeInterpolate5', moduleName: CORE};\n static attributeInterpolate6:\n o.ExternalReference = {name: 'ɵɵattributeInterpolate6', moduleName: CORE};\n static attributeInterpolate7:\n o.ExternalReference = {name: 'ɵɵattributeInterpolate7', moduleName: CORE};\n static attributeInterpolate8:\n o.ExternalReference = {name: 'ɵɵattributeInterpolate8', moduleName: CORE};\n static attributeInterpolateV:\n o.ExternalReference = {name: 'ɵɵattributeInterpolateV', moduleName: CORE};\n\n static classProp: o.ExternalReference = {name: 'ɵɵclassProp', moduleName: CORE};\n\n static elementContainerStart:\n o.ExternalReference = {name: 'ɵɵelementContainerStart', moduleName: CORE};\n\n static elementContainerEnd:\n o.ExternalReference = {name: 'ɵɵelementContainerEnd', moduleName: CORE};\n\n static elementContainer: o.ExternalReference = {name: 'ɵɵelementContainer', moduleName: CORE};\n\n static styleMap: o.ExternalReference = {name: 'ɵɵstyleMap', moduleName: CORE};\n\n static styleMapInterpolate1:\n o.ExternalReference = {name: 'ɵɵstyleMapInterpolate1', moduleName: CORE};\n static styleMapInterpolate2:\n o.ExternalReference = {name: 'ɵɵstyleMapInterpolate2', moduleName: CORE};\n static styleMapInterpolate3:\n o.ExternalReference = {name: 'ɵɵstyleMapInterpolate3', moduleName: CORE};\n static styleMapInterpolate4:\n o.ExternalReference = {name: 'ɵɵstyleMapInterpolate4', moduleName: CORE};\n static styleMapInterpolate5:\n o.ExternalReference = {name: 'ɵɵstyleMapInterpolate5', moduleName: CORE};\n static styleMapInterpolate6:\n o.ExternalReference = {name: 'ɵɵstyleMapInterpolate6', moduleName: CORE};\n static styleMapInterpolate7:\n o.ExternalReference = {name: 'ɵɵstyleMapInterpolate7', moduleName: CORE};\n static styleMapInterpolate8:\n o.ExternalReference = {name: 'ɵɵstyleMapInterpolate8', moduleName: CORE};\n static styleMapInterpolateV:\n o.ExternalReference = {name: 'ɵɵstyleMapInterpolateV', moduleName: CORE};\n\n static classMap: o.ExternalReference = {name: 'ɵɵclassMap', moduleName: CORE};\n\n static classMapInterpolate1:\n o.ExternalReference = {name: 'ɵɵclassMapInterpolate1', moduleName: CORE};\n static classMapInterpolate2:\n o.ExternalReference = {name: 'ɵɵclassMapInterpolate2', moduleName: CORE};\n static classMapInterpolate3:\n o.ExternalReference = {name: 'ɵɵclassMapInterpolate3', moduleName: CORE};\n static classMapInterpolate4:\n o.ExternalReference = {name: 'ɵɵclassMapInterpolate4', moduleName: CORE};\n static classMapInterpolate5:\n o.ExternalReference = {name: 'ɵɵclassMapInterpolate5', moduleName: CORE};\n static classMapInterpolate6:\n o.ExternalReference = {name: 'ɵɵclassMapInterpolate6', moduleName: CORE};\n static classMapInterpolate7:\n o.ExternalReference = {name: 'ɵɵclassMapInterpolate7', moduleName: CORE};\n static classMapInterpolate8:\n o.ExternalReference = {name: 'ɵɵclassMapInterpolate8', moduleName: CORE};\n static classMapInterpolateV:\n o.ExternalReference = {name: 'ɵɵclassMapInterpolateV', moduleName: CORE};\n\n static styleProp: o.ExternalReference = {name: 'ɵɵstyleProp', moduleName: CORE};\n\n static stylePropInterpolate1:\n o.ExternalReference = {name: 'ɵɵstylePropInterpolate1', moduleName: CORE};\n static stylePropInterpolate2:\n o.ExternalReference = {name: 'ɵɵstylePropInterpolate2', moduleName: CORE};\n static stylePropInterpolate3:\n o.ExternalReference = {name: 'ɵɵstylePropInterpolate3', moduleName: CORE};\n static stylePropInterpolate4:\n o.ExternalReference = {name: 'ɵɵstylePropInterpolate4', moduleName: CORE};\n static stylePropInterpolate5:\n o.ExternalReference = {name: 'ɵɵstylePropInterpolate5', moduleName: CORE};\n static stylePropInterpolate6:\n o.ExternalReference = {name: 'ɵɵstylePropInterpolate6', moduleName: CORE};\n static stylePropInterpolate7:\n o.ExternalReference = {name: 'ɵɵstylePropInterpolate7', moduleName: CORE};\n static stylePropInterpolate8:\n o.ExternalReference = {name: 'ɵɵstylePropInterpolate8', moduleName: CORE};\n static stylePropInterpolateV:\n o.ExternalReference = {name: 'ɵɵstylePropInterpolateV', moduleName: CORE};\n\n static nextContext: o.ExternalReference = {name: 'ɵɵnextContext', moduleName: CORE};\n\n static resetView: o.ExternalReference = {name: 'ɵɵresetView', moduleName: CORE};\n\n static templateCreate: o.ExternalReference = {name: 'ɵɵtemplate', moduleName: CORE};\n\n static defer: o.ExternalReference = {name: 'ɵɵdefer', moduleName: CORE};\n static deferWhen: o.ExternalReference = {name: 'ɵɵdeferWhen', moduleName: CORE};\n static deferOnIdle: o.ExternalReference = {name: 'ɵɵdeferOnIdle', moduleName: CORE};\n static deferOnImmediate: o.ExternalReference = {name: 'ɵɵdeferOnImmediate', moduleName: CORE};\n static deferOnTimer: o.ExternalReference = {name: 'ɵɵdeferOnTimer', moduleName: CORE};\n static deferOnHover: o.ExternalReference = {name: 'ɵɵdeferOnHover', moduleName: CORE};\n static deferOnInteraction: o.ExternalReference = {name: 'ɵɵdeferOnInteraction', moduleName: CORE};\n static deferOnViewport: o.ExternalReference = {name: 'ɵɵdeferOnViewport', moduleName: CORE};\n static deferPrefetchWhen: o.ExternalReference = {name: 'ɵɵdeferPrefetchWhen', moduleName: CORE};\n static deferPrefetchOnIdle:\n o.ExternalReference = {name: 'ɵɵdeferPrefetchOnIdle', moduleName: CORE};\n static deferPrefetchOnImmediate:\n o.ExternalReference = {name: 'ɵɵdeferPrefetchOnImmediate', moduleName: CORE};\n static deferPrefetchOnTimer:\n o.ExternalReference = {name: 'ɵɵdeferPrefetchOnTimer', moduleName: CORE};\n static deferPrefetchOnHover:\n o.ExternalReference = {name: 'ɵɵdeferPrefetchOnHover', moduleName: CORE};\n static deferPrefetchOnInteraction:\n o.ExternalReference = {name: 'ɵɵdeferPrefetchOnInteraction', moduleName: CORE};\n static deferPrefetchOnViewport:\n o.ExternalReference = {name: 'ɵɵdeferPrefetchOnViewport', moduleName: CORE};\n static deferEnableTimerScheduling:\n o.ExternalReference = {name: 'ɵɵdeferEnableTimerScheduling', moduleName: CORE};\n\n static conditional: o.ExternalReference = {name: 'ɵɵconditional', moduleName: CORE};\n static repeater: o.ExternalReference = {name: 'ɵɵrepeater', moduleName: CORE};\n static repeaterCreate: o.ExternalReference = {name: 'ɵɵrepeaterCreate', moduleName: CORE};\n static repeaterTrackByIndex:\n o.ExternalReference = {name: 'ɵɵrepeaterTrackByIndex', moduleName: CORE};\n static repeaterTrackByIdentity:\n o.ExternalReference = {name: 'ɵɵrepeaterTrackByIdentity', moduleName: CORE};\n static componentInstance: o.ExternalReference = {name: 'ɵɵcomponentInstance', moduleName: CORE};\n\n static text: o.ExternalReference = {name: 'ɵɵtext', moduleName: CORE};\n\n static enableBindings: o.ExternalReference = {name: 'ɵɵenableBindings', moduleName: CORE};\n\n static disableBindings: o.ExternalReference = {name: 'ɵɵdisableBindings', moduleName: CORE};\n\n static getCurrentView: o.ExternalReference = {name: 'ɵɵgetCurrentView', moduleName: CORE};\n\n static textInterpolate: o.ExternalReference = {name: 'ɵɵtextInterpolate', moduleName: CORE};\n static textInterpolate1: o.ExternalReference = {name: 'ɵɵtextInterpolate1', moduleName: CORE};\n static textInterpolate2: o.ExternalReference = {name: 'ɵɵtextInterpolate2', moduleName: CORE};\n static textInterpolate3: o.ExternalReference = {name: 'ɵɵtextInterpolate3', moduleName: CORE};\n static textInterpolate4: o.ExternalReference = {name: 'ɵɵtextInterpolate4', moduleName: CORE};\n static textInterpolate5: o.ExternalReference = {name: 'ɵɵtextInterpolate5', moduleName: CORE};\n static textInterpolate6: o.ExternalReference = {name: 'ɵɵtextInterpolate6', moduleName: CORE};\n static textInterpolate7: o.ExternalReference = {name: 'ɵɵtextInterpolate7', moduleName: CORE};\n static textInterpolate8: o.ExternalReference = {name: 'ɵɵtextInterpolate8', moduleName: CORE};\n static textInterpolateV: o.ExternalReference = {name: 'ɵɵtextInterpolateV', moduleName: CORE};\n\n static restoreView: o.ExternalReference = {name: 'ɵɵrestoreView', moduleName: CORE};\n\n static pureFunction0: o.ExternalReference = {name: 'ɵɵpureFunction0', moduleName: CORE};\n static pureFunction1: o.ExternalReference = {name: 'ɵɵpureFunction1', moduleName: CORE};\n static pureFunction2: o.ExternalReference = {name: 'ɵɵpureFunction2', moduleName: CORE};\n static pureFunction3: o.ExternalReference = {name: 'ɵɵpureFunction3', moduleName: CORE};\n static pureFunction4: o.ExternalReference = {name: 'ɵɵpureFunction4', moduleName: CORE};\n static pureFunction5: o.ExternalReference = {name: 'ɵɵpureFunction5', moduleName: CORE};\n static pureFunction6: o.ExternalReference = {name: 'ɵɵpureFunction6', moduleName: CORE};\n static pureFunction7: o.ExternalReference = {name: 'ɵɵpureFunction7', moduleName: CORE};\n static pureFunction8: o.ExternalReference = {name: 'ɵɵpureFunction8', moduleName: CORE};\n static pureFunctionV: o.ExternalReference = {name: 'ɵɵpureFunctionV', moduleName: CORE};\n\n static pipeBind1: o.ExternalReference = {name: 'ɵɵpipeBind1', moduleName: CORE};\n static pipeBind2: o.ExternalReference = {name: 'ɵɵpipeBind2', moduleName: CORE};\n static pipeBind3: o.ExternalReference = {name: 'ɵɵpipeBind3', moduleName: CORE};\n static pipeBind4: o.ExternalReference = {name: 'ɵɵpipeBind4', moduleName: CORE};\n static pipeBindV: o.ExternalReference = {name: 'ɵɵpipeBindV', moduleName: CORE};\n\n static hostProperty: o.ExternalReference = {name: 'ɵɵhostProperty', moduleName: CORE};\n\n static property: o.ExternalReference = {name: 'ɵɵproperty', moduleName: CORE};\n\n static propertyInterpolate:\n o.ExternalReference = {name: 'ɵɵpropertyInterpolate', moduleName: CORE};\n static propertyInterpolate1:\n o.ExternalReference = {name: 'ɵɵpropertyInterpolate1', moduleName: CORE};\n static propertyInterpolate2:\n o.ExternalReference = {name: 'ɵɵpropertyInterpolate2', moduleName: CORE};\n static propertyInterpolate3:\n o.ExternalReference = {name: 'ɵɵpropertyInterpolate3', moduleName: CORE};\n static propertyInterpolate4:\n o.ExternalReference = {name: 'ɵɵpropertyInterpolate4', moduleName: CORE};\n static propertyInterpolate5:\n o.ExternalReference = {name: 'ɵɵpropertyInterpolate5', moduleName: CORE};\n static propertyInterpolate6:\n o.ExternalReference = {name: 'ɵɵpropertyInterpolate6', moduleName: CORE};\n static propertyInterpolate7:\n o.ExternalReference = {name: 'ɵɵpropertyInterpolate7', moduleName: CORE};\n static propertyInterpolate8:\n o.ExternalReference = {name: 'ɵɵpropertyInterpolate8', moduleName: CORE};\n static propertyInterpolateV:\n o.ExternalReference = {name: 'ɵɵpropertyInterpolateV', moduleName: CORE};\n\n static i18n: o.ExternalReference = {name: 'ɵɵi18n', moduleName: CORE};\n static i18nAttributes: o.ExternalReference = {name: 'ɵɵi18nAttributes', moduleName: CORE};\n static i18nExp: o.ExternalReference = {name: 'ɵɵi18nExp', moduleName: CORE};\n static i18nStart: o.ExternalReference = {name: 'ɵɵi18nStart', moduleName: CORE};\n static i18nEnd: o.ExternalReference = {name: 'ɵɵi18nEnd', moduleName: CORE};\n static i18nApply: o.ExternalReference = {name: 'ɵɵi18nApply', moduleName: CORE};\n static i18nPostprocess: o.ExternalReference = {name: 'ɵɵi18nPostprocess', moduleName: CORE};\n\n static pipe: o.ExternalReference = {name: 'ɵɵpipe', moduleName: CORE};\n\n static projection: o.ExternalReference = {name: 'ɵɵprojection', moduleName: CORE};\n static projectionDef: o.ExternalReference = {name: 'ɵɵprojectionDef', moduleName: CORE};\n\n static reference: o.ExternalReference = {name: 'ɵɵreference', moduleName: CORE};\n\n static inject: o.ExternalReference = {name: 'ɵɵinject', moduleName: CORE};\n\n static injectAttribute: o.ExternalReference = {name: 'ɵɵinjectAttribute', moduleName: CORE};\n\n static directiveInject: o.ExternalReference = {name: 'ɵɵdirectiveInject', moduleName: CORE};\n static invalidFactory: o.ExternalReference = {name: 'ɵɵinvalidFactory', moduleName: CORE};\n static invalidFactoryDep: o.ExternalReference = {name: 'ɵɵinvalidFactoryDep', moduleName: CORE};\n\n static templateRefExtractor:\n o.ExternalReference = {name: 'ɵɵtemplateRefExtractor', moduleName: CORE};\n\n static forwardRef: o.ExternalReference = {name: 'forwardRef', moduleName: CORE};\n static resolveForwardRef: o.ExternalReference = {name: 'resolveForwardRef', moduleName: CORE};\n\n static ɵɵdefineInjectable: o.ExternalReference = {name: 'ɵɵdefineInjectable', moduleName: CORE};\n static declareInjectable: o.ExternalReference = {name: 'ɵɵngDeclareInjectable', moduleName: CORE};\n static InjectableDeclaration:\n o.ExternalReference = {name: 'ɵɵInjectableDeclaration', moduleName: CORE};\n\n static resolveWindow: o.ExternalReference = {name: 'ɵɵresolveWindow', moduleName: CORE};\n static resolveDocument: o.ExternalReference = {name: 'ɵɵresolveDocument', moduleName: CORE};\n static resolveBody: o.ExternalReference = {name: 'ɵɵresolveBody', moduleName: CORE};\n\n static getComponentDepsFactory:\n o.ExternalReference = {name: 'ɵɵgetComponentDepsFactory', moduleName: CORE};\n\n static defineComponent: o.ExternalReference = {name: 'ɵɵdefineComponent', moduleName: CORE};\n static declareComponent: o.ExternalReference = {name: 'ɵɵngDeclareComponent', moduleName: CORE};\n\n static setComponentScope: o.ExternalReference = {name: 'ɵɵsetComponentScope', moduleName: CORE};\n\n static ChangeDetectionStrategy: o.ExternalReference = {\n name: 'ChangeDetectionStrategy',\n moduleName: CORE,\n };\n static ViewEncapsulation: o.ExternalReference = {\n name: 'ViewEncapsulation',\n moduleName: CORE,\n };\n\n static ComponentDeclaration: o.ExternalReference = {\n name: 'ɵɵComponentDeclaration',\n moduleName: CORE,\n };\n\n static FactoryDeclaration: o.ExternalReference = {\n name: 'ɵɵFactoryDeclaration',\n moduleName: CORE,\n };\n static declareFactory: o.ExternalReference = {name: 'ɵɵngDeclareFactory', moduleName: CORE};\n static FactoryTarget: o.ExternalReference = {name: 'ɵɵFactoryTarget', moduleName: CORE};\n\n static defineDirective: o.ExternalReference = {name: 'ɵɵdefineDirective', moduleName: CORE};\n static declareDirective: o.ExternalReference = {name: 'ɵɵngDeclareDirective', moduleName: CORE};\n\n static DirectiveDeclaration: o.ExternalReference = {\n name: 'ɵɵDirectiveDeclaration',\n moduleName: CORE,\n };\n\n static InjectorDef: o.ExternalReference = {name: 'ɵɵInjectorDef', moduleName: CORE};\n static InjectorDeclaration:\n o.ExternalReference = {name: 'ɵɵInjectorDeclaration', moduleName: CORE};\n\n static defineInjector: o.ExternalReference = {name: 'ɵɵdefineInjector', moduleName: CORE};\n static declareInjector: o.ExternalReference = {name: 'ɵɵngDeclareInjector', moduleName: CORE};\n\n static NgModuleDeclaration: o.ExternalReference = {\n name: 'ɵɵNgModuleDeclaration',\n moduleName: CORE,\n };\n\n static ModuleWithProviders: o.ExternalReference = {\n name: 'ModuleWithProviders',\n moduleName: CORE,\n };\n\n static defineNgModule: o.ExternalReference = {name: 'ɵɵdefineNgModule', moduleName: CORE};\n static declareNgModule: o.ExternalReference = {name: 'ɵɵngDeclareNgModule', moduleName: CORE};\n static setNgModuleScope: o.ExternalReference = {name: 'ɵɵsetNgModuleScope', moduleName: CORE};\n static registerNgModuleType:\n o.ExternalReference = {name: 'ɵɵregisterNgModuleType', moduleName: CORE};\n\n\n static PipeDeclaration: o.ExternalReference = {name: 'ɵɵPipeDeclaration', moduleName: CORE};\n\n static definePipe: o.ExternalReference = {name: 'ɵɵdefinePipe', moduleName: CORE};\n static declarePipe: o.ExternalReference = {name: 'ɵɵngDeclarePipe', moduleName: CORE};\n\n static declareClassMetadata:\n o.ExternalReference = {name: 'ɵɵngDeclareClassMetadata', moduleName: CORE};\n static setClassMetadata: o.ExternalReference = {name: 'ɵsetClassMetadata', moduleName: CORE};\n static setClassMetadataAsync:\n o.ExternalReference = {name: 'ɵsetClassMetadataAsync', moduleName: CORE};\n static setClassDebugInfo: o.ExternalReference = {name: 'ɵsetClassDebugInfo', moduleName: CORE};\n static queryRefresh: o.ExternalReference = {name: 'ɵɵqueryRefresh', moduleName: CORE};\n static viewQuery: o.ExternalReference = {name: 'ɵɵviewQuery', moduleName: CORE};\n static loadQuery: o.ExternalReference = {name: 'ɵɵloadQuery', moduleName: CORE};\n static contentQuery: o.ExternalReference = {name: 'ɵɵcontentQuery', moduleName: CORE};\n\n static NgOnChangesFeature: o.ExternalReference = {name: 'ɵɵNgOnChangesFeature', moduleName: CORE};\n\n static InheritDefinitionFeature:\n o.ExternalReference = {name: 'ɵɵInheritDefinitionFeature', moduleName: CORE};\n\n static CopyDefinitionFeature:\n o.ExternalReference = {name: 'ɵɵCopyDefinitionFeature', moduleName: CORE};\n\n static StandaloneFeature: o.ExternalReference = {name: 'ɵɵStandaloneFeature', moduleName: CORE};\n\n static ProvidersFeature: o.ExternalReference = {name: 'ɵɵProvidersFeature', moduleName: CORE};\n\n static HostDirectivesFeature:\n o.ExternalReference = {name: 'ɵɵHostDirectivesFeature', moduleName: CORE};\n\n static InputTransformsFeatureFeature:\n o.ExternalReference = {name: 'ɵɵInputTransformsFeature', moduleName: CORE};\n\n static listener: o.ExternalReference = {name: 'ɵɵlistener', moduleName: CORE};\n\n static getInheritedFactory: o.ExternalReference = {\n name: 'ɵɵgetInheritedFactory',\n moduleName: CORE,\n };\n\n static InputFlags: o.ExternalReference = {\n name: 'ɵɵInputFlags',\n moduleName: CORE,\n };\n\n // sanitization-related functions\n static sanitizeHtml: o.ExternalReference = {name: 'ɵɵsanitizeHtml', moduleName: CORE};\n static sanitizeStyle: o.ExternalReference = {name: 'ɵɵsanitizeStyle', moduleName: CORE};\n static sanitizeResourceUrl:\n o.ExternalReference = {name: 'ɵɵsanitizeResourceUrl', moduleName: CORE};\n static sanitizeScript: o.ExternalReference = {name: 'ɵɵsanitizeScript', moduleName: CORE};\n static sanitizeUrl: o.ExternalReference = {name: 'ɵɵsanitizeUrl', moduleName: CORE};\n static sanitizeUrlOrResourceUrl:\n o.ExternalReference = {name: 'ɵɵsanitizeUrlOrResourceUrl', moduleName: CORE};\n static trustConstantHtml: o.ExternalReference = {name: 'ɵɵtrustConstantHtml', moduleName: CORE};\n static trustConstantResourceUrl:\n o.ExternalReference = {name: 'ɵɵtrustConstantResourceUrl', moduleName: CORE};\n static validateIframeAttribute:\n o.ExternalReference = {name: 'ɵɵvalidateIframeAttribute', moduleName: CORE};\n\n // type-checking\n static InputSignalBrandWriteType = {name: 'ɵINPUT_SIGNAL_BRAND_WRITE_TYPE', moduleName: CORE};\n static UnwrapDirectiveSignalInputs = {name: 'ɵUnwrapDirectiveSignalInputs', moduleName: CORE};\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nconst DASH_CASE_REGEXP = /-+([a-z0-9])/g;\n\nexport function dashCaseToCamelCase(input: string): string {\n return input.replace(DASH_CASE_REGEXP, (...m: any[]) => m[1].toUpperCase());\n}\n\nexport function splitAtColon(input: string, defaultValues: string[]): string[] {\n return _splitAt(input, ':', defaultValues);\n}\n\nexport function splitAtPeriod(input: string, defaultValues: string[]): string[] {\n return _splitAt(input, '.', defaultValues);\n}\n\nfunction _splitAt(input: string, character: string, defaultValues: string[]): string[] {\n const characterIndex = input.indexOf(character);\n if (characterIndex == -1) return defaultValues;\n return [input.slice(0, characterIndex).trim(), input.slice(characterIndex + 1).trim()];\n}\n\nexport function noUndefined(val: T|undefined): T {\n return val === undefined ? null! : val;\n}\n\nexport function error(msg: string): never {\n throw new Error(`Internal Error: ${msg}`);\n}\n\n// Escape characters that have a special meaning in Regular Expressions\nexport function escapeRegExp(s: string): string {\n return s.replace(/([.*+?^=!:${}()|[\\]\\/\\\\])/g, '\\\\$1');\n}\n\nexport type Byte = number;\n\nexport function utf8Encode(str: string): Byte[] {\n let encoded: Byte[] = [];\n for (let index = 0; index < str.length; index++) {\n let codePoint = str.charCodeAt(index);\n\n // decode surrogate\n // see https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae\n if (codePoint >= 0xd800 && codePoint <= 0xdbff && str.length > (index + 1)) {\n const low = str.charCodeAt(index + 1);\n if (low >= 0xdc00 && low <= 0xdfff) {\n index++;\n codePoint = ((codePoint - 0xd800) << 10) + low - 0xdc00 + 0x10000;\n }\n }\n\n if (codePoint <= 0x7f) {\n encoded.push(codePoint);\n } else if (codePoint <= 0x7ff) {\n encoded.push(((codePoint >> 6) & 0x1F) | 0xc0, (codePoint & 0x3f) | 0x80);\n } else if (codePoint <= 0xffff) {\n encoded.push(\n (codePoint >> 12) | 0xe0, ((codePoint >> 6) & 0x3f) | 0x80, (codePoint & 0x3f) | 0x80);\n } else if (codePoint <= 0x1fffff) {\n encoded.push(\n ((codePoint >> 18) & 0x07) | 0xf0, ((codePoint >> 12) & 0x3f) | 0x80,\n ((codePoint >> 6) & 0x3f) | 0x80, (codePoint & 0x3f) | 0x80);\n }\n }\n\n return encoded;\n}\n\nexport function stringify(token: any): string {\n if (typeof token === 'string') {\n return token;\n }\n\n if (Array.isArray(token)) {\n return '[' + token.map(stringify).join(', ') + ']';\n }\n\n if (token == null) {\n return '' + token;\n }\n\n if (token.overriddenName) {\n return `${token.overriddenName}`;\n }\n\n if (token.name) {\n return `${token.name}`;\n }\n\n if (!token.toString) {\n return 'object';\n }\n\n // WARNING: do not try to `JSON.stringify(token)` here\n // see https://github.com/angular/angular/issues/23440\n const res = token.toString();\n\n if (res == null) {\n return '' + res;\n }\n\n const newLineIndex = res.indexOf('\\n');\n return newLineIndex === -1 ? res : res.substring(0, newLineIndex);\n}\n\nexport class Version {\n public readonly major: string;\n public readonly minor: string;\n public readonly patch: string;\n\n constructor(public full: string) {\n const splits = full.split('.');\n this.major = splits[0];\n this.minor = splits[1];\n this.patch = splits.slice(2).join('.');\n }\n}\n\nexport interface Console {\n log(message: string): void;\n warn(message: string): void;\n}\n\nconst _global: {[name: string]: any} = globalThis;\nexport {_global as global};\n\nexport function newArray(size: number): T[];\nexport function newArray(size: number, value: T): T[];\nexport function newArray(size: number, value?: T): T[] {\n const list: T[] = [];\n for (let i = 0; i < size; i++) {\n list.push(value!);\n }\n return list;\n}\n\n/**\n * Partitions a given array into 2 arrays, based on a boolean value returned by the condition\n * function.\n *\n * @param arr Input array that should be partitioned\n * @param conditionFn Condition function that is called for each item in a given array and returns a\n * boolean value.\n */\nexport function partitionArray(\n arr: (T|F)[], conditionFn: (value: T|F) => boolean): [T[], F[]] {\n const truthy: T[] = [];\n const falsy: F[] = [];\n for (const item of arr) {\n (conditionFn(item) ? truthy : falsy).push(item as any);\n }\n return [truthy, falsy];\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {utf8Encode} from '../util';\n\n// https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit\nconst VERSION = 3;\n\nconst JS_B64_PREFIX = '# sourceMappingURL=data:application/json;base64,';\n\ntype Segment = {\n col0: number,\n sourceUrl?: string,\n sourceLine0?: number,\n sourceCol0?: number,\n};\n\nexport type SourceMap = {\n version: number,\n file?: string,\n sourceRoot: string,\n sources: string[],\n sourcesContent: (string|null)[],\n mappings: string,\n};\n\nexport class SourceMapGenerator {\n private sourcesContent: Map = new Map();\n private lines: Segment[][] = [];\n private lastCol0: number = 0;\n private hasMappings = false;\n\n constructor(private file: string|null = null) {}\n\n // The content is `null` when the content is expected to be loaded using the URL\n addSource(url: string, content: string|null = null): this {\n if (!this.sourcesContent.has(url)) {\n this.sourcesContent.set(url, content);\n }\n return this;\n }\n\n addLine(): this {\n this.lines.push([]);\n this.lastCol0 = 0;\n return this;\n }\n\n addMapping(col0: number, sourceUrl?: string, sourceLine0?: number, sourceCol0?: number): this {\n if (!this.currentLine) {\n throw new Error(`A line must be added before mappings can be added`);\n }\n if (sourceUrl != null && !this.sourcesContent.has(sourceUrl)) {\n throw new Error(`Unknown source file \"${sourceUrl}\"`);\n }\n if (col0 == null) {\n throw new Error(`The column in the generated code must be provided`);\n }\n if (col0 < this.lastCol0) {\n throw new Error(`Mapping should be added in output order`);\n }\n if (sourceUrl && (sourceLine0 == null || sourceCol0 == null)) {\n throw new Error(`The source location must be provided when a source url is provided`);\n }\n\n this.hasMappings = true;\n this.lastCol0 = col0;\n this.currentLine.push({col0, sourceUrl, sourceLine0, sourceCol0});\n return this;\n }\n\n /**\n * @internal strip this from published d.ts files due to\n * https://github.com/microsoft/TypeScript/issues/36216\n */\n private get currentLine(): Segment[]|null {\n return this.lines.slice(-1)[0];\n }\n\n toJSON(): SourceMap|null {\n if (!this.hasMappings) {\n return null;\n }\n\n const sourcesIndex = new Map();\n const sources: string[] = [];\n const sourcesContent: (string|null)[] = [];\n\n Array.from(this.sourcesContent.keys()).forEach((url: string, i: number) => {\n sourcesIndex.set(url, i);\n sources.push(url);\n sourcesContent.push(this.sourcesContent.get(url) || null);\n });\n\n let mappings: string = '';\n let lastCol0: number = 0;\n let lastSourceIndex: number = 0;\n let lastSourceLine0: number = 0;\n let lastSourceCol0: number = 0;\n\n this.lines.forEach(segments => {\n lastCol0 = 0;\n\n mappings += segments\n .map(segment => {\n // zero-based starting column of the line in the generated code\n let segAsStr = toBase64VLQ(segment.col0 - lastCol0);\n lastCol0 = segment.col0;\n\n if (segment.sourceUrl != null) {\n // zero-based index into the “sources” list\n segAsStr +=\n toBase64VLQ(sourcesIndex.get(segment.sourceUrl)! - lastSourceIndex);\n lastSourceIndex = sourcesIndex.get(segment.sourceUrl)!;\n // the zero-based starting line in the original source\n segAsStr += toBase64VLQ(segment.sourceLine0! - lastSourceLine0);\n lastSourceLine0 = segment.sourceLine0!;\n // the zero-based starting column in the original source\n segAsStr += toBase64VLQ(segment.sourceCol0! - lastSourceCol0);\n lastSourceCol0 = segment.sourceCol0!;\n }\n\n return segAsStr;\n })\n .join(',');\n mappings += ';';\n });\n\n mappings = mappings.slice(0, -1);\n\n return {\n 'file': this.file || '',\n 'version': VERSION,\n 'sourceRoot': '',\n 'sources': sources,\n 'sourcesContent': sourcesContent,\n 'mappings': mappings,\n };\n }\n\n toJsComment(): string {\n return this.hasMappings ? '//' + JS_B64_PREFIX + toBase64String(JSON.stringify(this, null, 0)) :\n '';\n }\n}\n\nexport function toBase64String(value: string): string {\n let b64 = '';\n const encoded = utf8Encode(value);\n for (let i = 0; i < encoded.length;) {\n const i1 = encoded[i++];\n const i2 = i < encoded.length ? encoded[i++] : null;\n const i3 = i < encoded.length ? encoded[i++] : null;\n b64 += toBase64Digit(i1 >> 2);\n b64 += toBase64Digit(((i1 & 3) << 4) | (i2 === null ? 0 : i2 >> 4));\n b64 += i2 === null ? '=' : toBase64Digit(((i2 & 15) << 2) | (i3 === null ? 0 : i3 >> 6));\n b64 += i2 === null || i3 === null ? '=' : toBase64Digit(i3 & 63);\n }\n\n return b64;\n}\n\nfunction toBase64VLQ(value: number): string {\n value = value < 0 ? ((-value) << 1) + 1 : value << 1;\n\n let out = '';\n do {\n let digit = value & 31;\n value = value >> 5;\n if (value > 0) {\n digit = digit | 32;\n }\n out += toBase64Digit(digit);\n } while (value > 0);\n\n return out;\n}\n\nconst B64_DIGITS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\n\nfunction toBase64Digit(value: number): string {\n if (value < 0 || value >= 64) {\n throw new Error(`Can only encode value in the range [0, 63]`);\n }\n\n return B64_DIGITS[value];\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ParseSourceSpan} from '../parse_util';\n\nimport * as o from './output_ast';\nimport {SourceMapGenerator} from './source_map';\n\nconst _SINGLE_QUOTE_ESCAPE_STRING_RE = /'|\\\\|\\n|\\r|\\$/g;\nconst _LEGAL_IDENTIFIER_RE = /^[$A-Z_][0-9A-Z_$]*$/i;\nconst _INDENT_WITH = ' ';\n\nclass _EmittedLine {\n partsLength = 0;\n parts: string[] = [];\n srcSpans: (ParseSourceSpan|null)[] = [];\n constructor(public indent: number) {}\n}\n\nexport class EmitterVisitorContext {\n static createRoot(): EmitterVisitorContext {\n return new EmitterVisitorContext(0);\n }\n\n private _lines: _EmittedLine[];\n\n constructor(private _indent: number) {\n this._lines = [new _EmittedLine(_indent)];\n }\n\n /**\n * @internal strip this from published d.ts files due to\n * https://github.com/microsoft/TypeScript/issues/36216\n */\n private get _currentLine(): _EmittedLine {\n return this._lines[this._lines.length - 1];\n }\n\n println(from?: {sourceSpan: ParseSourceSpan|null}|null, lastPart: string = ''): void {\n this.print(from || null, lastPart, true);\n }\n\n lineIsEmpty(): boolean {\n return this._currentLine.parts.length === 0;\n }\n\n lineLength(): number {\n return this._currentLine.indent * _INDENT_WITH.length + this._currentLine.partsLength;\n }\n\n print(from: {sourceSpan: ParseSourceSpan|null}|null, part: string, newLine: boolean = false) {\n if (part.length > 0) {\n this._currentLine.parts.push(part);\n this._currentLine.partsLength += part.length;\n this._currentLine.srcSpans.push(from && from.sourceSpan || null);\n }\n if (newLine) {\n this._lines.push(new _EmittedLine(this._indent));\n }\n }\n\n removeEmptyLastLine() {\n if (this.lineIsEmpty()) {\n this._lines.pop();\n }\n }\n\n incIndent() {\n this._indent++;\n if (this.lineIsEmpty()) {\n this._currentLine.indent = this._indent;\n }\n }\n\n decIndent() {\n this._indent--;\n if (this.lineIsEmpty()) {\n this._currentLine.indent = this._indent;\n }\n }\n\n toSource(): string {\n return this.sourceLines\n .map(l => l.parts.length > 0 ? _createIndent(l.indent) + l.parts.join('') : '')\n .join('\\n');\n }\n\n toSourceMapGenerator(genFilePath: string, startsAtLine: number = 0): SourceMapGenerator {\n const map = new SourceMapGenerator(genFilePath);\n\n let firstOffsetMapped = false;\n const mapFirstOffsetIfNeeded = () => {\n if (!firstOffsetMapped) {\n // Add a single space so that tools won't try to load the file from disk.\n // Note: We are using virtual urls like `ng:///`, so we have to\n // provide a content here.\n map.addSource(genFilePath, ' ').addMapping(0, genFilePath, 0, 0);\n firstOffsetMapped = true;\n }\n };\n\n for (let i = 0; i < startsAtLine; i++) {\n map.addLine();\n mapFirstOffsetIfNeeded();\n }\n\n this.sourceLines.forEach((line, lineIdx) => {\n map.addLine();\n\n const spans = line.srcSpans;\n const parts = line.parts;\n let col0 = line.indent * _INDENT_WITH.length;\n let spanIdx = 0;\n // skip leading parts without source spans\n while (spanIdx < spans.length && !spans[spanIdx]) {\n col0 += parts[spanIdx].length;\n spanIdx++;\n }\n if (spanIdx < spans.length && lineIdx === 0 && col0 === 0) {\n firstOffsetMapped = true;\n } else {\n mapFirstOffsetIfNeeded();\n }\n\n while (spanIdx < spans.length) {\n const span = spans[spanIdx]!;\n const source = span.start.file;\n const sourceLine = span.start.line;\n const sourceCol = span.start.col;\n map.addSource(source.url, source.content)\n .addMapping(col0, source.url, sourceLine, sourceCol);\n\n col0 += parts[spanIdx].length;\n spanIdx++;\n\n // assign parts without span or the same span to the previous segment\n while (spanIdx < spans.length && (span === spans[spanIdx] || !spans[spanIdx])) {\n col0 += parts[spanIdx].length;\n spanIdx++;\n }\n }\n });\n\n return map;\n }\n\n spanOf(line: number, column: number): ParseSourceSpan|null {\n const emittedLine = this._lines[line];\n if (emittedLine) {\n let columnsLeft = column - _createIndent(emittedLine.indent).length;\n for (let partIndex = 0; partIndex < emittedLine.parts.length; partIndex++) {\n const part = emittedLine.parts[partIndex];\n if (part.length > columnsLeft) {\n return emittedLine.srcSpans[partIndex];\n }\n columnsLeft -= part.length;\n }\n }\n return null;\n }\n\n /**\n * @internal strip this from published d.ts files due to\n * https://github.com/microsoft/TypeScript/issues/36216\n */\n private get sourceLines(): _EmittedLine[] {\n if (this._lines.length && this._lines[this._lines.length - 1].parts.length === 0) {\n return this._lines.slice(0, -1);\n }\n return this._lines;\n }\n}\n\nexport abstract class AbstractEmitterVisitor implements o.StatementVisitor, o.ExpressionVisitor {\n constructor(private _escapeDollarInStrings: boolean) {}\n\n protected printLeadingComments(stmt: o.Statement, ctx: EmitterVisitorContext): void {\n if (stmt.leadingComments === undefined) {\n return;\n }\n for (const comment of stmt.leadingComments) {\n if (comment instanceof o.JSDocComment) {\n ctx.print(stmt, `/*${comment.toString()}*/`, comment.trailingNewline);\n } else {\n if (comment.multiline) {\n ctx.print(stmt, `/* ${comment.text} */`, comment.trailingNewline);\n } else {\n comment.text.split('\\n').forEach((line) => {\n ctx.println(stmt, `// ${line}`);\n });\n }\n }\n }\n }\n\n visitExpressionStmt(stmt: o.ExpressionStatement, ctx: EmitterVisitorContext): any {\n this.printLeadingComments(stmt, ctx);\n stmt.expr.visitExpression(this, ctx);\n ctx.println(stmt, ';');\n return null;\n }\n\n visitReturnStmt(stmt: o.ReturnStatement, ctx: EmitterVisitorContext): any {\n this.printLeadingComments(stmt, ctx);\n ctx.print(stmt, `return `);\n stmt.value.visitExpression(this, ctx);\n ctx.println(stmt, ';');\n return null;\n }\n\n visitIfStmt(stmt: o.IfStmt, ctx: EmitterVisitorContext): any {\n this.printLeadingComments(stmt, ctx);\n ctx.print(stmt, `if (`);\n stmt.condition.visitExpression(this, ctx);\n ctx.print(stmt, `) {`);\n const hasElseCase = stmt.falseCase != null && stmt.falseCase.length > 0;\n if (stmt.trueCase.length <= 1 && !hasElseCase) {\n ctx.print(stmt, ` `);\n this.visitAllStatements(stmt.trueCase, ctx);\n ctx.removeEmptyLastLine();\n ctx.print(stmt, ` `);\n } else {\n ctx.println();\n ctx.incIndent();\n this.visitAllStatements(stmt.trueCase, ctx);\n ctx.decIndent();\n if (hasElseCase) {\n ctx.println(stmt, `} else {`);\n ctx.incIndent();\n this.visitAllStatements(stmt.falseCase, ctx);\n ctx.decIndent();\n }\n }\n ctx.println(stmt, `}`);\n return null;\n }\n\n abstract visitDeclareVarStmt(stmt: o.DeclareVarStmt, ctx: EmitterVisitorContext): any;\n\n visitWriteVarExpr(expr: o.WriteVarExpr, ctx: EmitterVisitorContext): any {\n const lineWasEmpty = ctx.lineIsEmpty();\n if (!lineWasEmpty) {\n ctx.print(expr, '(');\n }\n ctx.print(expr, `${expr.name} = `);\n expr.value.visitExpression(this, ctx);\n if (!lineWasEmpty) {\n ctx.print(expr, ')');\n }\n return null;\n }\n visitWriteKeyExpr(expr: o.WriteKeyExpr, ctx: EmitterVisitorContext): any {\n const lineWasEmpty = ctx.lineIsEmpty();\n if (!lineWasEmpty) {\n ctx.print(expr, '(');\n }\n expr.receiver.visitExpression(this, ctx);\n ctx.print(expr, `[`);\n expr.index.visitExpression(this, ctx);\n ctx.print(expr, `] = `);\n expr.value.visitExpression(this, ctx);\n if (!lineWasEmpty) {\n ctx.print(expr, ')');\n }\n return null;\n }\n visitWritePropExpr(expr: o.WritePropExpr, ctx: EmitterVisitorContext): any {\n const lineWasEmpty = ctx.lineIsEmpty();\n if (!lineWasEmpty) {\n ctx.print(expr, '(');\n }\n expr.receiver.visitExpression(this, ctx);\n ctx.print(expr, `.${expr.name} = `);\n expr.value.visitExpression(this, ctx);\n if (!lineWasEmpty) {\n ctx.print(expr, ')');\n }\n return null;\n }\n\n visitInvokeFunctionExpr(expr: o.InvokeFunctionExpr, ctx: EmitterVisitorContext): any {\n const shouldParenthesize = expr.fn instanceof o.ArrowFunctionExpr;\n\n if (shouldParenthesize) {\n ctx.print(expr.fn, '(');\n }\n expr.fn.visitExpression(this, ctx);\n if (shouldParenthesize) {\n ctx.print(expr.fn, ')');\n }\n ctx.print(expr, `(`);\n this.visitAllExpressions(expr.args, ctx, ',');\n ctx.print(expr, `)`);\n return null;\n }\n visitTaggedTemplateExpr(expr: o.TaggedTemplateExpr, ctx: EmitterVisitorContext): any {\n expr.tag.visitExpression(this, ctx);\n ctx.print(expr, '`' + expr.template.elements[0].rawText);\n for (let i = 1; i < expr.template.elements.length; i++) {\n ctx.print(expr, '${');\n expr.template.expressions[i - 1].visitExpression(this, ctx);\n ctx.print(expr, `}${expr.template.elements[i].rawText}`);\n }\n ctx.print(expr, '`');\n return null;\n }\n visitWrappedNodeExpr(ast: o.WrappedNodeExpr, ctx: EmitterVisitorContext): any {\n throw new Error('Abstract emitter cannot visit WrappedNodeExpr.');\n }\n visitTypeofExpr(expr: o.TypeofExpr, ctx: EmitterVisitorContext): any {\n ctx.print(expr, 'typeof ');\n expr.expr.visitExpression(this, ctx);\n }\n visitReadVarExpr(ast: o.ReadVarExpr, ctx: EmitterVisitorContext): any {\n ctx.print(ast, ast.name);\n return null;\n }\n visitInstantiateExpr(ast: o.InstantiateExpr, ctx: EmitterVisitorContext): any {\n ctx.print(ast, `new `);\n ast.classExpr.visitExpression(this, ctx);\n ctx.print(ast, `(`);\n this.visitAllExpressions(ast.args, ctx, ',');\n ctx.print(ast, `)`);\n return null;\n }\n\n visitLiteralExpr(ast: o.LiteralExpr, ctx: EmitterVisitorContext): any {\n const value = ast.value;\n if (typeof value === 'string') {\n ctx.print(ast, escapeIdentifier(value, this._escapeDollarInStrings));\n } else {\n ctx.print(ast, `${value}`);\n }\n return null;\n }\n\n visitLocalizedString(ast: o.LocalizedString, ctx: EmitterVisitorContext): any {\n const head = ast.serializeI18nHead();\n ctx.print(ast, '$localize `' + head.raw);\n for (let i = 1; i < ast.messageParts.length; i++) {\n ctx.print(ast, '${');\n ast.expressions[i - 1].visitExpression(this, ctx);\n ctx.print(ast, `}${ast.serializeI18nTemplatePart(i).raw}`);\n }\n ctx.print(ast, '`');\n return null;\n }\n\n abstract visitExternalExpr(ast: o.ExternalExpr, ctx: EmitterVisitorContext): any;\n\n visitConditionalExpr(ast: o.ConditionalExpr, ctx: EmitterVisitorContext): any {\n ctx.print(ast, `(`);\n ast.condition.visitExpression(this, ctx);\n ctx.print(ast, '? ');\n ast.trueCase.visitExpression(this, ctx);\n ctx.print(ast, ': ');\n ast.falseCase!.visitExpression(this, ctx);\n ctx.print(ast, `)`);\n return null;\n }\n\n\n visitDynamicImportExpr(ast: o.DynamicImportExpr, ctx: EmitterVisitorContext) {\n ctx.print(ast, `import(${ast.url})`);\n }\n\n visitNotExpr(ast: o.NotExpr, ctx: EmitterVisitorContext): any {\n ctx.print(ast, '!');\n ast.condition.visitExpression(this, ctx);\n return null;\n }\n abstract visitFunctionExpr(ast: o.FunctionExpr, ctx: EmitterVisitorContext): any;\n abstract visitArrowFunctionExpr(ast: o.ArrowFunctionExpr, context: any): any;\n abstract visitDeclareFunctionStmt(stmt: o.DeclareFunctionStmt, context: any): any;\n\n visitUnaryOperatorExpr(ast: o.UnaryOperatorExpr, ctx: EmitterVisitorContext): any {\n let opStr: string;\n switch (ast.operator) {\n case o.UnaryOperator.Plus:\n opStr = '+';\n break;\n case o.UnaryOperator.Minus:\n opStr = '-';\n break;\n default:\n throw new Error(`Unknown operator ${ast.operator}`);\n }\n if (ast.parens) ctx.print(ast, `(`);\n ctx.print(ast, opStr);\n ast.expr.visitExpression(this, ctx);\n if (ast.parens) ctx.print(ast, `)`);\n return null;\n }\n\n visitBinaryOperatorExpr(ast: o.BinaryOperatorExpr, ctx: EmitterVisitorContext): any {\n let opStr: string;\n switch (ast.operator) {\n case o.BinaryOperator.Equals:\n opStr = '==';\n break;\n case o.BinaryOperator.Identical:\n opStr = '===';\n break;\n case o.BinaryOperator.NotEquals:\n opStr = '!=';\n break;\n case o.BinaryOperator.NotIdentical:\n opStr = '!==';\n break;\n case o.BinaryOperator.And:\n opStr = '&&';\n break;\n case o.BinaryOperator.BitwiseOr:\n opStr = '|';\n break;\n case o.BinaryOperator.BitwiseAnd:\n opStr = '&';\n break;\n case o.BinaryOperator.Or:\n opStr = '||';\n break;\n case o.BinaryOperator.Plus:\n opStr = '+';\n break;\n case o.BinaryOperator.Minus:\n opStr = '-';\n break;\n case o.BinaryOperator.Divide:\n opStr = '/';\n break;\n case o.BinaryOperator.Multiply:\n opStr = '*';\n break;\n case o.BinaryOperator.Modulo:\n opStr = '%';\n break;\n case o.BinaryOperator.Lower:\n opStr = '<';\n break;\n case o.BinaryOperator.LowerEquals:\n opStr = '<=';\n break;\n case o.BinaryOperator.Bigger:\n opStr = '>';\n break;\n case o.BinaryOperator.BiggerEquals:\n opStr = '>=';\n break;\n case o.BinaryOperator.NullishCoalesce:\n opStr = '??';\n break;\n default:\n throw new Error(`Unknown operator ${ast.operator}`);\n }\n if (ast.parens) ctx.print(ast, `(`);\n ast.lhs.visitExpression(this, ctx);\n ctx.print(ast, ` ${opStr} `);\n ast.rhs.visitExpression(this, ctx);\n if (ast.parens) ctx.print(ast, `)`);\n return null;\n }\n\n visitReadPropExpr(ast: o.ReadPropExpr, ctx: EmitterVisitorContext): any {\n ast.receiver.visitExpression(this, ctx);\n ctx.print(ast, `.`);\n ctx.print(ast, ast.name);\n return null;\n }\n visitReadKeyExpr(ast: o.ReadKeyExpr, ctx: EmitterVisitorContext): any {\n ast.receiver.visitExpression(this, ctx);\n ctx.print(ast, `[`);\n ast.index.visitExpression(this, ctx);\n ctx.print(ast, `]`);\n return null;\n }\n visitLiteralArrayExpr(ast: o.LiteralArrayExpr, ctx: EmitterVisitorContext): any {\n ctx.print(ast, `[`);\n this.visitAllExpressions(ast.entries, ctx, ',');\n ctx.print(ast, `]`);\n return null;\n }\n visitLiteralMapExpr(ast: o.LiteralMapExpr, ctx: EmitterVisitorContext): any {\n ctx.print(ast, `{`);\n this.visitAllObjects(entry => {\n ctx.print(ast, `${escapeIdentifier(entry.key, this._escapeDollarInStrings, entry.quoted)}:`);\n entry.value.visitExpression(this, ctx);\n }, ast.entries, ctx, ',');\n ctx.print(ast, `}`);\n return null;\n }\n visitCommaExpr(ast: o.CommaExpr, ctx: EmitterVisitorContext): any {\n ctx.print(ast, '(');\n this.visitAllExpressions(ast.parts, ctx, ',');\n ctx.print(ast, ')');\n return null;\n }\n visitAllExpressions(expressions: o.Expression[], ctx: EmitterVisitorContext, separator: string):\n void {\n this.visitAllObjects(expr => expr.visitExpression(this, ctx), expressions, ctx, separator);\n }\n\n visitAllObjects(\n handler: (t: T) => void, expressions: T[], ctx: EmitterVisitorContext,\n separator: string): void {\n let incrementedIndent = false;\n for (let i = 0; i < expressions.length; i++) {\n if (i > 0) {\n if (ctx.lineLength() > 80) {\n ctx.print(null, separator, true);\n if (!incrementedIndent) {\n // continuation are marked with double indent.\n ctx.incIndent();\n ctx.incIndent();\n incrementedIndent = true;\n }\n } else {\n ctx.print(null, separator, false);\n }\n }\n handler(expressions[i]);\n }\n if (incrementedIndent) {\n // continuation are marked with double indent.\n ctx.decIndent();\n ctx.decIndent();\n }\n }\n\n visitAllStatements(statements: o.Statement[], ctx: EmitterVisitorContext): void {\n statements.forEach((stmt) => stmt.visitStatement(this, ctx));\n }\n}\n\nexport function escapeIdentifier(\n input: string, escapeDollar: boolean, alwaysQuote: boolean = true): any {\n if (input == null) {\n return null;\n }\n const body = input.replace(_SINGLE_QUOTE_ESCAPE_STRING_RE, (...match: string[]) => {\n if (match[0] == '$') {\n return escapeDollar ? '\\\\$' : '$';\n } else if (match[0] == '\\n') {\n return '\\\\n';\n } else if (match[0] == '\\r') {\n return '\\\\r';\n } else {\n return `\\\\${match[0]}`;\n }\n });\n const requiresQuotes = alwaysQuote || !_LEGAL_IDENTIFIER_RE.test(body);\n return requiresQuotes ? `'${body}'` : body;\n}\n\nfunction _createIndent(count: number): string {\n let res = '';\n for (let i = 0; i < count; i++) {\n res += _INDENT_WITH;\n }\n return res;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {escapeIdentifier} from '../output/abstract_emitter';\nimport * as o from '../output/output_ast';\n\nimport {Identifiers} from './r3_identifiers';\n\nexport function typeWithParameters(type: o.Expression, numParams: number): o.ExpressionType {\n if (numParams === 0) {\n return o.expressionType(type);\n }\n const params: o.Type[] = [];\n for (let i = 0; i < numParams; i++) {\n params.push(o.DYNAMIC_TYPE);\n }\n return o.expressionType(type, undefined, params);\n}\n\nexport interface R3Reference {\n value: o.Expression;\n type: o.Expression;\n}\n\n/**\n * Result of compilation of a render3 code unit, e.g. component, directive, pipe, etc.\n */\nexport interface R3CompiledExpression {\n expression: o.Expression;\n type: o.Type;\n statements: o.Statement[];\n}\n\nconst ANIMATE_SYMBOL_PREFIX = '@';\nexport function prepareSyntheticPropertyName(name: string) {\n return `${ANIMATE_SYMBOL_PREFIX}${name}`;\n}\n\nexport function prepareSyntheticListenerName(name: string, phase: string) {\n return `${ANIMATE_SYMBOL_PREFIX}${name}.${phase}`;\n}\n\nexport function getSafePropertyAccessString(accessor: string, name: string): string {\n const escapedName = escapeIdentifier(name, false, false);\n return escapedName !== name ? `${accessor}[${escapedName}]` : `${accessor}.${name}`;\n}\n\nexport function prepareSyntheticListenerFunctionName(name: string, phase: string) {\n return `animation_${name}_${phase}`;\n}\n\nexport function jitOnlyGuardedExpression(expr: o.Expression): o.Expression {\n return guardedExpression('ngJitMode', expr);\n}\n\nexport function devOnlyGuardedExpression(expr: o.Expression): o.Expression {\n return guardedExpression('ngDevMode', expr);\n}\n\nexport function guardedExpression(guard: string, expr: o.Expression): o.Expression {\n const guardExpr = new o.ExternalExpr({name: guard, moduleName: null});\n const guardNotDefined = new o.BinaryOperatorExpr(\n o.BinaryOperator.Identical, new o.TypeofExpr(guardExpr), o.literal('undefined'));\n const guardUndefinedOrTrue = new o.BinaryOperatorExpr(\n o.BinaryOperator.Or, guardNotDefined, guardExpr, /* type */ undefined,\n /* sourceSpan */ undefined, true);\n return new o.BinaryOperatorExpr(o.BinaryOperator.And, guardUndefinedOrTrue, expr);\n}\n\nexport function wrapReference(value: any): R3Reference {\n const wrapped = new o.WrappedNodeExpr(value);\n return {value: wrapped, type: wrapped};\n}\n\nexport function refsToArray(refs: R3Reference[], shouldForwardDeclare: boolean): o.Expression {\n const values = o.literalArr(refs.map(ref => ref.value));\n return shouldForwardDeclare ? o.arrowFn([], values) : values;\n}\n\n\n/**\n * Describes an expression that may have been wrapped in a `forwardRef()` guard.\n *\n * This is used when describing expressions that can refer to types that may eagerly reference types\n * that have not yet been defined.\n */\nexport interface MaybeForwardRefExpression {\n /**\n * The unwrapped expression.\n */\n expression: T;\n /**\n * Specified whether the `expression` contains a reference to something that has not yet been\n * defined, and whether the expression is still wrapped in a `forwardRef()` call.\n *\n * If this value is `ForwardRefHandling.None` then the `expression` is safe to use as-is.\n *\n * Otherwise the `expression` was wrapped in a call to `forwardRef()` and must not be eagerly\n * evaluated. Instead it must be wrapped in a function closure that will be evaluated lazily to\n * allow the definition of the expression to be evaluated first.\n *\n * In full AOT compilation it can be safe to unwrap the `forwardRef()` call up front if the\n * expression will actually be evaluated lazily inside a function call after the value of\n * `expression` has been defined.\n *\n * But in other cases, such as partial AOT compilation or JIT compilation the expression will be\n * evaluated eagerly in top level code so will need to continue to be wrapped in a `forwardRef()`\n * call.\n *\n */\n forwardRef: ForwardRefHandling;\n}\n\nexport function createMayBeForwardRefExpression(\n expression: T, forwardRef: ForwardRefHandling): MaybeForwardRefExpression {\n return {expression, forwardRef};\n}\n\n/**\n * Convert a `MaybeForwardRefExpression` to an `Expression`, possibly wrapping its expression in a\n * `forwardRef()` call.\n *\n * If `MaybeForwardRefExpression.forwardRef` is `ForwardRefHandling.Unwrapped` then the expression\n * was originally wrapped in a `forwardRef()` call to prevent the value from being eagerly evaluated\n * in the code.\n *\n * See `packages/compiler-cli/src/ngtsc/annotations/src/injectable.ts` and\n * `packages/compiler/src/jit_compiler_facade.ts` for more information.\n */\nexport function convertFromMaybeForwardRefExpression(\n {expression, forwardRef}: MaybeForwardRefExpression): o.Expression {\n switch (forwardRef) {\n case ForwardRefHandling.None:\n case ForwardRefHandling.Wrapped:\n return expression;\n case ForwardRefHandling.Unwrapped:\n return generateForwardRef(expression);\n }\n}\n\n/**\n * Generate an expression that has the given `expr` wrapped in the following form:\n *\n * ```\n * forwardRef(() => expr)\n * ```\n */\nexport function generateForwardRef(expr: o.Expression): o.Expression {\n return o.importExpr(Identifiers.forwardRef).callFn([o.arrowFn([], expr)]);\n}\n\n/**\n * Specifies how a forward ref has been handled in a MaybeForwardRefExpression\n */\nexport const enum ForwardRefHandling {\n /** The expression was not wrapped in a `forwardRef()` call in the first place. */\n None,\n /** The expression is still wrapped in a `forwardRef()` call. */\n Wrapped,\n /** The expression was wrapped in a `forwardRef()` call but has since been unwrapped. */\n Unwrapped,\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {InjectFlags} from '../core';\nimport * as o from '../output/output_ast';\nimport {Identifiers as R3} from '../render3/r3_identifiers';\n\nimport {R3CompiledExpression, R3Reference, typeWithParameters} from './util';\n\n\n/**\n * Metadata required by the factory generator to generate a `factory` function for a type.\n */\nexport interface R3ConstructorFactoryMetadata {\n /**\n * String name of the type being generated (used to name the factory function).\n */\n name: string;\n\n /**\n * An expression representing the interface type being constructed.\n */\n type: R3Reference;\n\n /** Number of arguments for the `type`. */\n typeArgumentCount: number;\n\n /**\n * Regardless of whether `fnOrClass` is a constructor function or a user-defined factory, it\n * may have 0 or more parameters, which will be injected according to the `R3DependencyMetadata`\n * for those parameters. If this is `null`, then the type's constructor is nonexistent and will\n * be inherited from `fnOrClass` which is interpreted as the current type. If this is `'invalid'`,\n * then one or more of the parameters wasn't resolvable and any attempt to use these deps will\n * result in a runtime error.\n */\n deps: R3DependencyMetadata[]|'invalid'|null;\n\n /**\n * Type of the target being created by the factory.\n */\n target: FactoryTarget;\n}\n\nexport enum R3FactoryDelegateType {\n Class = 0,\n Function = 1,\n}\n\nexport interface R3DelegatedFnOrClassMetadata extends R3ConstructorFactoryMetadata {\n delegate: o.Expression;\n delegateType: R3FactoryDelegateType;\n delegateDeps: R3DependencyMetadata[];\n}\n\nexport interface R3ExpressionFactoryMetadata extends R3ConstructorFactoryMetadata {\n expression: o.Expression;\n}\n\nexport type R3FactoryMetadata =\n R3ConstructorFactoryMetadata|R3DelegatedFnOrClassMetadata|R3ExpressionFactoryMetadata;\n\nexport enum FactoryTarget {\n Directive = 0,\n Component = 1,\n Injectable = 2,\n Pipe = 3,\n NgModule = 4,\n}\n\nexport interface R3DependencyMetadata {\n /**\n * An expression representing the token or value to be injected.\n * Or `null` if the dependency could not be resolved - making it invalid.\n */\n token: o.Expression|null;\n\n /**\n * If an @Attribute decorator is present, this is the literal type of the attribute name, or\n * the unknown type if no literal type is available (e.g. the attribute name is an expression).\n * Otherwise it is null;\n */\n attributeNameType: o.Expression|null;\n\n /**\n * Whether the dependency has an @Host qualifier.\n */\n host: boolean;\n\n /**\n * Whether the dependency has an @Optional qualifier.\n */\n optional: boolean;\n\n /**\n * Whether the dependency has an @Self qualifier.\n */\n self: boolean;\n\n /**\n * Whether the dependency has an @SkipSelf qualifier.\n */\n skipSelf: boolean;\n}\n\n/**\n * Construct a factory function expression for the given `R3FactoryMetadata`.\n */\nexport function compileFactoryFunction(meta: R3FactoryMetadata): R3CompiledExpression {\n const t = o.variable('t');\n let baseFactoryVar: o.ReadVarExpr|null = null;\n\n // The type to instantiate via constructor invocation. If there is no delegated factory, meaning\n // this type is always created by constructor invocation, then this is the type-to-create\n // parameter provided by the user (t) if specified, or the current type if not. If there is a\n // delegated factory (which is used to create the current type) then this is only the type-to-\n // create parameter (t).\n const typeForCtor = !isDelegatedFactoryMetadata(meta) ?\n new o.BinaryOperatorExpr(o.BinaryOperator.Or, t, meta.type.value) :\n t;\n\n let ctorExpr: o.Expression|null = null;\n if (meta.deps !== null) {\n // There is a constructor (either explicitly or implicitly defined).\n if (meta.deps !== 'invalid') {\n ctorExpr = new o.InstantiateExpr(typeForCtor, injectDependencies(meta.deps, meta.target));\n }\n } else {\n // There is no constructor, use the base class' factory to construct typeForCtor.\n baseFactoryVar = o.variable(`ɵ${meta.name}_BaseFactory`);\n ctorExpr = baseFactoryVar.callFn([typeForCtor]);\n }\n\n const body: o.Statement[] = [];\n let retExpr: o.Expression|null = null;\n\n function makeConditionalFactory(nonCtorExpr: o.Expression): o.ReadVarExpr {\n const r = o.variable('r');\n body.push(r.set(o.NULL_EXPR).toDeclStmt());\n const ctorStmt = ctorExpr !== null ? r.set(ctorExpr).toStmt() :\n o.importExpr(R3.invalidFactory).callFn([]).toStmt();\n body.push(o.ifStmt(t, [ctorStmt], [r.set(nonCtorExpr).toStmt()]));\n return r;\n }\n\n if (isDelegatedFactoryMetadata(meta)) {\n // This type is created with a delegated factory. If a type parameter is not specified, call\n // the factory instead.\n const delegateArgs = injectDependencies(meta.delegateDeps, meta.target);\n // Either call `new delegate(...)` or `delegate(...)` depending on meta.delegateType.\n const factoryExpr = new (\n meta.delegateType === R3FactoryDelegateType.Class ?\n o.InstantiateExpr :\n o.InvokeFunctionExpr)(meta.delegate, delegateArgs);\n retExpr = makeConditionalFactory(factoryExpr);\n } else if (isExpressionFactoryMetadata(meta)) {\n // TODO(alxhub): decide whether to lower the value here or in the caller\n retExpr = makeConditionalFactory(meta.expression);\n } else {\n retExpr = ctorExpr;\n }\n\n\n if (retExpr === null) {\n // The expression cannot be formed so render an `ɵɵinvalidFactory()` call.\n body.push(o.importExpr(R3.invalidFactory).callFn([]).toStmt());\n } else if (baseFactoryVar !== null) {\n // This factory uses a base factory, so call `ɵɵgetInheritedFactory()` to compute it.\n const getInheritedFactoryCall = o.importExpr(R3.getInheritedFactory).callFn([meta.type.value]);\n // Memoize the base factoryFn: `baseFactory || (baseFactory = ɵɵgetInheritedFactory(...))`\n const baseFactory = new o.BinaryOperatorExpr(\n o.BinaryOperator.Or, baseFactoryVar, baseFactoryVar.set(getInheritedFactoryCall));\n body.push(new o.ReturnStatement(baseFactory.callFn([typeForCtor])));\n } else {\n // This is straightforward factory, just return it.\n body.push(new o.ReturnStatement(retExpr));\n }\n\n let factoryFn: o.Expression = o.fn(\n [new o.FnParam('t', o.DYNAMIC_TYPE)], body, o.INFERRED_TYPE, undefined,\n `${meta.name}_Factory`);\n\n if (baseFactoryVar !== null) {\n // There is a base factory variable so wrap its declaration along with the factory function into\n // an IIFE.\n factoryFn = o.arrowFn([], [\n new o.DeclareVarStmt(baseFactoryVar.name!), new o.ReturnStatement(factoryFn)\n ]).callFn([], /* sourceSpan */ undefined, /* pure */ true);\n }\n\n return {\n expression: factoryFn,\n statements: [],\n type: createFactoryType(meta),\n };\n}\n\nexport function createFactoryType(meta: R3FactoryMetadata) {\n const ctorDepsType =\n meta.deps !== null && meta.deps !== 'invalid' ? createCtorDepsType(meta.deps) : o.NONE_TYPE;\n return o.expressionType(o.importExpr(\n R3.FactoryDeclaration,\n [typeWithParameters(meta.type.type, meta.typeArgumentCount), ctorDepsType]));\n}\n\nfunction injectDependencies(deps: R3DependencyMetadata[], target: FactoryTarget): o.Expression[] {\n return deps.map((dep, index) => compileInjectDependency(dep, target, index));\n}\n\nfunction compileInjectDependency(\n dep: R3DependencyMetadata, target: FactoryTarget, index: number): o.Expression {\n // Interpret the dependency according to its resolved type.\n if (dep.token === null) {\n return o.importExpr(R3.invalidFactoryDep).callFn([o.literal(index)]);\n } else if (dep.attributeNameType === null) {\n // Build up the injection flags according to the metadata.\n const flags = InjectFlags.Default | (dep.self ? InjectFlags.Self : 0) |\n (dep.skipSelf ? InjectFlags.SkipSelf : 0) | (dep.host ? InjectFlags.Host : 0) |\n (dep.optional ? InjectFlags.Optional : 0) |\n (target === FactoryTarget.Pipe ? InjectFlags.ForPipe : 0);\n\n // If this dependency is optional or otherwise has non-default flags, then additional\n // parameters describing how to inject the dependency must be passed to the inject function\n // that's being used.\n let flagsParam: o.LiteralExpr|null =\n (flags !== InjectFlags.Default || dep.optional) ? o.literal(flags) : null;\n\n // Build up the arguments to the injectFn call.\n const injectArgs = [dep.token];\n if (flagsParam) {\n injectArgs.push(flagsParam);\n }\n const injectFn = getInjectFn(target);\n return o.importExpr(injectFn).callFn(injectArgs);\n } else {\n // The `dep.attributeTypeName` value is defined, which indicates that this is an `@Attribute()`\n // type dependency. For the generated JS we still want to use the `dep.token` value in case the\n // name given for the attribute is not a string literal. For example given `@Attribute(foo())`,\n // we want to generate `ɵɵinjectAttribute(foo())`.\n //\n // The `dep.attributeTypeName` is only actually used (in `createCtorDepType()`) to generate\n // typings.\n return o.importExpr(R3.injectAttribute).callFn([dep.token]);\n }\n}\n\nfunction createCtorDepsType(deps: R3DependencyMetadata[]): o.Type {\n let hasTypes = false;\n const attributeTypes = deps.map(dep => {\n const type = createCtorDepType(dep);\n if (type !== null) {\n hasTypes = true;\n return type;\n } else {\n return o.literal(null);\n }\n });\n\n if (hasTypes) {\n return o.expressionType(o.literalArr(attributeTypes));\n } else {\n return o.NONE_TYPE;\n }\n}\n\nfunction createCtorDepType(dep: R3DependencyMetadata): o.LiteralMapExpr|null {\n const entries: {key: string, quoted: boolean, value: o.Expression}[] = [];\n\n if (dep.attributeNameType !== null) {\n entries.push({key: 'attribute', value: dep.attributeNameType, quoted: false});\n }\n if (dep.optional) {\n entries.push({key: 'optional', value: o.literal(true), quoted: false});\n }\n if (dep.host) {\n entries.push({key: 'host', value: o.literal(true), quoted: false});\n }\n if (dep.self) {\n entries.push({key: 'self', value: o.literal(true), quoted: false});\n }\n if (dep.skipSelf) {\n entries.push({key: 'skipSelf', value: o.literal(true), quoted: false});\n }\n\n return entries.length > 0 ? o.literalMap(entries) : null;\n}\n\nexport function isDelegatedFactoryMetadata(meta: R3FactoryMetadata):\n meta is R3DelegatedFnOrClassMetadata {\n return (meta as any).delegateType !== undefined;\n}\n\nexport function isExpressionFactoryMetadata(meta: R3FactoryMetadata):\n meta is R3ExpressionFactoryMetadata {\n return (meta as any).expression !== undefined;\n}\n\nfunction getInjectFn(target: FactoryTarget): o.ExternalReference {\n switch (target) {\n case FactoryTarget.Component:\n case FactoryTarget.Directive:\n case FactoryTarget.Pipe:\n return R3.directiveInject;\n case FactoryTarget.NgModule:\n case FactoryTarget.Injectable:\n default:\n return R3.inject;\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nexport enum TagContentType {\n RAW_TEXT,\n ESCAPABLE_RAW_TEXT,\n PARSABLE_DATA\n}\n\nexport interface TagDefinition {\n closedByParent: boolean;\n implicitNamespacePrefix: string|null;\n isVoid: boolean;\n ignoreFirstLf: boolean;\n canSelfClose: boolean;\n preventNamespaceInheritance: boolean;\n\n isClosedByChild(name: string): boolean;\n getContentType(prefix?: string): TagContentType;\n}\n\nexport function splitNsName(elementName: string, fatal: boolean = true): [string|null, string] {\n if (elementName[0] != ':') {\n return [null, elementName];\n }\n\n const colonIndex = elementName.indexOf(':', 1);\n\n if (colonIndex === -1) {\n if (fatal) {\n throw new Error(`Unsupported format \"${elementName}\" expecting \":namespace:name\"`);\n } else {\n return [null, elementName];\n }\n }\n\n return [elementName.slice(1, colonIndex), elementName.slice(colonIndex + 1)];\n}\n\n// `` tags work the same regardless the namespace\nexport function isNgContainer(tagName: string): boolean {\n return splitNsName(tagName)[1] === 'ng-container';\n}\n\n// `` tags work the same regardless the namespace\nexport function isNgContent(tagName: string): boolean {\n return splitNsName(tagName)[1] === 'ng-content';\n}\n\n// `` tags work the same regardless the namespace\nexport function isNgTemplate(tagName: string): boolean {\n return splitNsName(tagName)[1] === 'ng-template';\n}\n\nexport function getNsPrefix(fullName: string): string;\nexport function getNsPrefix(fullName: null): null;\nexport function getNsPrefix(fullName: string|null): string|null {\n return fullName === null ? null : splitNsName(fullName)[0];\n}\n\nexport function mergeNsAndName(prefix: string, localName: string): string {\n return prefix ? `:${prefix}:${localName}` : localName;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {SecurityContext} from '../core';\nimport {AST, ASTWithSource, BindingType, BoundElementProperty, ParsedEvent, ParsedEventType} from '../expression_parser/ast';\nimport {I18nMeta} from '../i18n/i18n_ast';\nimport {ParseSourceSpan} from '../parse_util';\n\nexport interface Node {\n sourceSpan: ParseSourceSpan;\n visit(visitor: Visitor): Result;\n}\n\n/**\n * This is an R3 `Node`-like wrapper for a raw `html.Comment` node. We do not currently\n * require the implementation of a visitor for Comments as they are only collected at\n * the top-level of the R3 AST, and only if `Render3ParseOptions['collectCommentNodes']`\n * is true.\n */\nexport class Comment implements Node {\n constructor(public value: string, public sourceSpan: ParseSourceSpan) {}\n visit(_visitor: Visitor): Result {\n throw new Error('visit() not implemented for Comment');\n }\n}\n\nexport class Text implements Node {\n constructor(public value: string, public sourceSpan: ParseSourceSpan) {}\n visit(visitor: Visitor): Result {\n return visitor.visitText(this);\n }\n}\n\nexport class BoundText implements Node {\n constructor(public value: AST, public sourceSpan: ParseSourceSpan, public i18n?: I18nMeta) {}\n visit(visitor: Visitor): Result {\n return visitor.visitBoundText(this);\n }\n}\n\n/**\n * Represents a text attribute in the template.\n *\n * `valueSpan` may not be present in cases where there is no value `
`.\n * `keySpan` may also not be present for synthetic attributes from ICU expansions.\n */\nexport class TextAttribute implements Node {\n constructor(\n public name: string, public value: string, public sourceSpan: ParseSourceSpan,\n readonly keySpan: ParseSourceSpan|undefined, public valueSpan?: ParseSourceSpan,\n public i18n?: I18nMeta) {}\n visit(visitor: Visitor): Result {\n return visitor.visitTextAttribute(this);\n }\n}\n\nexport class BoundAttribute implements Node {\n constructor(\n public name: string, public type: BindingType, public securityContext: SecurityContext,\n public value: AST, public unit: string|null, public sourceSpan: ParseSourceSpan,\n readonly keySpan: ParseSourceSpan, public valueSpan: ParseSourceSpan|undefined,\n public i18n: I18nMeta|undefined) {}\n\n static fromBoundElementProperty(prop: BoundElementProperty, i18n?: I18nMeta): BoundAttribute {\n if (prop.keySpan === undefined) {\n throw new Error(\n `Unexpected state: keySpan must be defined for bound attributes but was not for ${\n prop.name}: ${prop.sourceSpan}`);\n }\n return new BoundAttribute(\n prop.name, prop.type, prop.securityContext, prop.value, prop.unit, prop.sourceSpan,\n prop.keySpan, prop.valueSpan, i18n);\n }\n\n visit(visitor: Visitor): Result {\n return visitor.visitBoundAttribute(this);\n }\n}\n\nexport class BoundEvent implements Node {\n constructor(\n public name: string, public type: ParsedEventType, public handler: AST,\n public target: string|null, public phase: string|null, public sourceSpan: ParseSourceSpan,\n public handlerSpan: ParseSourceSpan, readonly keySpan: ParseSourceSpan) {}\n\n static fromParsedEvent(event: ParsedEvent) {\n const target: string|null = event.type === ParsedEventType.Regular ? event.targetOrPhase : null;\n const phase: string|null =\n event.type === ParsedEventType.Animation ? event.targetOrPhase : null;\n if (event.keySpan === undefined) {\n throw new Error(`Unexpected state: keySpan must be defined for bound event but was not for ${\n event.name}: ${event.sourceSpan}`);\n }\n return new BoundEvent(\n event.name, event.type, event.handler, target, phase, event.sourceSpan, event.handlerSpan,\n event.keySpan);\n }\n\n visit(visitor: Visitor): Result {\n return visitor.visitBoundEvent(this);\n }\n}\n\nexport class Element implements Node {\n constructor(\n public name: string, public attributes: TextAttribute[], public inputs: BoundAttribute[],\n public outputs: BoundEvent[], public children: Node[], public references: Reference[],\n public sourceSpan: ParseSourceSpan, public startSourceSpan: ParseSourceSpan,\n public endSourceSpan: ParseSourceSpan|null, public i18n?: I18nMeta) {}\n visit(visitor: Visitor): Result {\n return visitor.visitElement(this);\n }\n}\n\nexport abstract class DeferredTrigger implements Node {\n constructor(\n public nameSpan: ParseSourceSpan|null, public sourceSpan: ParseSourceSpan,\n public prefetchSpan: ParseSourceSpan|null, public whenOrOnSourceSpan: ParseSourceSpan|null) {}\n\n visit(visitor: Visitor): Result {\n return visitor.visitDeferredTrigger(this);\n }\n}\n\nexport class BoundDeferredTrigger extends DeferredTrigger {\n constructor(\n public value: AST, sourceSpan: ParseSourceSpan, prefetchSpan: ParseSourceSpan|null,\n whenSourceSpan: ParseSourceSpan) {\n // BoundDeferredTrigger is for 'when' triggers. These aren't really \"triggers\" and don't have a\n // nameSpan. Trigger names are the built in event triggers like hover, interaction, etc.\n super(/** nameSpan */ null, sourceSpan, prefetchSpan, whenSourceSpan);\n }\n}\n\nexport class IdleDeferredTrigger extends DeferredTrigger {}\n\nexport class ImmediateDeferredTrigger extends DeferredTrigger {}\n\nexport class HoverDeferredTrigger extends DeferredTrigger {\n constructor(\n public reference: string|null, nameSpan: ParseSourceSpan, sourceSpan: ParseSourceSpan,\n prefetchSpan: ParseSourceSpan|null, onSourceSpan: ParseSourceSpan|null) {\n super(nameSpan, sourceSpan, prefetchSpan, onSourceSpan);\n }\n}\n\nexport class TimerDeferredTrigger extends DeferredTrigger {\n constructor(\n public delay: number, nameSpan: ParseSourceSpan, sourceSpan: ParseSourceSpan,\n prefetchSpan: ParseSourceSpan|null, onSourceSpan: ParseSourceSpan|null) {\n super(nameSpan, sourceSpan, prefetchSpan, onSourceSpan);\n }\n}\n\nexport class InteractionDeferredTrigger extends DeferredTrigger {\n constructor(\n public reference: string|null, nameSpan: ParseSourceSpan, sourceSpan: ParseSourceSpan,\n prefetchSpan: ParseSourceSpan|null, onSourceSpan: ParseSourceSpan|null) {\n super(nameSpan, sourceSpan, prefetchSpan, onSourceSpan);\n }\n}\n\nexport class ViewportDeferredTrigger extends DeferredTrigger {\n constructor(\n public reference: string|null, nameSpan: ParseSourceSpan, sourceSpan: ParseSourceSpan,\n prefetchSpan: ParseSourceSpan|null, onSourceSpan: ParseSourceSpan|null) {\n super(nameSpan, sourceSpan, prefetchSpan, onSourceSpan);\n }\n}\n\nexport class BlockNode {\n constructor(\n public nameSpan: ParseSourceSpan, public sourceSpan: ParseSourceSpan,\n public startSourceSpan: ParseSourceSpan, public endSourceSpan: ParseSourceSpan|null) {}\n}\n\nexport class DeferredBlockPlaceholder extends BlockNode implements Node {\n constructor(\n public children: Node[], public minimumTime: number|null, nameSpan: ParseSourceSpan,\n sourceSpan: ParseSourceSpan, startSourceSpan: ParseSourceSpan,\n endSourceSpan: ParseSourceSpan|null, public i18n?: I18nMeta) {\n super(nameSpan, sourceSpan, startSourceSpan, endSourceSpan);\n }\n\n visit(visitor: Visitor): Result {\n return visitor.visitDeferredBlockPlaceholder(this);\n }\n}\n\nexport class DeferredBlockLoading extends BlockNode implements Node {\n constructor(\n public children: Node[], public afterTime: number|null, public minimumTime: number|null,\n nameSpan: ParseSourceSpan, sourceSpan: ParseSourceSpan, startSourceSpan: ParseSourceSpan,\n endSourceSpan: ParseSourceSpan|null, public i18n?: I18nMeta) {\n super(nameSpan, sourceSpan, startSourceSpan, endSourceSpan);\n }\n\n visit(visitor: Visitor): Result {\n return visitor.visitDeferredBlockLoading(this);\n }\n}\n\nexport class DeferredBlockError extends BlockNode implements Node {\n constructor(\n public children: Node[], nameSpan: ParseSourceSpan, sourceSpan: ParseSourceSpan,\n startSourceSpan: ParseSourceSpan, endSourceSpan: ParseSourceSpan|null,\n public i18n?: I18nMeta) {\n super(nameSpan, sourceSpan, startSourceSpan, endSourceSpan);\n }\n\n visit(visitor: Visitor): Result {\n return visitor.visitDeferredBlockError(this);\n }\n}\n\nexport interface DeferredBlockTriggers {\n when?: BoundDeferredTrigger;\n idle?: IdleDeferredTrigger;\n immediate?: ImmediateDeferredTrigger;\n hover?: HoverDeferredTrigger;\n timer?: TimerDeferredTrigger;\n interaction?: InteractionDeferredTrigger;\n viewport?: ViewportDeferredTrigger;\n}\n\nexport class DeferredBlock extends BlockNode implements Node {\n readonly triggers: Readonly;\n readonly prefetchTriggers: Readonly;\n private readonly definedTriggers: (keyof DeferredBlockTriggers)[];\n private readonly definedPrefetchTriggers: (keyof DeferredBlockTriggers)[];\n\n constructor(\n public children: Node[], triggers: DeferredBlockTriggers,\n prefetchTriggers: DeferredBlockTriggers, public placeholder: DeferredBlockPlaceholder|null,\n public loading: DeferredBlockLoading|null, public error: DeferredBlockError|null,\n nameSpan: ParseSourceSpan, sourceSpan: ParseSourceSpan, public mainBlockSpan: ParseSourceSpan,\n startSourceSpan: ParseSourceSpan, endSourceSpan: ParseSourceSpan|null,\n public i18n?: I18nMeta) {\n super(nameSpan, sourceSpan, startSourceSpan, endSourceSpan);\n this.triggers = triggers;\n this.prefetchTriggers = prefetchTriggers;\n // We cache the keys since we know that they won't change and we\n // don't want to enumarate them every time we're traversing the AST.\n this.definedTriggers = Object.keys(triggers) as (keyof DeferredBlockTriggers)[];\n this.definedPrefetchTriggers = Object.keys(prefetchTriggers) as (keyof DeferredBlockTriggers)[];\n }\n\n visit(visitor: Visitor): Result {\n return visitor.visitDeferredBlock(this);\n }\n\n visitAll(visitor: Visitor): void {\n this.visitTriggers(this.definedTriggers, this.triggers, visitor);\n this.visitTriggers(this.definedPrefetchTriggers, this.prefetchTriggers, visitor);\n visitAll(visitor, this.children);\n const remainingBlocks =\n [this.placeholder, this.loading, this.error].filter(x => x !== null) as Array;\n visitAll(visitor, remainingBlocks);\n }\n\n private visitTriggers(\n keys: (keyof DeferredBlockTriggers)[], triggers: DeferredBlockTriggers, visitor: Visitor) {\n visitAll(visitor, keys.map(k => triggers[k]!));\n }\n}\n\nexport class SwitchBlock extends BlockNode implements Node {\n constructor(\n public expression: AST, public cases: SwitchBlockCase[],\n /**\n * These blocks are only captured to allow for autocompletion in the language service. They\n * aren't meant to be processed in any other way.\n */\n public unknownBlocks: UnknownBlock[], sourceSpan: ParseSourceSpan,\n startSourceSpan: ParseSourceSpan, endSourceSpan: ParseSourceSpan|null,\n nameSpan: ParseSourceSpan) {\n super(nameSpan, sourceSpan, startSourceSpan, endSourceSpan);\n }\n\n visit(visitor: Visitor): Result {\n return visitor.visitSwitchBlock(this);\n }\n}\n\nexport class SwitchBlockCase extends BlockNode implements Node {\n constructor(\n public expression: AST|null, public children: Node[], sourceSpan: ParseSourceSpan,\n startSourceSpan: ParseSourceSpan, endSourceSpan: ParseSourceSpan|null,\n nameSpan: ParseSourceSpan, public i18n?: I18nMeta) {\n super(nameSpan, sourceSpan, startSourceSpan, endSourceSpan);\n }\n\n visit(visitor: Visitor): Result {\n return visitor.visitSwitchBlockCase(this);\n }\n}\n\n// Note: this is a weird way to define the properties, but we do it so that we can\n// get strong typing when the context is passed through `Object.values`.\n/** Context variables that can be used inside a `ForLoopBlock`. */\nexport type ForLoopBlockContext =\n Record<'$index'|'$first'|'$last'|'$even'|'$odd'|'$count', Variable>;\n\nexport class ForLoopBlock extends BlockNode implements Node {\n constructor(\n public item: Variable, public expression: ASTWithSource, public trackBy: ASTWithSource,\n public trackKeywordSpan: ParseSourceSpan, public contextVariables: ForLoopBlockContext,\n public children: Node[], public empty: ForLoopBlockEmpty|null, sourceSpan: ParseSourceSpan,\n public mainBlockSpan: ParseSourceSpan, startSourceSpan: ParseSourceSpan,\n endSourceSpan: ParseSourceSpan|null, nameSpan: ParseSourceSpan, public i18n?: I18nMeta) {\n super(nameSpan, sourceSpan, startSourceSpan, endSourceSpan);\n }\n\n visit(visitor: Visitor): Result {\n return visitor.visitForLoopBlock(this);\n }\n}\n\nexport class ForLoopBlockEmpty extends BlockNode implements Node {\n constructor(\n public children: Node[], sourceSpan: ParseSourceSpan, startSourceSpan: ParseSourceSpan,\n endSourceSpan: ParseSourceSpan|null, nameSpan: ParseSourceSpan, public i18n?: I18nMeta) {\n super(nameSpan, sourceSpan, startSourceSpan, endSourceSpan);\n }\n\n visit(visitor: Visitor): Result {\n return visitor.visitForLoopBlockEmpty(this);\n }\n}\n\nexport class IfBlock extends BlockNode implements Node {\n constructor(\n public branches: IfBlockBranch[], sourceSpan: ParseSourceSpan,\n startSourceSpan: ParseSourceSpan, endSourceSpan: ParseSourceSpan|null,\n nameSpan: ParseSourceSpan) {\n super(nameSpan, sourceSpan, startSourceSpan, endSourceSpan);\n }\n\n visit(visitor: Visitor): Result {\n return visitor.visitIfBlock(this);\n }\n}\n\nexport class IfBlockBranch extends BlockNode implements Node {\n constructor(\n public expression: AST|null, public children: Node[], public expressionAlias: Variable|null,\n sourceSpan: ParseSourceSpan, startSourceSpan: ParseSourceSpan,\n endSourceSpan: ParseSourceSpan|null, nameSpan: ParseSourceSpan, public i18n?: I18nMeta) {\n super(nameSpan, sourceSpan, startSourceSpan, endSourceSpan);\n }\n\n visit(visitor: Visitor): Result {\n return visitor.visitIfBlockBranch(this);\n }\n}\n\nexport class UnknownBlock implements Node {\n constructor(\n public name: string, public sourceSpan: ParseSourceSpan, public nameSpan: ParseSourceSpan) {}\n\n visit(visitor: Visitor): Result {\n return visitor.visitUnknownBlock(this);\n }\n}\n\nexport class Template implements Node {\n constructor(\n // tagName is the name of the container element, if applicable.\n // `null` is a special case for when there is a structural directive on an `ng-template` so\n // the renderer can differentiate between the synthetic template and the one written in the\n // file.\n public tagName: string|null,\n public attributes: TextAttribute[],\n public inputs: BoundAttribute[],\n public outputs: BoundEvent[],\n public templateAttrs: (BoundAttribute|TextAttribute)[],\n public children: Node[],\n public references: Reference[],\n public variables: Variable[],\n public sourceSpan: ParseSourceSpan,\n public startSourceSpan: ParseSourceSpan,\n public endSourceSpan: ParseSourceSpan|null,\n public i18n?: I18nMeta,\n ) {}\n visit(visitor: Visitor): Result {\n return visitor.visitTemplate(this);\n }\n}\n\nexport class Content implements Node {\n readonly name = 'ng-content';\n\n constructor(\n public selector: string, public attributes: TextAttribute[],\n public sourceSpan: ParseSourceSpan, public i18n?: I18nMeta) {}\n visit(visitor: Visitor): Result {\n return visitor.visitContent(this);\n }\n}\n\nexport class Variable implements Node {\n constructor(\n public name: string, public value: string, public sourceSpan: ParseSourceSpan,\n readonly keySpan: ParseSourceSpan, public valueSpan?: ParseSourceSpan) {}\n visit(visitor: Visitor): Result {\n return visitor.visitVariable(this);\n }\n}\n\nexport class Reference implements Node {\n constructor(\n public name: string, public value: string, public sourceSpan: ParseSourceSpan,\n readonly keySpan: ParseSourceSpan, public valueSpan?: ParseSourceSpan) {}\n visit(visitor: Visitor): Result {\n return visitor.visitReference(this);\n }\n}\n\nexport class Icu implements Node {\n constructor(\n public vars: {[name: string]: BoundText},\n public placeholders: {[name: string]: Text|BoundText}, public sourceSpan: ParseSourceSpan,\n public i18n?: I18nMeta) {}\n visit(visitor: Visitor): Result {\n return visitor.visitIcu(this);\n }\n}\n\nexport interface Visitor {\n // Returning a truthy value from `visit()` will prevent `visitAll()` from the call to the typed\n // method and result returned will become the result included in `visitAll()`s result array.\n visit?(node: Node): Result;\n\n visitElement(element: Element): Result;\n visitTemplate(template: Template): Result;\n visitContent(content: Content): Result;\n visitVariable(variable: Variable): Result;\n visitReference(reference: Reference): Result;\n visitTextAttribute(attribute: TextAttribute): Result;\n visitBoundAttribute(attribute: BoundAttribute): Result;\n visitBoundEvent(attribute: BoundEvent): Result;\n visitText(text: Text): Result;\n visitBoundText(text: BoundText): Result;\n visitIcu(icu: Icu): Result;\n visitDeferredBlock(deferred: DeferredBlock): Result;\n visitDeferredBlockPlaceholder(block: DeferredBlockPlaceholder): Result;\n visitDeferredBlockError(block: DeferredBlockError): Result;\n visitDeferredBlockLoading(block: DeferredBlockLoading): Result;\n visitDeferredTrigger(trigger: DeferredTrigger): Result;\n visitSwitchBlock(block: SwitchBlock): Result;\n visitSwitchBlockCase(block: SwitchBlockCase): Result;\n visitForLoopBlock(block: ForLoopBlock): Result;\n visitForLoopBlockEmpty(block: ForLoopBlockEmpty): Result;\n visitIfBlock(block: IfBlock): Result;\n visitIfBlockBranch(block: IfBlockBranch): Result;\n visitUnknownBlock(block: UnknownBlock): Result;\n}\n\nexport class RecursiveVisitor implements Visitor {\n visitElement(element: Element): void {\n visitAll(this, element.attributes);\n visitAll(this, element.inputs);\n visitAll(this, element.outputs);\n visitAll(this, element.children);\n visitAll(this, element.references);\n }\n visitTemplate(template: Template): void {\n visitAll(this, template.attributes);\n visitAll(this, template.inputs);\n visitAll(this, template.outputs);\n visitAll(this, template.children);\n visitAll(this, template.references);\n visitAll(this, template.variables);\n }\n visitDeferredBlock(deferred: DeferredBlock): void {\n deferred.visitAll(this);\n }\n visitDeferredBlockPlaceholder(block: DeferredBlockPlaceholder): void {\n visitAll(this, block.children);\n }\n visitDeferredBlockError(block: DeferredBlockError): void {\n visitAll(this, block.children);\n }\n visitDeferredBlockLoading(block: DeferredBlockLoading): void {\n visitAll(this, block.children);\n }\n visitSwitchBlock(block: SwitchBlock): void {\n visitAll(this, block.cases);\n }\n visitSwitchBlockCase(block: SwitchBlockCase): void {\n visitAll(this, block.children);\n }\n visitForLoopBlock(block: ForLoopBlock): void {\n const blockItems = [block.item, ...Object.values(block.contextVariables), ...block.children];\n block.empty && blockItems.push(block.empty);\n visitAll(this, blockItems);\n }\n visitForLoopBlockEmpty(block: ForLoopBlockEmpty): void {\n visitAll(this, block.children);\n }\n visitIfBlock(block: IfBlock): void {\n visitAll(this, block.branches);\n }\n visitIfBlockBranch(block: IfBlockBranch): void {\n const blockItems = block.children;\n block.expressionAlias && blockItems.push(block.expressionAlias);\n visitAll(this, blockItems);\n }\n visitContent(content: Content): void {}\n visitVariable(variable: Variable): void {}\n visitReference(reference: Reference): void {}\n visitTextAttribute(attribute: TextAttribute): void {}\n visitBoundAttribute(attribute: BoundAttribute): void {}\n visitBoundEvent(attribute: BoundEvent): void {}\n visitText(text: Text): void {}\n visitBoundText(text: BoundText): void {}\n visitIcu(icu: Icu): void {}\n visitDeferredTrigger(trigger: DeferredTrigger): void {}\n visitUnknownBlock(block: UnknownBlock): void {}\n}\n\n\nexport function visitAll(visitor: Visitor, nodes: Node[]): Result[] {\n const result: Result[] = [];\n if (visitor.visit) {\n for (const node of nodes) {\n visitor.visit(node) || node.visit(visitor);\n }\n } else {\n for (const node of nodes) {\n const newNode = node.visit(visitor);\n if (newNode) {\n result.push(newNode);\n }\n }\n }\n return result;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ParseSourceSpan} from '../parse_util';\n\n/**\n * Describes the text contents of a placeholder as it appears in an ICU expression, including its\n * source span information.\n */\nexport interface MessagePlaceholder {\n /** The text contents of the placeholder */\n text: string;\n\n /** The source span of the placeholder */\n sourceSpan: ParseSourceSpan;\n}\n\nexport class Message {\n sources: MessageSpan[];\n id: string;\n /** The ids to use if there are no custom id and if `i18nLegacyMessageIdFormat` is not empty */\n legacyIds: string[] = [];\n\n messageString: string;\n\n /**\n * @param nodes message AST\n * @param placeholders maps placeholder names to static content and their source spans\n * @param placeholderToMessage maps placeholder names to messages (used for nested ICU messages)\n * @param meaning\n * @param description\n * @param customId\n */\n constructor(\n public nodes: Node[], public placeholders: {[phName: string]: MessagePlaceholder},\n public placeholderToMessage: {[phName: string]: Message}, public meaning: string,\n public description: string, public customId: string) {\n this.id = this.customId;\n this.messageString = serializeMessage(this.nodes);\n\n if (nodes.length) {\n this.sources = [{\n filePath: nodes[0].sourceSpan.start.file.url,\n startLine: nodes[0].sourceSpan.start.line + 1,\n startCol: nodes[0].sourceSpan.start.col + 1,\n endLine: nodes[nodes.length - 1].sourceSpan.end.line + 1,\n endCol: nodes[0].sourceSpan.start.col + 1\n }];\n } else {\n this.sources = [];\n }\n }\n}\n\n// line and columns indexes are 1 based\nexport interface MessageSpan {\n filePath: string;\n startLine: number;\n startCol: number;\n endLine: number;\n endCol: number;\n}\n\nexport interface Node {\n sourceSpan: ParseSourceSpan;\n visit(visitor: Visitor, context?: any): any;\n}\n\nexport class Text implements Node {\n constructor(public value: string, public sourceSpan: ParseSourceSpan) {}\n\n visit(visitor: Visitor, context?: any): any {\n return visitor.visitText(this, context);\n }\n}\n\n// TODO(vicb): do we really need this node (vs an array) ?\nexport class Container implements Node {\n constructor(public children: Node[], public sourceSpan: ParseSourceSpan) {}\n\n visit(visitor: Visitor, context?: any): any {\n return visitor.visitContainer(this, context);\n }\n}\n\nexport class Icu implements Node {\n constructor(\n public expression: string, public type: string, public cases: {[k: string]: Node},\n public sourceSpan: ParseSourceSpan, public expressionPlaceholder?: string) {}\n\n visit(visitor: Visitor, context?: any): any {\n return visitor.visitIcu(this, context);\n }\n}\n\nexport class TagPlaceholder implements Node {\n constructor(\n public tag: string, public attrs: {[k: string]: string}, public startName: string,\n public closeName: string, public children: Node[], public isVoid: boolean,\n // TODO sourceSpan should cover all (we need a startSourceSpan and endSourceSpan)\n public sourceSpan: ParseSourceSpan, public startSourceSpan: ParseSourceSpan|null,\n public endSourceSpan: ParseSourceSpan|null) {}\n\n visit(visitor: Visitor, context?: any): any {\n return visitor.visitTagPlaceholder(this, context);\n }\n}\n\nexport class Placeholder implements Node {\n constructor(public value: string, public name: string, public sourceSpan: ParseSourceSpan) {}\n\n visit(visitor: Visitor, context?: any): any {\n return visitor.visitPlaceholder(this, context);\n }\n}\n\nexport class IcuPlaceholder implements Node {\n /** Used to capture a message computed from a previous processing pass (see `setI18nRefs()`). */\n previousMessage?: Message;\n constructor(public value: Icu, public name: string, public sourceSpan: ParseSourceSpan) {}\n\n visit(visitor: Visitor, context?: any): any {\n return visitor.visitIcuPlaceholder(this, context);\n }\n}\n\nexport class BlockPlaceholder implements Node {\n constructor(\n public name: string, public parameters: string[], public startName: string,\n public closeName: string, public children: Node[], public sourceSpan: ParseSourceSpan,\n public startSourceSpan: ParseSourceSpan|null, public endSourceSpan: ParseSourceSpan|null) {}\n\n visit(visitor: Visitor, context?: any): any {\n return visitor.visitBlockPlaceholder(this, context);\n }\n}\n\n/**\n * Each HTML node that is affect by an i18n tag will also have an `i18n` property that is of type\n * `I18nMeta`.\n * This information is either a `Message`, which indicates it is the root of an i18n message, or a\n * `Node`, which indicates is it part of a containing `Message`.\n */\nexport type I18nMeta = Message|Node;\n\nexport interface Visitor {\n visitText(text: Text, context?: any): any;\n visitContainer(container: Container, context?: any): any;\n visitIcu(icu: Icu, context?: any): any;\n visitTagPlaceholder(ph: TagPlaceholder, context?: any): any;\n visitPlaceholder(ph: Placeholder, context?: any): any;\n visitIcuPlaceholder(ph: IcuPlaceholder, context?: any): any;\n visitBlockPlaceholder(ph: BlockPlaceholder, context?: any): any;\n}\n\n// Clone the AST\nexport class CloneVisitor implements Visitor {\n visitText(text: Text, context?: any): Text {\n return new Text(text.value, text.sourceSpan);\n }\n\n visitContainer(container: Container, context?: any): Container {\n const children = container.children.map(n => n.visit(this, context));\n return new Container(children, container.sourceSpan);\n }\n\n visitIcu(icu: Icu, context?: any): Icu {\n const cases: {[k: string]: Node} = {};\n Object.keys(icu.cases).forEach(key => cases[key] = icu.cases[key].visit(this, context));\n const msg = new Icu(icu.expression, icu.type, cases, icu.sourceSpan, icu.expressionPlaceholder);\n return msg;\n }\n\n visitTagPlaceholder(ph: TagPlaceholder, context?: any): TagPlaceholder {\n const children = ph.children.map(n => n.visit(this, context));\n return new TagPlaceholder(\n ph.tag, ph.attrs, ph.startName, ph.closeName, children, ph.isVoid, ph.sourceSpan,\n ph.startSourceSpan, ph.endSourceSpan);\n }\n\n visitPlaceholder(ph: Placeholder, context?: any): Placeholder {\n return new Placeholder(ph.value, ph.name, ph.sourceSpan);\n }\n\n visitIcuPlaceholder(ph: IcuPlaceholder, context?: any): IcuPlaceholder {\n return new IcuPlaceholder(ph.value, ph.name, ph.sourceSpan);\n }\n\n visitBlockPlaceholder(ph: BlockPlaceholder, context?: any): BlockPlaceholder {\n const children = ph.children.map(n => n.visit(this, context));\n return new BlockPlaceholder(\n ph.name, ph.parameters, ph.startName, ph.closeName, children, ph.sourceSpan,\n ph.startSourceSpan, ph.endSourceSpan);\n }\n}\n\n// Visit all the nodes recursively\nexport class RecurseVisitor implements Visitor {\n visitText(text: Text, context?: any): any {}\n\n visitContainer(container: Container, context?: any): any {\n container.children.forEach(child => child.visit(this));\n }\n\n visitIcu(icu: Icu, context?: any): any {\n Object.keys(icu.cases).forEach(k => {\n icu.cases[k].visit(this);\n });\n }\n\n visitTagPlaceholder(ph: TagPlaceholder, context?: any): any {\n ph.children.forEach(child => child.visit(this));\n }\n\n visitPlaceholder(ph: Placeholder, context?: any): any {}\n\n visitIcuPlaceholder(ph: IcuPlaceholder, context?: any): any {}\n\n visitBlockPlaceholder(ph: BlockPlaceholder, context?: any): any {\n ph.children.forEach(child => child.visit(this));\n }\n}\n\n\n/**\n * Serialize the message to the Localize backtick string format that would appear in compiled code.\n */\nfunction serializeMessage(messageNodes: Node[]): string {\n const visitor = new LocalizeMessageStringVisitor();\n const str = messageNodes.map(n => n.visit(visitor)).join('');\n return str;\n}\n\nclass LocalizeMessageStringVisitor implements Visitor {\n visitText(text: Text): any {\n return text.value;\n }\n\n visitContainer(container: Container): any {\n return container.children.map(child => child.visit(this)).join('');\n }\n\n visitIcu(icu: Icu): any {\n const strCases =\n Object.keys(icu.cases).map((k: string) => `${k} {${icu.cases[k].visit(this)}}`);\n return `{${icu.expressionPlaceholder}, ${icu.type}, ${strCases.join(' ')}}`;\n }\n\n visitTagPlaceholder(ph: TagPlaceholder): any {\n const children = ph.children.map(child => child.visit(this)).join('');\n return `{$${ph.startName}}${children}{$${ph.closeName}}`;\n }\n\n visitPlaceholder(ph: Placeholder): any {\n return `{$${ph.name}}`;\n }\n\n visitIcuPlaceholder(ph: IcuPlaceholder): any {\n return `{$${ph.name}}`;\n }\n\n visitBlockPlaceholder(ph: BlockPlaceholder): any {\n const children = ph.children.map(child => child.visit(this)).join('');\n return `{$${ph.startName}}${children}{$${ph.closeName}}`;\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport * as i18n from '../i18n_ast';\n\nexport abstract class Serializer {\n // - The `placeholders` and `placeholderToMessage` properties are irrelevant in the input messages\n // - The `id` contains the message id that the serializer is expected to use\n // - Placeholder names are already map to public names using the provided mapper\n abstract write(messages: i18n.Message[], locale: string|null): string;\n\n abstract load(content: string, url: string):\n {locale: string|null, i18nNodesByMsgId: {[msgId: string]: i18n.Node[]}};\n\n abstract digest(message: i18n.Message): string;\n\n // Creates a name mapper, see `PlaceholderMapper`\n // Returning `null` means that no name mapping is used.\n createNameMapper(message: i18n.Message): PlaceholderMapper|null {\n return null;\n }\n}\n\n/**\n * A `PlaceholderMapper` converts placeholder names from internal to serialized representation and\n * back.\n *\n * It should be used for serialization format that put constraints on the placeholder names.\n */\nexport interface PlaceholderMapper {\n toPublicName(internalName: string): string|null;\n\n toInternalName(publicName: string): string|null;\n}\n\n/**\n * A simple mapper that take a function to transform an internal name to a public name\n */\nexport class SimplePlaceholderMapper extends i18n.RecurseVisitor implements PlaceholderMapper {\n private internalToPublic: {[k: string]: string} = {};\n private publicToNextId: {[k: string]: number} = {};\n private publicToInternal: {[k: string]: string} = {};\n\n // create a mapping from the message\n constructor(message: i18n.Message, private mapName: (name: string) => string) {\n super();\n message.nodes.forEach(node => node.visit(this));\n }\n\n toPublicName(internalName: string): string|null {\n return this.internalToPublic.hasOwnProperty(internalName) ?\n this.internalToPublic[internalName] :\n null;\n }\n\n toInternalName(publicName: string): string|null {\n return this.publicToInternal.hasOwnProperty(publicName) ? this.publicToInternal[publicName] :\n null;\n }\n\n override visitText(text: i18n.Text, context?: any): any {\n return null;\n }\n\n override visitTagPlaceholder(ph: i18n.TagPlaceholder, context?: any): any {\n this.visitPlaceholderName(ph.startName);\n super.visitTagPlaceholder(ph, context);\n this.visitPlaceholderName(ph.closeName);\n }\n\n override visitPlaceholder(ph: i18n.Placeholder, context?: any): any {\n this.visitPlaceholderName(ph.name);\n }\n\n override visitBlockPlaceholder(ph: i18n.BlockPlaceholder, context?: any): any {\n this.visitPlaceholderName(ph.startName);\n super.visitBlockPlaceholder(ph, context);\n this.visitPlaceholderName(ph.closeName);\n }\n\n override visitIcuPlaceholder(ph: i18n.IcuPlaceholder, context?: any): any {\n this.visitPlaceholderName(ph.name);\n }\n\n // XMB placeholders could only contains A-Z, 0-9 and _\n private visitPlaceholderName(internalName: string): void {\n if (!internalName || this.internalToPublic.hasOwnProperty(internalName)) {\n return;\n }\n\n let publicName = this.mapName(internalName);\n\n if (this.publicToInternal.hasOwnProperty(publicName)) {\n // Create a new XMB when it has already been used\n const nextId = this.publicToNextId[publicName];\n this.publicToNextId[publicName] = nextId + 1;\n publicName = `${publicName}_${nextId}`;\n } else {\n this.publicToNextId[publicName] = 1;\n }\n\n this.internalToPublic[internalName] = publicName;\n this.publicToInternal[publicName] = internalName;\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nexport interface IVisitor {\n visitTag(tag: Tag): any;\n visitText(text: Text): any;\n visitDeclaration(decl: Declaration): any;\n visitDoctype(doctype: Doctype): any;\n}\n\nclass _Visitor implements IVisitor {\n visitTag(tag: Tag): string {\n const strAttrs = this._serializeAttributes(tag.attrs);\n\n if (tag.children.length == 0) {\n return `<${tag.name}${strAttrs}/>`;\n }\n\n const strChildren = tag.children.map(node => node.visit(this));\n return `<${tag.name}${strAttrs}>${strChildren.join('')}`;\n }\n\n visitText(text: Text): string {\n return text.value;\n }\n\n visitDeclaration(decl: Declaration): string {\n return ``;\n }\n\n private _serializeAttributes(attrs: {[k: string]: string}) {\n const strAttrs = Object.keys(attrs).map((name: string) => `${name}=\"${attrs[name]}\"`).join(' ');\n return strAttrs.length > 0 ? ' ' + strAttrs : '';\n }\n\n visitDoctype(doctype: Doctype): any {\n return ``;\n }\n}\n\nconst _visitor = new _Visitor();\n\nexport function serialize(nodes: Node[]): string {\n return nodes.map((node: Node): string => node.visit(_visitor)).join('');\n}\n\nexport interface Node {\n visit(visitor: IVisitor): any;\n}\n\nexport class Declaration implements Node {\n public attrs: {[k: string]: string} = {};\n\n constructor(unescapedAttrs: {[k: string]: string}) {\n Object.keys(unescapedAttrs).forEach((k: string) => {\n this.attrs[k] = escapeXml(unescapedAttrs[k]);\n });\n }\n\n visit(visitor: IVisitor): any {\n return visitor.visitDeclaration(this);\n }\n}\n\nexport class Doctype implements Node {\n constructor(public rootTag: string, public dtd: string) {}\n\n visit(visitor: IVisitor): any {\n return visitor.visitDoctype(this);\n }\n}\n\nexport class Tag implements Node {\n public attrs: {[k: string]: string} = {};\n\n constructor(\n public name: string, unescapedAttrs: {[k: string]: string} = {},\n public children: Node[] = []) {\n Object.keys(unescapedAttrs).forEach((k: string) => {\n this.attrs[k] = escapeXml(unescapedAttrs[k]);\n });\n }\n\n visit(visitor: IVisitor): any {\n return visitor.visitTag(this);\n }\n}\n\nexport class Text implements Node {\n value: string;\n constructor(unescapedValue: string) {\n this.value = escapeXml(unescapedValue);\n }\n\n visit(visitor: IVisitor): any {\n return visitor.visitText(this);\n }\n}\n\nexport class CR extends Text {\n constructor(ws: number = 0) {\n super(`\\n${new Array(ws + 1).join(' ')}`);\n }\n}\n\nconst _ESCAPED_CHARS: [RegExp, string][] = [\n [/&/g, '&'],\n [/\"/g, '"'],\n [/'/g, '''],\n [//g, '>'],\n];\n\n// Escape `_ESCAPED_CHARS` characters in the given text with encoded entities\nexport function escapeXml(text: string): string {\n return _ESCAPED_CHARS.reduce(\n (text: string, entry: [RegExp, string]) => text.replace(entry[0], entry[1]), text);\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {decimalDigest} from '../digest';\nimport * as i18n from '../i18n_ast';\n\nimport {PlaceholderMapper, Serializer, SimplePlaceholderMapper} from './serializer';\nimport * as xml from './xml_helper';\n\nconst _MESSAGES_TAG = 'messagebundle';\nconst _MESSAGE_TAG = 'msg';\nconst _PLACEHOLDER_TAG = 'ph';\nconst _EXAMPLE_TAG = 'ex';\nconst _SOURCE_TAG = 'source';\n\nconst _DOCTYPE = `\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n`;\n\nexport class Xmb extends Serializer {\n override write(messages: i18n.Message[], locale: string|null): string {\n const exampleVisitor = new ExampleVisitor();\n const visitor = new _Visitor();\n let rootNode = new xml.Tag(_MESSAGES_TAG);\n\n messages.forEach(message => {\n const attrs: {[k: string]: string} = {id: message.id};\n\n if (message.description) {\n attrs['desc'] = message.description;\n }\n\n if (message.meaning) {\n attrs['meaning'] = message.meaning;\n }\n\n let sourceTags: xml.Tag[] = [];\n message.sources.forEach((source: i18n.MessageSpan) => {\n sourceTags.push(new xml.Tag(\n _SOURCE_TAG, {},\n [new xml.Text(`${source.filePath}:${source.startLine}${\n source.endLine !== source.startLine ? ',' + source.endLine : ''}`)]));\n });\n\n rootNode.children.push(\n new xml.CR(2),\n new xml.Tag(_MESSAGE_TAG, attrs, [...sourceTags, ...visitor.serialize(message.nodes)]));\n });\n\n rootNode.children.push(new xml.CR());\n\n return xml.serialize([\n new xml.Declaration({version: '1.0', encoding: 'UTF-8'}),\n new xml.CR(),\n new xml.Doctype(_MESSAGES_TAG, _DOCTYPE),\n new xml.CR(),\n exampleVisitor.addDefaultExamples(rootNode),\n new xml.CR(),\n ]);\n }\n\n override load(content: string, url: string):\n {locale: string, i18nNodesByMsgId: {[msgId: string]: i18n.Node[]}} {\n throw new Error('Unsupported');\n }\n\n override digest(message: i18n.Message): string {\n return digest(message);\n }\n\n\n override createNameMapper(message: i18n.Message): PlaceholderMapper {\n return new SimplePlaceholderMapper(message, toPublicName);\n }\n}\n\nclass _Visitor implements i18n.Visitor {\n visitText(text: i18n.Text, context?: any): xml.Node[] {\n return [new xml.Text(text.value)];\n }\n\n visitContainer(container: i18n.Container, context: any): xml.Node[] {\n const nodes: xml.Node[] = [];\n container.children.forEach((node: i18n.Node) => nodes.push(...node.visit(this)));\n return nodes;\n }\n\n visitIcu(icu: i18n.Icu, context?: any): xml.Node[] {\n const nodes = [new xml.Text(`{${icu.expressionPlaceholder}, ${icu.type}, `)];\n\n Object.keys(icu.cases).forEach((c: string) => {\n nodes.push(new xml.Text(`${c} {`), ...icu.cases[c].visit(this), new xml.Text(`} `));\n });\n\n nodes.push(new xml.Text(`}`));\n\n return nodes;\n }\n\n visitTagPlaceholder(ph: i18n.TagPlaceholder, context?: any): xml.Node[] {\n const startTagAsText = new xml.Text(`<${ph.tag}>`);\n const startEx = new xml.Tag(_EXAMPLE_TAG, {}, [startTagAsText]);\n // TC requires PH to have a non empty EX, and uses the text node to show the \"original\" value.\n const startTagPh =\n new xml.Tag(_PLACEHOLDER_TAG, {name: ph.startName}, [startEx, startTagAsText]);\n if (ph.isVoid) {\n // void tags have no children nor closing tags\n return [startTagPh];\n }\n\n const closeTagAsText = new xml.Text(``);\n const closeEx = new xml.Tag(_EXAMPLE_TAG, {}, [closeTagAsText]);\n // TC requires PH to have a non empty EX, and uses the text node to show the \"original\" value.\n const closeTagPh =\n new xml.Tag(_PLACEHOLDER_TAG, {name: ph.closeName}, [closeEx, closeTagAsText]);\n\n return [startTagPh, ...this.serialize(ph.children), closeTagPh];\n }\n\n visitPlaceholder(ph: i18n.Placeholder, context?: any): xml.Node[] {\n const interpolationAsText = new xml.Text(`{{${ph.value}}}`);\n // Example tag needs to be not-empty for TC.\n const exTag = new xml.Tag(_EXAMPLE_TAG, {}, [interpolationAsText]);\n return [\n // TC requires PH to have a non empty EX, and uses the text node to show the \"original\" value.\n new xml.Tag(_PLACEHOLDER_TAG, {name: ph.name}, [exTag, interpolationAsText])\n ];\n }\n\n visitBlockPlaceholder(ph: i18n.BlockPlaceholder, context?: any): xml.Node[] {\n const startAsText = new xml.Text(`@${ph.name}`);\n const startEx = new xml.Tag(_EXAMPLE_TAG, {}, [startAsText]);\n // TC requires PH to have a non empty EX, and uses the text node to show the \"original\" value.\n const startTagPh = new xml.Tag(_PLACEHOLDER_TAG, {name: ph.startName}, [startEx, startAsText]);\n\n const closeAsText = new xml.Text(`}`);\n const closeEx = new xml.Tag(_EXAMPLE_TAG, {}, [closeAsText]);\n // TC requires PH to have a non empty EX, and uses the text node to show the \"original\" value.\n const closeTagPh = new xml.Tag(_PLACEHOLDER_TAG, {name: ph.closeName}, [closeEx, closeAsText]);\n\n return [startTagPh, ...this.serialize(ph.children), closeTagPh];\n }\n\n visitIcuPlaceholder(ph: i18n.IcuPlaceholder, context?: any): xml.Node[] {\n const icuExpression = ph.value.expression;\n const icuType = ph.value.type;\n const icuCases = Object.keys(ph.value.cases).map((value: string) => value + ' {...}').join(' ');\n const icuAsText = new xml.Text(`{${icuExpression}, ${icuType}, ${icuCases}}`);\n const exTag = new xml.Tag(_EXAMPLE_TAG, {}, [icuAsText]);\n return [\n // TC requires PH to have a non empty EX, and uses the text node to show the \"original\" value.\n new xml.Tag(_PLACEHOLDER_TAG, {name: ph.name}, [exTag, icuAsText])\n ];\n }\n\n serialize(nodes: i18n.Node[]): xml.Node[] {\n return [].concat(...nodes.map(node => node.visit(this)));\n }\n}\n\nexport function digest(message: i18n.Message): string {\n return decimalDigest(message);\n}\n\n// TC requires at least one non-empty example on placeholders\nclass ExampleVisitor implements xml.IVisitor {\n addDefaultExamples(node: xml.Node): xml.Node {\n node.visit(this);\n return node;\n }\n\n visitTag(tag: xml.Tag): void {\n if (tag.name === _PLACEHOLDER_TAG) {\n if (!tag.children || tag.children.length == 0) {\n const exText = new xml.Text(tag.attrs['name'] || '...');\n tag.children = [new xml.Tag(_EXAMPLE_TAG, {}, [exText])];\n }\n } else if (tag.children) {\n tag.children.forEach(node => node.visit(this));\n }\n }\n\n visitText(text: xml.Text): void {}\n visitDeclaration(decl: xml.Declaration): void {}\n visitDoctype(doctype: xml.Doctype): void {}\n}\n\n// XMB/XTB placeholders can only contain A-Z, 0-9 and _\nexport function toPublicName(internalName: string): string {\n return internalName.toUpperCase().replace(/[^A-Z0-9_]/g, '_');\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport * as i18n from '../../../i18n/i18n_ast';\nimport {toPublicName} from '../../../i18n/serializers/xmb';\nimport * as html from '../../../ml_parser/ast';\nimport * as o from '../../../output/output_ast';\nimport * as t from '../../r3_ast';\n\n/* Closure variables holding messages must be named `MSG_[A-Z0-9]+` */\nconst CLOSURE_TRANSLATION_VAR_PREFIX = 'MSG_';\n\n/**\n * Prefix for non-`goog.getMsg` i18n-related vars.\n * Note: the prefix uses lowercase characters intentionally due to a Closure behavior that\n * considers variables like `I18N_0` as constants and throws an error when their value changes.\n */\nexport const TRANSLATION_VAR_PREFIX = 'i18n_';\n\n/** Name of the i18n attributes **/\nexport const I18N_ATTR = 'i18n';\nexport const I18N_ATTR_PREFIX = 'i18n-';\n\n/** Prefix of var expressions used in ICUs */\nexport const I18N_ICU_VAR_PREFIX = 'VAR_';\n\n/** Prefix of ICU expressions for post processing */\nexport const I18N_ICU_MAPPING_PREFIX = 'I18N_EXP_';\n\n/** Placeholder wrapper for i18n expressions **/\nexport const I18N_PLACEHOLDER_SYMBOL = '�';\n\nexport function isI18nAttribute(name: string): boolean {\n return name === I18N_ATTR || name.startsWith(I18N_ATTR_PREFIX);\n}\n\nexport function isI18nRootNode(meta?: i18n.I18nMeta): meta is i18n.Message {\n return meta instanceof i18n.Message;\n}\n\nexport function isSingleI18nIcu(meta?: i18n.I18nMeta): meta is i18n.I18nMeta&{nodes: [i18n.Icu]} {\n return isI18nRootNode(meta) && meta.nodes.length === 1 && meta.nodes[0] instanceof i18n.Icu;\n}\n\nexport function hasI18nMeta(node: t.Node&{i18n?: i18n.I18nMeta}): boolean {\n return !!node.i18n;\n}\n\nexport function hasI18nAttrs(element: html.Element): boolean {\n return element.attrs.some((attr: html.Attribute) => isI18nAttribute(attr.name));\n}\n\nexport function icuFromI18nMessage(message: i18n.Message) {\n return message.nodes[0] as i18n.IcuPlaceholder;\n}\n\nexport function wrapI18nPlaceholder(content: string|number, contextId: number = 0): string {\n const blockId = contextId > 0 ? `:${contextId}` : '';\n return `${I18N_PLACEHOLDER_SYMBOL}${content}${blockId}${I18N_PLACEHOLDER_SYMBOL}`;\n}\n\nexport function assembleI18nBoundString(\n strings: string[], bindingStartIndex: number = 0, contextId: number = 0): string {\n if (!strings.length) return '';\n let acc = '';\n const lastIdx = strings.length - 1;\n for (let i = 0; i < lastIdx; i++) {\n acc += `${strings[i]}${wrapI18nPlaceholder(bindingStartIndex + i, contextId)}`;\n }\n acc += strings[lastIdx];\n return acc;\n}\n\nexport function getSeqNumberGenerator(startsAt: number = 0): () => number {\n let current = startsAt;\n return () => current++;\n}\n\nexport function placeholdersToParams(placeholders: Map):\n {[name: string]: o.LiteralExpr} {\n const params: {[name: string]: o.LiteralExpr} = {};\n placeholders.forEach((values: string[], key: string) => {\n params[key] = o.literal(values.length > 1 ? `[${values.join('|')}]` : values[0]);\n });\n return params;\n}\n\nexport function updatePlaceholderMap(map: Map, name: string, ...values: any[]) {\n const current = map.get(name) || [];\n current.push(...values);\n map.set(name, current);\n}\n\nexport function assembleBoundTextPlaceholders(\n meta: i18n.I18nMeta, bindingStartIndex: number = 0, contextId: number = 0): Map {\n const startIdx = bindingStartIndex;\n const placeholders = new Map();\n const node =\n meta instanceof i18n.Message ? meta.nodes.find(node => node instanceof i18n.Container) : meta;\n if (node) {\n (node as i18n.Container)\n .children\n .filter((child: i18n.Node): child is i18n.Placeholder => child instanceof i18n.Placeholder)\n .forEach((child: i18n.Placeholder, idx: number) => {\n const content = wrapI18nPlaceholder(startIdx + idx, contextId);\n updatePlaceholderMap(placeholders, child.name, content);\n });\n }\n return placeholders;\n}\n\n/**\n * Format the placeholder names in a map of placeholders to expressions.\n *\n * The placeholder names are converted from \"internal\" format (e.g. `START_TAG_DIV_1`) to \"external\"\n * format (e.g. `startTagDiv_1`).\n *\n * @param params A map of placeholder names to expressions.\n * @param useCamelCase whether to camelCase the placeholder name when formatting.\n * @returns A new map of formatted placeholder names to expressions.\n */\nexport function formatI18nPlaceholderNamesInMap(\n params: {[name: string]: o.Expression} = {}, useCamelCase: boolean) {\n const _params: {[key: string]: o.Expression} = {};\n if (params && Object.keys(params).length) {\n Object.keys(params).forEach(\n key => _params[formatI18nPlaceholderName(key, useCamelCase)] = params[key]);\n }\n return _params;\n}\n\n/**\n * Converts internal placeholder names to public-facing format\n * (for example to use in goog.getMsg call).\n * Example: `START_TAG_DIV_1` is converted to `startTagDiv_1`.\n *\n * @param name The placeholder name that should be formatted\n * @returns Formatted placeholder name\n */\nexport function formatI18nPlaceholderName(name: string, useCamelCase: boolean = true): string {\n const publicName = toPublicName(name);\n if (!useCamelCase) {\n return publicName;\n }\n const chunks = publicName.split('_');\n if (chunks.length === 1) {\n // if no \"_\" found - just lowercase the value\n return name.toLowerCase();\n }\n let postfix;\n // eject last element if it's a number\n if (/^\\d+$/.test(chunks[chunks.length - 1])) {\n postfix = chunks.pop();\n }\n let raw = chunks.shift()!.toLowerCase();\n if (chunks.length) {\n raw += chunks.map(c => c.charAt(0).toUpperCase() + c.slice(1).toLowerCase()).join('');\n }\n return postfix ? `${raw}_${postfix}` : raw;\n}\n\n/**\n * Generates a prefix for translation const name.\n *\n * @param extra Additional local prefix that should be injected into translation var name\n * @returns Complete translation const prefix\n */\nexport function getTranslationConstPrefix(extra: string): string {\n return `${CLOSURE_TRANSLATION_VAR_PREFIX}${extra}`.toUpperCase();\n}\n\n/**\n * Generate AST to declare a variable. E.g. `var I18N_1;`.\n * @param variable the name of the variable to declare.\n */\nexport function declareI18nVariable(variable: o.ReadVarExpr): o.Statement {\n return new o.DeclareVarStmt(\n variable.name!, undefined, o.INFERRED_TYPE, undefined, variable.sourceSpan);\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ConstantPool} from '../../constant_pool';\nimport {InputFlags} from '../../core';\nimport {BindingType, Interpolation} from '../../expression_parser/ast';\nimport {splitNsName} from '../../ml_parser/tags';\nimport * as o from '../../output/output_ast';\nimport {ParseSourceSpan} from '../../parse_util';\nimport {CssSelector} from '../../selector';\nimport * as t from '../r3_ast';\nimport {Identifiers as R3} from '../r3_identifiers';\nimport {ForwardRefHandling} from '../util';\n\nimport {R3QueryMetadata} from './api';\nimport {isI18nAttribute} from './i18n/util';\n\n\n/**\n * Checks whether an object key contains potentially unsafe chars, thus the key should be wrapped in\n * quotes. Note: we do not wrap all keys into quotes, as it may have impact on minification and may\n * not work in some cases when object keys are mangled by a minifier.\n *\n * TODO(FW-1136): this is a temporary solution, we need to come up with a better way of working with\n * inputs that contain potentially unsafe chars.\n */\nexport const UNSAFE_OBJECT_KEY_NAME_REGEXP = /[-.]/;\n\n/** Name of the temporary to use during data binding */\nexport const TEMPORARY_NAME = '_t';\n\n/** Name of the context parameter passed into a template function */\nexport const CONTEXT_NAME = 'ctx';\n\n/** Name of the RenderFlag passed into a template function */\nexport const RENDER_FLAGS = 'rf';\n\n/** The prefix reference variables */\nexport const REFERENCE_PREFIX = '_r';\n\n/** The name of the implicit context reference */\nexport const IMPLICIT_REFERENCE = '$implicit';\n\n/** Non bindable attribute name **/\nexport const NON_BINDABLE_ATTR = 'ngNonBindable';\n\n/** Name for the variable keeping track of the context returned by `ɵɵrestoreView`. */\nexport const RESTORED_VIEW_CONTEXT_NAME = 'restoredCtx';\n\n/** Special value representing a direct access to a template's context. */\nexport const DIRECT_CONTEXT_REFERENCE = '#context';\n\n/**\n * Maximum length of a single instruction chain. Because our output AST uses recursion, we're\n * limited in how many expressions we can nest before we reach the call stack limit. This\n * length is set very conservatively in order to reduce the chance of problems.\n */\nconst MAX_CHAIN_LENGTH = 500;\n\n/** Instructions that support chaining. */\nconst CHAINABLE_INSTRUCTIONS = new Set([\n R3.element,\n R3.elementStart,\n R3.elementEnd,\n R3.elementContainer,\n R3.elementContainerStart,\n R3.elementContainerEnd,\n R3.i18nExp,\n R3.listener,\n R3.classProp,\n R3.syntheticHostListener,\n R3.hostProperty,\n R3.syntheticHostProperty,\n R3.property,\n R3.propertyInterpolate1,\n R3.propertyInterpolate2,\n R3.propertyInterpolate3,\n R3.propertyInterpolate4,\n R3.propertyInterpolate5,\n R3.propertyInterpolate6,\n R3.propertyInterpolate7,\n R3.propertyInterpolate8,\n R3.propertyInterpolateV,\n R3.attribute,\n R3.attributeInterpolate1,\n R3.attributeInterpolate2,\n R3.attributeInterpolate3,\n R3.attributeInterpolate4,\n R3.attributeInterpolate5,\n R3.attributeInterpolate6,\n R3.attributeInterpolate7,\n R3.attributeInterpolate8,\n R3.attributeInterpolateV,\n R3.styleProp,\n R3.stylePropInterpolate1,\n R3.stylePropInterpolate2,\n R3.stylePropInterpolate3,\n R3.stylePropInterpolate4,\n R3.stylePropInterpolate5,\n R3.stylePropInterpolate6,\n R3.stylePropInterpolate7,\n R3.stylePropInterpolate8,\n R3.stylePropInterpolateV,\n R3.textInterpolate,\n R3.textInterpolate1,\n R3.textInterpolate2,\n R3.textInterpolate3,\n R3.textInterpolate4,\n R3.textInterpolate5,\n R3.textInterpolate6,\n R3.textInterpolate7,\n R3.textInterpolate8,\n R3.textInterpolateV,\n R3.templateCreate,\n]);\n\n/**\n * Possible types that can be used to generate the parameters of an instruction call.\n * If the parameters are a function, the function will be invoked at the time the instruction\n * is generated.\n */\nexport type InstructionParams = (o.Expression|o.Expression[])|(() => (o.Expression|o.Expression[]));\n\n/** Necessary information to generate a call to an instruction function. */\nexport interface Instruction {\n span: ParseSourceSpan|null;\n reference: o.ExternalReference;\n paramsOrFn?: InstructionParams;\n}\n\n/** Generates a call to a single instruction. */\nexport function invokeInstruction(\n span: ParseSourceSpan|null, reference: o.ExternalReference,\n params: o.Expression[]): o.Expression {\n return o.importExpr(reference, null, span).callFn(params, span);\n}\n\n/**\n * Creates an allocator for a temporary variable.\n *\n * A variable declaration is added to the statements the first time the allocator is invoked.\n */\nexport function temporaryAllocator(statements: o.Statement[], name: string): () => o.ReadVarExpr {\n let temp: o.ReadVarExpr|null = null;\n return () => {\n if (!temp) {\n statements.push(new o.DeclareVarStmt(TEMPORARY_NAME, undefined, o.DYNAMIC_TYPE));\n temp = o.variable(name);\n }\n return temp;\n };\n}\n\n\nexport function invalid(this: t.Visitor, arg: o.Expression|o.Statement|t.Node): never {\n throw new Error(\n `Invalid state: Visitor ${this.constructor.name} doesn't handle ${arg.constructor.name}`);\n}\n\nexport function asLiteral(value: any): o.Expression {\n if (Array.isArray(value)) {\n return o.literalArr(value.map(asLiteral));\n }\n return o.literal(value, o.INFERRED_TYPE);\n}\n\n/**\n * Serializes inputs and outputs for `defineDirective` and `defineComponent`.\n *\n * This will attempt to generate optimized data structures to minimize memory or\n * file size of fully compiled applications.\n */\nexport function conditionallyCreateDirectiveBindingLiteral(\n map: Record, forInputs?: boolean): o.Expression|null {\n const keys = Object.getOwnPropertyNames(map);\n\n if (keys.length === 0) {\n return null;\n }\n\n return o.literalMap(keys.map(key => {\n const value = map[key];\n let declaredName: string;\n let publicName: string;\n let minifiedName: string;\n let expressionValue: o.Expression;\n\n if (typeof value === 'string') {\n // canonical syntax: `dirProp: publicProp`\n declaredName = key;\n minifiedName = key;\n publicName = value;\n expressionValue = asLiteral(publicName);\n } else {\n minifiedName = key;\n declaredName = value.classPropertyName;\n publicName = value.bindingPropertyName;\n\n const differentDeclaringName = publicName !== declaredName;\n const hasDecoratorInputTransform = value.transformFunction !== null;\n\n // Build up input flags\n let flags: o.Expression|null = null;\n if (value.isSignal) {\n flags = bitwiseOrInputFlagsExpr(InputFlags.SignalBased, flags);\n }\n if (hasDecoratorInputTransform) {\n flags = bitwiseOrInputFlagsExpr(InputFlags.HasDecoratorInputTransform, flags);\n }\n\n // Inputs, compared to outputs, will track their declared name (for `ngOnChanges`), support\n // decorator input transform functions, or store flag information if there is any.\n if (forInputs && (differentDeclaringName || hasDecoratorInputTransform || flags !== null)) {\n const flagsExpr = flags ?? o.importExpr(R3.InputFlags).prop(InputFlags[InputFlags.None]);\n const result: o.Expression[] = [flagsExpr, asLiteral(publicName)];\n\n if (differentDeclaringName || hasDecoratorInputTransform) {\n result.push(asLiteral(declaredName));\n\n if (hasDecoratorInputTransform) {\n result.push(value.transformFunction!);\n }\n }\n\n expressionValue = o.literalArr(result);\n } else {\n expressionValue = asLiteral(publicName);\n }\n }\n\n return {\n key: minifiedName,\n // put quotes around keys that contain potentially unsafe characters\n quoted: UNSAFE_OBJECT_KEY_NAME_REGEXP.test(minifiedName),\n value: expressionValue,\n };\n }));\n}\n\n/** Gets an output AST expression referencing the given flag. */\nfunction getInputFlagExpr(flag: InputFlags): o.Expression {\n return o.importExpr(R3.InputFlags).prop(InputFlags[flag]);\n}\n\n/** Combines a given input flag with an existing flag expression, if present. */\nfunction bitwiseOrInputFlagsExpr(flag: InputFlags, expr: o.Expression|null): o.Expression {\n if (expr === null) {\n return getInputFlagExpr(flag);\n }\n return getInputFlagExpr(flag).bitwiseOr(expr);\n}\n\n/**\n * Remove trailing null nodes as they are implied.\n */\nexport function trimTrailingNulls(parameters: o.Expression[]): o.Expression[] {\n while (o.isNull(parameters[parameters.length - 1])) {\n parameters.pop();\n }\n return parameters;\n}\n\nexport function getQueryPredicate(\n query: R3QueryMetadata, constantPool: ConstantPool): o.Expression {\n if (Array.isArray(query.predicate)) {\n let predicate: o.Expression[] = [];\n query.predicate.forEach((selector: string): void => {\n // Each item in predicates array may contain strings with comma-separated refs\n // (for ex. 'ref, ref1, ..., refN'), thus we extract individual refs and store them\n // as separate array entities\n const selectors = selector.split(',').map(token => o.literal(token.trim()));\n predicate.push(...selectors);\n });\n return constantPool.getConstLiteral(o.literalArr(predicate), true);\n } else {\n // The original predicate may have been wrapped in a `forwardRef()` call.\n switch (query.predicate.forwardRef) {\n case ForwardRefHandling.None:\n case ForwardRefHandling.Unwrapped:\n return query.predicate.expression;\n case ForwardRefHandling.Wrapped:\n return o.importExpr(R3.resolveForwardRef).callFn([query.predicate.expression]);\n }\n }\n}\n\n/**\n * A representation for an object literal used during codegen of definition objects. The generic\n * type `T` allows to reference a documented type of the generated structure, such that the\n * property names that are set can be resolved to their documented declaration.\n */\nexport class DefinitionMap {\n values: {key: string, quoted: boolean, value: o.Expression}[] = [];\n\n set(key: keyof T, value: o.Expression|null): void {\n if (value) {\n const existing = this.values.find(value => value.key === key);\n\n if (existing) {\n existing.value = value;\n } else {\n this.values.push({key: key as string, value, quoted: false});\n }\n }\n }\n\n toLiteralMap(): o.LiteralMapExpr {\n return o.literalMap(this.values);\n }\n}\n\n/**\n * Creates a `CssSelector` from an AST node.\n */\nexport function createCssSelectorFromNode(node: t.Element|t.Template): CssSelector {\n const elementName = node instanceof t.Element ? node.name : 'ng-template';\n const attributes = getAttrsForDirectiveMatching(node);\n const cssSelector = new CssSelector();\n const elementNameNoNs = splitNsName(elementName)[1];\n\n cssSelector.setElement(elementNameNoNs);\n\n Object.getOwnPropertyNames(attributes).forEach((name) => {\n const nameNoNs = splitNsName(name)[1];\n const value = attributes[name];\n\n cssSelector.addAttribute(nameNoNs, value);\n if (name.toLowerCase() === 'class') {\n const classes = value.trim().split(/\\s+/);\n classes.forEach(className => cssSelector.addClassName(className));\n }\n });\n\n return cssSelector;\n}\n\n/**\n * Extract a map of properties to values for a given element or template node, which can be used\n * by the directive matching machinery.\n *\n * @param elOrTpl the element or template in question\n * @return an object set up for directive matching. For attributes on the element/template, this\n * object maps a property name to its (static) value. For any bindings, this map simply maps the\n * property name to an empty string.\n */\nfunction getAttrsForDirectiveMatching(elOrTpl: t.Element|t.Template): {[name: string]: string} {\n const attributesMap: {[name: string]: string} = {};\n\n\n if (elOrTpl instanceof t.Template && elOrTpl.tagName !== 'ng-template') {\n elOrTpl.templateAttrs.forEach(a => attributesMap[a.name] = '');\n } else {\n elOrTpl.attributes.forEach(a => {\n if (!isI18nAttribute(a.name)) {\n attributesMap[a.name] = a.value;\n }\n });\n\n elOrTpl.inputs.forEach(i => {\n if (i.type === BindingType.Property || i.type === BindingType.TwoWay) {\n attributesMap[i.name] = '';\n }\n });\n elOrTpl.outputs.forEach(o => {\n attributesMap[o.name] = '';\n });\n }\n\n return attributesMap;\n}\n\n/**\n * Gets the number of arguments expected to be passed to a generated instruction in the case of\n * interpolation instructions.\n * @param interpolation An interpolation ast\n */\nexport function getInterpolationArgsLength(interpolation: Interpolation) {\n const {expressions, strings} = interpolation;\n if (expressions.length === 1 && strings.length === 2 && strings[0] === '' && strings[1] === '') {\n // If the interpolation has one interpolated value, but the prefix and suffix are both empty\n // strings, we only pass one argument, to a special instruction like `propertyInterpolate` or\n // `textInterpolate`.\n return 1;\n } else {\n return expressions.length + strings.length;\n }\n}\n\n/**\n * Generates the final instruction call statements based on the passed in configuration.\n * Will try to chain instructions as much as possible, if chaining is supported.\n */\nexport function getInstructionStatements(instructions: Instruction[]): o.Statement[] {\n const statements: o.Statement[] = [];\n let pendingExpression: o.Expression|null = null;\n let pendingExpressionType: o.ExternalReference|null = null;\n let chainLength = 0;\n\n for (const current of instructions) {\n const resolvedParams =\n (typeof current.paramsOrFn === 'function' ? current.paramsOrFn() : current.paramsOrFn) ??\n [];\n const params = Array.isArray(resolvedParams) ? resolvedParams : [resolvedParams];\n\n // If the current instruction is the same as the previous one\n // and it can be chained, add another call to the chain.\n if (chainLength < MAX_CHAIN_LENGTH && pendingExpressionType === current.reference &&\n CHAINABLE_INSTRUCTIONS.has(pendingExpressionType)) {\n // We'll always have a pending expression when there's a pending expression type.\n pendingExpression = pendingExpression!.callFn(params, pendingExpression!.sourceSpan);\n chainLength++;\n } else {\n if (pendingExpression !== null) {\n statements.push(pendingExpression.toStmt());\n }\n pendingExpression = invokeInstruction(current.span, current.reference, params);\n pendingExpressionType = current.reference;\n chainLength = 0;\n }\n }\n\n // Since the current instruction adds the previous one to the statements,\n // we may be left with the final one at the end that is still pending.\n if (pendingExpression !== null) {\n statements.push(pendingExpression.toStmt());\n }\n\n return statements;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport * as o from './output/output_ast';\nimport {compileFactoryFunction, FactoryTarget, R3DependencyMetadata, R3FactoryDelegateType, R3FactoryMetadata} from './render3/r3_factory';\nimport {Identifiers} from './render3/r3_identifiers';\nimport {convertFromMaybeForwardRefExpression, ForwardRefHandling, generateForwardRef, MaybeForwardRefExpression, R3CompiledExpression, R3Reference, typeWithParameters} from './render3/util';\nimport {DefinitionMap} from './render3/view/util';\n\nexport interface R3InjectableMetadata {\n name: string;\n type: R3Reference;\n typeArgumentCount: number;\n providedIn: MaybeForwardRefExpression;\n useClass?: MaybeForwardRefExpression;\n useFactory?: o.Expression;\n useExisting?: MaybeForwardRefExpression;\n useValue?: MaybeForwardRefExpression;\n deps?: R3DependencyMetadata[];\n}\n\nexport function compileInjectable(\n meta: R3InjectableMetadata, resolveForwardRefs: boolean): R3CompiledExpression {\n let result: {expression: o.Expression, statements: o.Statement[]}|null = null;\n\n const factoryMeta: R3FactoryMetadata = {\n name: meta.name,\n type: meta.type,\n typeArgumentCount: meta.typeArgumentCount,\n deps: [],\n target: FactoryTarget.Injectable,\n };\n\n if (meta.useClass !== undefined) {\n // meta.useClass has two modes of operation. Either deps are specified, in which case `new` is\n // used to instantiate the class with dependencies injected, or deps are not specified and\n // the factory of the class is used to instantiate it.\n //\n // A special case exists for useClass: Type where Type is the injectable type itself and no\n // deps are specified, in which case 'useClass' is effectively ignored.\n\n const useClassOnSelf = meta.useClass.expression.isEquivalent(meta.type.value);\n let deps: R3DependencyMetadata[]|undefined = undefined;\n if (meta.deps !== undefined) {\n deps = meta.deps;\n }\n\n if (deps !== undefined) {\n // factory: () => new meta.useClass(...deps)\n result = compileFactoryFunction({\n ...factoryMeta,\n delegate: meta.useClass.expression,\n delegateDeps: deps,\n delegateType: R3FactoryDelegateType.Class,\n });\n } else if (useClassOnSelf) {\n result = compileFactoryFunction(factoryMeta);\n } else {\n result = {\n statements: [],\n expression: delegateToFactory(\n meta.type.value as o.WrappedNodeExpr,\n meta.useClass.expression as o.WrappedNodeExpr, resolveForwardRefs)\n };\n }\n } else if (meta.useFactory !== undefined) {\n if (meta.deps !== undefined) {\n result = compileFactoryFunction({\n ...factoryMeta,\n delegate: meta.useFactory,\n delegateDeps: meta.deps || [],\n delegateType: R3FactoryDelegateType.Function,\n });\n } else {\n result = {statements: [], expression: o.arrowFn([], meta.useFactory.callFn([]))};\n }\n } else if (meta.useValue !== undefined) {\n // Note: it's safe to use `meta.useValue` instead of the `USE_VALUE in meta` check used for\n // client code because meta.useValue is an Expression which will be defined even if the actual\n // value is undefined.\n result = compileFactoryFunction({\n ...factoryMeta,\n expression: meta.useValue.expression,\n });\n } else if (meta.useExisting !== undefined) {\n // useExisting is an `inject` call on the existing token.\n result = compileFactoryFunction({\n ...factoryMeta,\n expression: o.importExpr(Identifiers.inject).callFn([meta.useExisting.expression]),\n });\n } else {\n result = {\n statements: [],\n expression: delegateToFactory(\n meta.type.value as o.WrappedNodeExpr, meta.type.value as o.WrappedNodeExpr,\n resolveForwardRefs)\n };\n }\n\n const token = meta.type.value;\n\n const injectableProps =\n new DefinitionMap<{token: o.Expression, factory: o.Expression, providedIn: o.Expression}>();\n injectableProps.set('token', token);\n injectableProps.set('factory', result.expression);\n\n // Only generate providedIn property if it has a non-null value\n if ((meta.providedIn.expression as o.LiteralExpr).value !== null) {\n injectableProps.set('providedIn', convertFromMaybeForwardRefExpression(meta.providedIn));\n }\n\n const expression = o.importExpr(Identifiers.ɵɵdefineInjectable)\n .callFn([injectableProps.toLiteralMap()], undefined, true);\n return {\n expression,\n type: createInjectableType(meta),\n statements: result.statements,\n };\n}\n\nexport function createInjectableType(meta: R3InjectableMetadata) {\n return new o.ExpressionType(o.importExpr(\n Identifiers.InjectableDeclaration,\n [typeWithParameters(meta.type.type, meta.typeArgumentCount)]));\n}\n\nfunction delegateToFactory(\n type: o.WrappedNodeExpr, useType: o.WrappedNodeExpr,\n unwrapForwardRefs: boolean): o.Expression {\n if (type.node === useType.node) {\n // The types are the same, so we can simply delegate directly to the type's factory.\n // ```\n // factory: type.ɵfac\n // ```\n return useType.prop('ɵfac');\n }\n\n if (!unwrapForwardRefs) {\n // The type is not wrapped in a `forwardRef()`, so we create a simple factory function that\n // accepts a sub-type as an argument.\n // ```\n // factory: function(t) { return useType.ɵfac(t); }\n // ```\n return createFactoryFunction(useType);\n }\n\n // The useType is actually wrapped in a `forwardRef()` so we need to resolve that before\n // calling its factory.\n // ```\n // factory: function(t) { return core.resolveForwardRef(type).ɵfac(t); }\n // ```\n const unwrappedType = o.importExpr(Identifiers.resolveForwardRef).callFn([useType]);\n return createFactoryFunction(unwrappedType);\n}\n\nfunction createFactoryFunction(type: o.Expression): o.ArrowFunctionExpr {\n return o.arrowFn(\n [new o.FnParam('t', o.DYNAMIC_TYPE)], type.prop('ɵfac').callFn([o.variable('t')]));\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nconst UNUSABLE_INTERPOLATION_REGEXPS = [\n /^\\s*$/, // empty\n /[<>]/, // html tag\n /^[{}]$/, // i18n expansion\n /&(#|[a-z])/i, // character reference,\n /^\\/\\//, // comment\n];\n\nexport function assertInterpolationSymbols(identifier: string, value: any): void {\n if (value != null && !(Array.isArray(value) && value.length == 2)) {\n throw new Error(`Expected '${identifier}' to be an array, [start, end].`);\n } else if (value != null) {\n const start = value[0] as string;\n const end = value[1] as string;\n // Check for unusable interpolation symbols\n UNUSABLE_INTERPOLATION_REGEXPS.forEach(regexp => {\n if (regexp.test(start) || regexp.test(end)) {\n throw new Error(`['${start}', '${end}'] contains unusable interpolation symbol.`);\n }\n });\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {assertInterpolationSymbols} from '../assertions';\n\nexport class InterpolationConfig {\n static fromArray(markers: [string, string]|null): InterpolationConfig {\n if (!markers) {\n return DEFAULT_INTERPOLATION_CONFIG;\n }\n\n assertInterpolationSymbols('interpolation', markers);\n return new InterpolationConfig(markers[0], markers[1]);\n }\n\n constructor(public start: string, public end: string) {}\n}\n\nexport const DEFAULT_INTERPOLATION_CONFIG: InterpolationConfig =\n new InterpolationConfig('{{', '}}');\n\nexport const DEFAULT_CONTAINER_BLOCKS = new Set(['switch']);\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nexport const $EOF = 0;\nexport const $BSPACE = 8;\nexport const $TAB = 9;\nexport const $LF = 10;\nexport const $VTAB = 11;\nexport const $FF = 12;\nexport const $CR = 13;\nexport const $SPACE = 32;\nexport const $BANG = 33;\nexport const $DQ = 34;\nexport const $HASH = 35;\nexport const $$ = 36;\nexport const $PERCENT = 37;\nexport const $AMPERSAND = 38;\nexport const $SQ = 39;\nexport const $LPAREN = 40;\nexport const $RPAREN = 41;\nexport const $STAR = 42;\nexport const $PLUS = 43;\nexport const $COMMA = 44;\nexport const $MINUS = 45;\nexport const $PERIOD = 46;\nexport const $SLASH = 47;\nexport const $COLON = 58;\nexport const $SEMICOLON = 59;\nexport const $LT = 60;\nexport const $EQ = 61;\nexport const $GT = 62;\nexport const $QUESTION = 63;\n\nexport const $0 = 48;\nexport const $7 = 55;\nexport const $9 = 57;\n\nexport const $A = 65;\nexport const $E = 69;\nexport const $F = 70;\nexport const $X = 88;\nexport const $Z = 90;\n\nexport const $LBRACKET = 91;\nexport const $BACKSLASH = 92;\nexport const $RBRACKET = 93;\nexport const $CARET = 94;\nexport const $_ = 95;\n\nexport const $a = 97;\nexport const $b = 98;\nexport const $e = 101;\nexport const $f = 102;\nexport const $n = 110;\nexport const $r = 114;\nexport const $t = 116;\nexport const $u = 117;\nexport const $v = 118;\nexport const $x = 120;\nexport const $z = 122;\n\nexport const $LBRACE = 123;\nexport const $BAR = 124;\nexport const $RBRACE = 125;\nexport const $NBSP = 160;\n\nexport const $PIPE = 124;\nexport const $TILDA = 126;\nexport const $AT = 64;\n\nexport const $BT = 96;\n\nexport function isWhitespace(code: number): boolean {\n return (code >= $TAB && code <= $SPACE) || (code == $NBSP);\n}\n\nexport function isDigit(code: number): boolean {\n return $0 <= code && code <= $9;\n}\n\nexport function isAsciiLetter(code: number): boolean {\n return code >= $a && code <= $z || code >= $A && code <= $Z;\n}\n\nexport function isAsciiHexDigit(code: number): boolean {\n return code >= $a && code <= $f || code >= $A && code <= $F || isDigit(code);\n}\n\nexport function isNewLine(code: number): boolean {\n return code === $LF || code === $CR;\n}\n\nexport function isOctalDigit(code: number): boolean {\n return $0 <= code && code <= $7;\n}\n\nexport function isQuote(code: number): boolean {\n return code === $SQ || code === $DQ || code === $BT;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport * as chars from './chars';\nimport {stringify} from './util';\n\nexport class ParseLocation {\n constructor(\n public file: ParseSourceFile, public offset: number, public line: number,\n public col: number) {}\n\n toString(): string {\n return this.offset != null ? `${this.file.url}@${this.line}:${this.col}` : this.file.url;\n }\n\n moveBy(delta: number): ParseLocation {\n const source = this.file.content;\n const len = source.length;\n let offset = this.offset;\n let line = this.line;\n let col = this.col;\n while (offset > 0 && delta < 0) {\n offset--;\n delta++;\n const ch = source.charCodeAt(offset);\n if (ch == chars.$LF) {\n line--;\n const priorLine =\n source.substring(0, offset - 1).lastIndexOf(String.fromCharCode(chars.$LF));\n col = priorLine > 0 ? offset - priorLine : offset;\n } else {\n col--;\n }\n }\n while (offset < len && delta > 0) {\n const ch = source.charCodeAt(offset);\n offset++;\n delta--;\n if (ch == chars.$LF) {\n line++;\n col = 0;\n } else {\n col++;\n }\n }\n return new ParseLocation(this.file, offset, line, col);\n }\n\n // Return the source around the location\n // Up to `maxChars` or `maxLines` on each side of the location\n getContext(maxChars: number, maxLines: number): {before: string, after: string}|null {\n const content = this.file.content;\n let startOffset = this.offset;\n\n if (startOffset != null) {\n if (startOffset > content.length - 1) {\n startOffset = content.length - 1;\n }\n let endOffset = startOffset;\n let ctxChars = 0;\n let ctxLines = 0;\n\n while (ctxChars < maxChars && startOffset > 0) {\n startOffset--;\n ctxChars++;\n if (content[startOffset] == '\\n') {\n if (++ctxLines == maxLines) {\n break;\n }\n }\n }\n\n ctxChars = 0;\n ctxLines = 0;\n while (ctxChars < maxChars && endOffset < content.length - 1) {\n endOffset++;\n ctxChars++;\n if (content[endOffset] == '\\n') {\n if (++ctxLines == maxLines) {\n break;\n }\n }\n }\n\n return {\n before: content.substring(startOffset, this.offset),\n after: content.substring(this.offset, endOffset + 1),\n };\n }\n\n return null;\n }\n}\n\nexport class ParseSourceFile {\n constructor(public content: string, public url: string) {}\n}\n\nexport class ParseSourceSpan {\n /**\n * Create an object that holds information about spans of tokens/nodes captured during\n * lexing/parsing of text.\n *\n * @param start\n * The location of the start of the span (having skipped leading trivia).\n * Skipping leading trivia makes source-spans more \"user friendly\", since things like HTML\n * elements will appear to begin at the start of the opening tag, rather than at the start of any\n * leading trivia, which could include newlines.\n *\n * @param end\n * The location of the end of the span.\n *\n * @param fullStart\n * The start of the token without skipping the leading trivia.\n * This is used by tooling that splits tokens further, such as extracting Angular interpolations\n * from text tokens. Such tooling creates new source-spans relative to the original token's\n * source-span. If leading trivia characters have been skipped then the new source-spans may be\n * incorrectly offset.\n *\n * @param details\n * Additional information (such as identifier names) that should be associated with the span.\n */\n constructor(\n public start: ParseLocation, public end: ParseLocation,\n public fullStart: ParseLocation = start, public details: string|null = null) {}\n\n toString(): string {\n return this.start.file.content.substring(this.start.offset, this.end.offset);\n }\n}\n\nexport enum ParseErrorLevel {\n WARNING,\n ERROR,\n}\n\nexport class ParseError {\n constructor(\n public span: ParseSourceSpan, public msg: string,\n public level: ParseErrorLevel = ParseErrorLevel.ERROR) {}\n\n contextualMessage(): string {\n const ctx = this.span.start.getContext(100, 3);\n return ctx ? `${this.msg} (\"${ctx.before}[${ParseErrorLevel[this.level]} ->]${ctx.after}\")` :\n this.msg;\n }\n\n toString(): string {\n const details = this.span.details ? `, ${this.span.details}` : '';\n return `${this.contextualMessage()}: ${this.span.start}${details}`;\n }\n}\n\n/**\n * Generates Source Span object for a given R3 Type for JIT mode.\n *\n * @param kind Component or Directive.\n * @param typeName name of the Component or Directive.\n * @param sourceUrl reference to Component or Directive source.\n * @returns instance of ParseSourceSpan that represent a given Component or Directive.\n */\nexport function r3JitTypeSourceSpan(\n kind: string, typeName: string, sourceUrl: string): ParseSourceSpan {\n const sourceFileName = `in ${kind} ${typeName} in ${sourceUrl}`;\n const sourceFile = new ParseSourceFile('', sourceFileName);\n return new ParseSourceSpan(\n new ParseLocation(sourceFile, -1, -1, -1), new ParseLocation(sourceFile, -1, -1, -1));\n}\n\nlet _anonymousTypeIndex = 0;\n\nexport function identifierName(compileIdentifier: CompileIdentifierMetadata|null|undefined): string|\n null {\n if (!compileIdentifier || !compileIdentifier.reference) {\n return null;\n }\n const ref = compileIdentifier.reference;\n if (ref['__anonymousType']) {\n return ref['__anonymousType'];\n }\n if (ref['__forward_ref__']) {\n // We do not want to try to stringify a `forwardRef()` function because that would cause the\n // inner function to be evaluated too early, defeating the whole point of the `forwardRef`.\n return '__forward_ref__';\n }\n let identifier = stringify(ref);\n if (identifier.indexOf('(') >= 0) {\n // case: anonymous functions!\n identifier = `anonymous_${_anonymousTypeIndex++}`;\n ref['__anonymousType'] = identifier;\n } else {\n identifier = sanitizeIdentifier(identifier);\n }\n return identifier;\n}\n\nexport interface CompileIdentifierMetadata {\n reference: any;\n}\n\nexport function sanitizeIdentifier(name: string): string {\n return name.replace(/\\W/g, '_');\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n\nimport {AbstractEmitterVisitor, EmitterVisitorContext, escapeIdentifier} from './abstract_emitter';\nimport * as o from './output_ast';\n\n/**\n * In TypeScript, tagged template functions expect a \"template object\", which is an array of\n * \"cooked\" strings plus a `raw` property that contains an array of \"raw\" strings. This is\n * typically constructed with a function called `__makeTemplateObject(cooked, raw)`, but it may not\n * be available in all environments.\n *\n * This is a JavaScript polyfill that uses __makeTemplateObject when it's available, but otherwise\n * creates an inline helper with the same functionality.\n *\n * In the inline function, if `Object.defineProperty` is available we use that to attach the `raw`\n * array.\n */\nconst makeTemplateObjectPolyfill =\n '(this&&this.__makeTemplateObject||function(e,t){return Object.defineProperty?Object.defineProperty(e,\"raw\",{value:t}):e.raw=t,e})';\n\nexport abstract class AbstractJsEmitterVisitor extends AbstractEmitterVisitor {\n constructor() {\n super(false);\n }\n\n override visitWrappedNodeExpr(ast: o.WrappedNodeExpr, ctx: EmitterVisitorContext): any {\n throw new Error('Cannot emit a WrappedNodeExpr in Javascript.');\n }\n\n override visitDeclareVarStmt(stmt: o.DeclareVarStmt, ctx: EmitterVisitorContext): any {\n ctx.print(stmt, `var ${stmt.name}`);\n if (stmt.value) {\n ctx.print(stmt, ' = ');\n stmt.value.visitExpression(this, ctx);\n }\n ctx.println(stmt, `;`);\n return null;\n }\n override visitTaggedTemplateExpr(ast: o.TaggedTemplateExpr, ctx: EmitterVisitorContext): any {\n // The following convoluted piece of code is effectively the downlevelled equivalent of\n // ```\n // tag`...`\n // ```\n // which is effectively like:\n // ```\n // tag(__makeTemplateObject(cooked, raw), expression1, expression2, ...);\n // ```\n const elements = ast.template.elements;\n ast.tag.visitExpression(this, ctx);\n ctx.print(ast, `(${makeTemplateObjectPolyfill}(`);\n ctx.print(ast, `[${elements.map(part => escapeIdentifier(part.text, false)).join(', ')}], `);\n ctx.print(ast, `[${elements.map(part => escapeIdentifier(part.rawText, false)).join(', ')}])`);\n ast.template.expressions.forEach(expression => {\n ctx.print(ast, ', ');\n expression.visitExpression(this, ctx);\n });\n ctx.print(ast, ')');\n return null;\n }\n override visitFunctionExpr(ast: o.FunctionExpr, ctx: EmitterVisitorContext): any {\n ctx.print(ast, `function${ast.name ? ' ' + ast.name : ''}(`);\n this._visitParams(ast.params, ctx);\n ctx.println(ast, `) {`);\n ctx.incIndent();\n this.visitAllStatements(ast.statements, ctx);\n ctx.decIndent();\n ctx.print(ast, `}`);\n return null;\n }\n override visitArrowFunctionExpr(ast: o.ArrowFunctionExpr, ctx: EmitterVisitorContext): any {\n ctx.print(ast, '(');\n this._visitParams(ast.params, ctx);\n ctx.print(ast, ') =>');\n\n if (Array.isArray(ast.body)) {\n ctx.println(ast, `{`);\n ctx.incIndent();\n this.visitAllStatements(ast.body, ctx);\n ctx.decIndent();\n ctx.print(ast, `}`);\n } else {\n const isObjectLiteral = ast.body instanceof o.LiteralMapExpr;\n\n if (isObjectLiteral) {\n ctx.print(ast, '(');\n }\n\n ast.body.visitExpression(this, ctx);\n\n if (isObjectLiteral) {\n ctx.print(ast, ')');\n }\n }\n\n return null;\n }\n override visitDeclareFunctionStmt(stmt: o.DeclareFunctionStmt, ctx: EmitterVisitorContext): any {\n ctx.print(stmt, `function ${stmt.name}(`);\n this._visitParams(stmt.params, ctx);\n ctx.println(stmt, `) {`);\n ctx.incIndent();\n this.visitAllStatements(stmt.statements, ctx);\n ctx.decIndent();\n ctx.println(stmt, `}`);\n return null;\n }\n override visitLocalizedString(ast: o.LocalizedString, ctx: EmitterVisitorContext): any {\n // The following convoluted piece of code is effectively the downlevelled equivalent of\n // ```\n // $localize `...`\n // ```\n // which is effectively like:\n // ```\n // $localize(__makeTemplateObject(cooked, raw), expression1, expression2, ...);\n // ```\n ctx.print(ast, `$localize(${makeTemplateObjectPolyfill}(`);\n const parts = [ast.serializeI18nHead()];\n for (let i = 1; i < ast.messageParts.length; i++) {\n parts.push(ast.serializeI18nTemplatePart(i));\n }\n ctx.print(ast, `[${parts.map(part => escapeIdentifier(part.cooked, false)).join(', ')}], `);\n ctx.print(ast, `[${parts.map(part => escapeIdentifier(part.raw, false)).join(', ')}])`);\n ast.expressions.forEach(expression => {\n ctx.print(ast, ', ');\n expression.visitExpression(this, ctx);\n });\n ctx.print(ast, ')');\n return null;\n }\n\n private _visitParams(params: o.FnParam[], ctx: EmitterVisitorContext): void {\n this.visitAllObjects(param => ctx.print(null, param.name), params, ctx, ',');\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * @fileoverview\n * A module to facilitate use of a Trusted Types policy within the JIT\n * compiler. It lazily constructs the Trusted Types policy, providing helper\n * utilities for promoting strings to Trusted Types. When Trusted Types are not\n * available, strings are used as a fallback.\n * @security All use of this module is security-sensitive and should go through\n * security review.\n */\n\nimport {global} from '../util';\n\n/**\n * While Angular only uses Trusted Types internally for the time being,\n * references to Trusted Types could leak into our core.d.ts, which would force\n * anyone compiling against @angular/core to provide the @types/trusted-types\n * package in their compilation unit.\n *\n * Until https://github.com/microsoft/TypeScript/issues/30024 is resolved, we\n * will keep Angular's public API surface free of references to Trusted Types.\n * For internal and semi-private APIs that need to reference Trusted Types, the\n * minimal type definitions for the Trusted Types API provided by this module\n * should be used instead. They are marked as \"declare\" to prevent them from\n * being renamed by compiler optimization.\n *\n * Adapted from\n * https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/trusted-types/index.d.ts\n * but restricted to the API surface used within Angular.\n */\n\nexport declare interface TrustedScript {\n __brand__: 'TrustedScript';\n}\n\nexport declare interface TrustedTypePolicyFactory {\n createPolicy(policyName: string, policyOptions: {\n createScript?: (input: string) => string,\n }): TrustedTypePolicy;\n}\n\nexport declare interface TrustedTypePolicy {\n createScript(input: string): TrustedScript;\n}\n\n\n/**\n * The Trusted Types policy, or null if Trusted Types are not\n * enabled/supported, or undefined if the policy has not been created yet.\n */\nlet policy: TrustedTypePolicy|null|undefined;\n\n/**\n * Returns the Trusted Types policy, or null if Trusted Types are not\n * enabled/supported. The first call to this function will create the policy.\n */\nfunction getPolicy(): TrustedTypePolicy|null {\n if (policy === undefined) {\n const trustedTypes = global['trustedTypes'] as TrustedTypePolicyFactory | undefined;\n policy = null;\n\n if (trustedTypes) {\n try {\n policy = trustedTypes.createPolicy('angular#unsafe-jit', {\n createScript: (s: string) => s,\n });\n } catch {\n // trustedTypes.createPolicy throws if called with a name that is\n // already registered, even in report-only mode. Until the API changes,\n // catch the error not to break the applications functionally. In such\n // cases, the code will fall back to using strings.\n }\n }\n }\n return policy;\n}\n\n/**\n * Unsafely promote a string to a TrustedScript, falling back to strings when\n * Trusted Types are not available.\n * @security In particular, it must be assured that the provided string will\n * never cause an XSS vulnerability if used in a context that will be\n * interpreted and executed as a script by a browser, e.g. when calling eval.\n */\nfunction trustedScriptFromString(script: string): TrustedScript|string {\n return getPolicy()?.createScript(script) || script;\n}\n\n/**\n * Unsafely call the Function constructor with the given string arguments.\n * @security This is a security-sensitive function; any use of this function\n * must go through security review. In particular, it must be assured that it\n * is only called from the JIT compiler, as use in other code can lead to XSS\n * vulnerabilities.\n */\nexport function newTrustedFunctionForJIT(...args: string[]): Function {\n if (!global['trustedTypes']) {\n // In environments that don't support Trusted Types, fall back to the most\n // straightforward implementation:\n return new Function(...args);\n }\n\n // Chrome currently does not support passing TrustedScript to the Function\n // constructor. The following implements the workaround proposed on the page\n // below, where the Chromium bug is also referenced:\n // https://github.com/w3c/webappsec-trusted-types/wiki/Trusted-Types-for-function-constructor\n const fnArgs = args.slice(0, -1).join(',');\n const fnBody = args[args.length - 1];\n const body = `(function anonymous(${fnArgs}\n) { ${fnBody}\n})`;\n\n // Using eval directly confuses the compiler and prevents this module from\n // being stripped out of JS binaries even if not used. The global['eval']\n // indirection fixes that.\n const fn = global['eval'](trustedScriptFromString(body) as string) as Function;\n if (fn.bind === undefined) {\n // Workaround for a browser bug that only exists in Chrome 83, where passing\n // a TrustedScript to eval just returns the TrustedScript back without\n // evaluating it. In that case, fall back to the most straightforward\n // implementation:\n return new Function(...args);\n }\n\n // To completely mimic the behavior of calling \"new Function\", two more\n // things need to happen:\n // 1. Stringifying the resulting function should return its source code\n fn.toString = () => body;\n // 2. When calling the resulting function, `this` should refer to `global`\n return fn.bind(global);\n\n // When Trusted Types support in Function constructors is widely available,\n // the implementation of this function can be simplified to:\n // return new Function(...args.map(a => trustedScriptFromString(a)));\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {identifierName} from '../parse_util';\n\nimport {EmitterVisitorContext} from './abstract_emitter';\nimport {AbstractJsEmitterVisitor} from './abstract_js_emitter';\nimport * as o from './output_ast';\nimport {newTrustedFunctionForJIT} from './output_jit_trusted_types';\n\nexport interface ExternalReferenceResolver {\n resolveExternalReference(ref: o.ExternalReference): unknown;\n}\n\n/**\n * A helper class to manage the evaluation of JIT generated code.\n */\nexport class JitEvaluator {\n /**\n *\n * @param sourceUrl The URL of the generated code.\n * @param statements An array of Angular statement AST nodes to be evaluated.\n * @param refResolver Resolves `o.ExternalReference`s into values.\n * @param createSourceMaps If true then create a source-map for the generated code and include it\n * inline as a source-map comment.\n * @returns A map of all the variables in the generated code.\n */\n evaluateStatements(\n sourceUrl: string, statements: o.Statement[], refResolver: ExternalReferenceResolver,\n createSourceMaps: boolean): {[key: string]: any} {\n const converter = new JitEmitterVisitor(refResolver);\n const ctx = EmitterVisitorContext.createRoot();\n // Ensure generated code is in strict mode\n if (statements.length > 0 && !isUseStrictStatement(statements[0])) {\n statements = [\n o.literal('use strict').toStmt(),\n ...statements,\n ];\n }\n converter.visitAllStatements(statements, ctx);\n converter.createReturnStmt(ctx);\n return this.evaluateCode(sourceUrl, ctx, converter.getArgs(), createSourceMaps);\n }\n\n /**\n * Evaluate a piece of JIT generated code.\n * @param sourceUrl The URL of this generated code.\n * @param ctx A context object that contains an AST of the code to be evaluated.\n * @param vars A map containing the names and values of variables that the evaluated code might\n * reference.\n * @param createSourceMap If true then create a source-map for the generated code and include it\n * inline as a source-map comment.\n * @returns The result of evaluating the code.\n */\n evaluateCode(\n sourceUrl: string, ctx: EmitterVisitorContext, vars: {[key: string]: any},\n createSourceMap: boolean): any {\n let fnBody = `\"use strict\";${ctx.toSource()}\\n//# sourceURL=${sourceUrl}`;\n const fnArgNames: string[] = [];\n const fnArgValues: any[] = [];\n for (const argName in vars) {\n fnArgValues.push(vars[argName]);\n fnArgNames.push(argName);\n }\n if (createSourceMap) {\n // using `new Function(...)` generates a header, 1 line of no arguments, 2 lines otherwise\n // E.g. ```\n // function anonymous(a,b,c\n // /**/) { ... }```\n // We don't want to hard code this fact, so we auto detect it via an empty function first.\n const emptyFn = newTrustedFunctionForJIT(...fnArgNames.concat('return null;')).toString();\n const headerLines = emptyFn.slice(0, emptyFn.indexOf('return null;')).split('\\n').length - 1;\n fnBody += `\\n${ctx.toSourceMapGenerator(sourceUrl, headerLines).toJsComment()}`;\n }\n const fn = newTrustedFunctionForJIT(...fnArgNames.concat(fnBody));\n return this.executeFunction(fn, fnArgValues);\n }\n\n /**\n * Execute a JIT generated function by calling it.\n *\n * This method can be overridden in tests to capture the functions that are generated\n * by this `JitEvaluator` class.\n *\n * @param fn A function to execute.\n * @param args The arguments to pass to the function being executed.\n * @returns The return value of the executed function.\n */\n executeFunction(fn: Function, args: any[]) {\n return fn(...args);\n }\n}\n\n/**\n * An Angular AST visitor that converts AST nodes into executable JavaScript code.\n */\nexport class JitEmitterVisitor extends AbstractJsEmitterVisitor {\n private _evalArgNames: string[] = [];\n private _evalArgValues: any[] = [];\n private _evalExportedVars: string[] = [];\n\n constructor(private refResolver: ExternalReferenceResolver) {\n super();\n }\n\n createReturnStmt(ctx: EmitterVisitorContext) {\n const stmt = new o.ReturnStatement(new o.LiteralMapExpr(this._evalExportedVars.map(\n resultVar => new o.LiteralMapEntry(resultVar, o.variable(resultVar), false))));\n stmt.visitStatement(this, ctx);\n }\n\n getArgs(): {[key: string]: any} {\n const result: {[key: string]: any} = {};\n for (let i = 0; i < this._evalArgNames.length; i++) {\n result[this._evalArgNames[i]] = this._evalArgValues[i];\n }\n return result;\n }\n\n override visitExternalExpr(ast: o.ExternalExpr, ctx: EmitterVisitorContext): any {\n this._emitReferenceToExternal(ast, this.refResolver.resolveExternalReference(ast.value), ctx);\n return null;\n }\n\n override visitWrappedNodeExpr(ast: o.WrappedNodeExpr, ctx: EmitterVisitorContext): any {\n this._emitReferenceToExternal(ast, ast.node, ctx);\n return null;\n }\n\n override visitDeclareVarStmt(stmt: o.DeclareVarStmt, ctx: EmitterVisitorContext): any {\n if (stmt.hasModifier(o.StmtModifier.Exported)) {\n this._evalExportedVars.push(stmt.name);\n }\n return super.visitDeclareVarStmt(stmt, ctx);\n }\n\n override visitDeclareFunctionStmt(stmt: o.DeclareFunctionStmt, ctx: EmitterVisitorContext): any {\n if (stmt.hasModifier(o.StmtModifier.Exported)) {\n this._evalExportedVars.push(stmt.name);\n }\n return super.visitDeclareFunctionStmt(stmt, ctx);\n }\n\n private _emitReferenceToExternal(ast: o.Expression, value: any, ctx: EmitterVisitorContext):\n void {\n let id = this._evalArgValues.indexOf(value);\n if (id === -1) {\n id = this._evalArgValues.length;\n this._evalArgValues.push(value);\n const name = identifierName({reference: value}) || 'val';\n this._evalArgNames.push(`jit_${name}_${id}`);\n }\n ctx.print(ast, this._evalArgNames[id]);\n }\n}\n\n\nfunction isUseStrictStatement(statement: o.Statement): boolean {\n return statement.isEquivalent(o.literal('use strict').toStmt());\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport * as o from '../output/output_ast';\n\nimport {Identifiers as R3} from './r3_identifiers';\nimport {R3CompiledExpression, R3Reference} from './util';\nimport {DefinitionMap} from './view/util';\n\nexport interface R3InjectorMetadata {\n name: string;\n type: R3Reference;\n providers: o.Expression|null;\n imports: o.Expression[];\n}\n\nexport function compileInjector(meta: R3InjectorMetadata): R3CompiledExpression {\n const definitionMap = new DefinitionMap<{providers: o.Expression; imports: o.Expression;}>();\n\n if (meta.providers !== null) {\n definitionMap.set('providers', meta.providers);\n }\n\n if (meta.imports.length > 0) {\n definitionMap.set('imports', o.literalArr(meta.imports));\n }\n\n const expression =\n o.importExpr(R3.defineInjector).callFn([definitionMap.toLiteralMap()], undefined, true);\n const type = createInjectorType(meta);\n return {expression, type, statements: []};\n}\n\nexport function createInjectorType(meta: R3InjectorMetadata): o.Type {\n return new o.ExpressionType(\n o.importExpr(R3.InjectorDeclaration, [new o.ExpressionType(meta.type.type)]));\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport * as o from '../output/output_ast';\nimport {ExternalReferenceResolver} from '../output/output_jit';\n\n/**\n * Implementation of `CompileReflector` which resolves references to @angular/core\n * symbols at runtime, according to a consumer-provided mapping.\n *\n * Only supports `resolveExternalReference`, all other methods throw.\n */\nexport class R3JitReflector implements ExternalReferenceResolver {\n constructor(private context: {[key: string]: unknown}) {}\n\n resolveExternalReference(ref: o.ExternalReference): unknown {\n // This reflector only handles @angular/core imports.\n if (ref.moduleName !== '@angular/core') {\n throw new Error(`Cannot resolve external reference to ${\n ref.moduleName}, only references to @angular/core are supported.`);\n }\n if (!this.context.hasOwnProperty(ref.name!)) {\n throw new Error(`No value provided for @angular/core symbol '${ref.name!}'.`);\n }\n return this.context[ref.name!];\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {R3DeclareNgModuleFacade} from '../compiler_facade_interface';\nimport * as o from '../output/output_ast';\n\nimport {Identifiers as R3} from './r3_identifiers';\nimport {jitOnlyGuardedExpression, R3CompiledExpression, R3Reference, refsToArray} from './util';\nimport {DefinitionMap} from './view/util';\n\n/**\n * How the selector scope of an NgModule (its declarations, imports, and exports) should be emitted\n * as a part of the NgModule definition.\n */\nexport enum R3SelectorScopeMode {\n /**\n * Emit the declarations inline into the module definition.\n *\n * This option is useful in certain contexts where it's known that JIT support is required. The\n * tradeoff here is that this emit style prevents directives and pipes from being tree-shaken if\n * they are unused, but the NgModule is used.\n */\n Inline,\n\n /**\n * Emit the declarations using a side effectful function call, `ɵɵsetNgModuleScope`, that is\n * guarded with the `ngJitMode` flag.\n *\n * This form of emit supports JIT and can be optimized away if the `ngJitMode` flag is set to\n * false, which allows unused directives and pipes to be tree-shaken.\n */\n SideEffect,\n\n /**\n * Don't generate selector scopes at all.\n *\n * This is useful for contexts where JIT support is known to be unnecessary.\n */\n Omit,\n}\n\n/**\n * The type of the NgModule meta data.\n * - Global: Used for full and partial compilation modes which mainly includes R3References.\n * - Local: Used for the local compilation mode which mainly includes the raw expressions as appears\n * in the NgModule decorator.\n */\nexport enum R3NgModuleMetadataKind {\n Global,\n Local,\n}\n\ninterface R3NgModuleMetadataCommon {\n kind: R3NgModuleMetadataKind;\n\n /**\n * An expression representing the module type being compiled.\n */\n type: R3Reference;\n\n /**\n * How to emit the selector scope values (declarations, imports, exports).\n */\n selectorScopeMode: R3SelectorScopeMode;\n\n /**\n * The set of schemas that declare elements to be allowed in the NgModule.\n */\n schemas: R3Reference[]|null;\n\n /** Unique ID or expression representing the unique ID of an NgModule. */\n id: o.Expression|null;\n}\n\n/**\n * Metadata required by the module compiler in full/partial mode to generate a module def (`ɵmod`)\n * for a type.\n */\nexport interface R3NgModuleMetadataGlobal extends R3NgModuleMetadataCommon {\n kind: R3NgModuleMetadataKind.Global;\n\n /**\n * An array of expressions representing the bootstrap components specified by the module.\n */\n bootstrap: R3Reference[];\n\n /**\n * An array of expressions representing the directives and pipes declared by the module.\n */\n declarations: R3Reference[];\n\n /**\n * Those declarations which should be visible to downstream consumers. If not specified, all\n * declarations are made visible to downstream consumers.\n */\n publicDeclarationTypes: o.Expression[]|null;\n\n /**\n * An array of expressions representing the imports of the module.\n */\n imports: R3Reference[];\n\n /**\n * Whether or not to include `imports` in generated type declarations.\n */\n includeImportTypes: boolean;\n\n /**\n * An array of expressions representing the exports of the module.\n */\n exports: R3Reference[];\n\n /**\n * Whether to generate closure wrappers for bootstrap, declarations, imports, and exports.\n */\n containsForwardDecls: boolean;\n}\n\n/**\n * Metadata required by the module compiler in local mode to generate a module def (`ɵmod`) for a\n * type.\n */\nexport interface R3NgModuleMetadataLocal extends R3NgModuleMetadataCommon {\n kind: R3NgModuleMetadataKind.Local;\n\n /**\n * The output expression representing the bootstrap components specified by the module.\n */\n bootstrapExpression: o.Expression|null;\n\n /**\n * The output expression representing the declarations of the module.\n */\n declarationsExpression: o.Expression|null;\n\n /**\n * The output expression representing the imports of the module.\n */\n importsExpression: o.Expression|null;\n\n /**\n * The output expression representing the exports of the module.\n */\n exportsExpression: o.Expression|null;\n\n /**\n * Local compilation mode always requires scope to be handled using side effect function calls.\n */\n selectorScopeMode: R3SelectorScopeMode.SideEffect;\n}\n\n/**\n * Metadata required by the module compiler to generate a module def (`ɵmod`) for a type.\n */\nexport type R3NgModuleMetadata = R3NgModuleMetadataGlobal|R3NgModuleMetadataLocal;\n\n/**\n * The shape of the object literal that is passed to the `ɵɵdefineNgModule()` call.\n */\ninterface R3NgModuleDefMap {\n /**\n * An expression representing the module type being compiled.\n */\n type: o.Expression;\n /**\n * An expression evaluating to an array of expressions representing the bootstrap components\n * specified by the module.\n */\n bootstrap?: o.Expression;\n /**\n * An expression evaluating to an array of expressions representing the directives and pipes\n * declared by the module.\n */\n declarations?: o.Expression;\n /**\n * An expression evaluating to an array of expressions representing the imports of the module.\n */\n imports?: o.Expression;\n /**\n * An expression evaluating to an array of expressions representing the exports of the module.\n */\n exports?: o.Expression;\n /**\n * A literal array expression containing the schemas that declare elements to be allowed in the\n * NgModule.\n */\n schemas?: o.LiteralArrayExpr;\n /**\n * An expression evaluating to the unique ID of an NgModule.\n * */\n id?: o.Expression;\n}\n\n/**\n * Construct an `R3NgModuleDef` for the given `R3NgModuleMetadata`.\n */\nexport function compileNgModule(meta: R3NgModuleMetadata): R3CompiledExpression {\n const statements: o.Statement[] = [];\n const definitionMap = new DefinitionMap();\n definitionMap.set('type', meta.type.value);\n\n // Assign bootstrap definition. In local compilation mode (i.e., for\n // `R3NgModuleMetadataKind.LOCAL`) we assign the bootstrap field using the runtime\n // `ɵɵsetNgModuleScope`.\n if (meta.kind === R3NgModuleMetadataKind.Global && meta.bootstrap.length > 0) {\n definitionMap.set('bootstrap', refsToArray(meta.bootstrap, meta.containsForwardDecls));\n }\n\n if (meta.selectorScopeMode === R3SelectorScopeMode.Inline) {\n // If requested to emit scope information inline, pass the `declarations`, `imports` and\n // `exports` to the `ɵɵdefineNgModule()` call directly.\n\n if (meta.declarations.length > 0) {\n definitionMap.set('declarations', refsToArray(meta.declarations, meta.containsForwardDecls));\n }\n\n if (meta.imports.length > 0) {\n definitionMap.set('imports', refsToArray(meta.imports, meta.containsForwardDecls));\n }\n\n if (meta.exports.length > 0) {\n definitionMap.set('exports', refsToArray(meta.exports, meta.containsForwardDecls));\n }\n } else if (meta.selectorScopeMode === R3SelectorScopeMode.SideEffect) {\n // In this mode, scope information is not passed into `ɵɵdefineNgModule` as it\n // would prevent tree-shaking of the declarations, imports and exports references. Instead, it's\n // patched onto the NgModule definition with a `ɵɵsetNgModuleScope` call that's guarded by the\n // `ngJitMode` flag.\n const setNgModuleScopeCall = generateSetNgModuleScopeCall(meta);\n if (setNgModuleScopeCall !== null) {\n statements.push(setNgModuleScopeCall);\n }\n } else {\n // Selector scope emit was not requested, so skip it.\n }\n\n if (meta.schemas !== null && meta.schemas.length > 0) {\n definitionMap.set('schemas', o.literalArr(meta.schemas.map(ref => ref.value)));\n }\n\n if (meta.id !== null) {\n definitionMap.set('id', meta.id);\n\n // Generate a side-effectful call to register this NgModule by its id, as per the semantics of\n // NgModule ids.\n statements.push(\n o.importExpr(R3.registerNgModuleType).callFn([meta.type.value, meta.id]).toStmt());\n }\n\n const expression =\n o.importExpr(R3.defineNgModule).callFn([definitionMap.toLiteralMap()], undefined, true);\n const type = createNgModuleType(meta);\n\n return {expression, type, statements};\n}\n\n/**\n * This function is used in JIT mode to generate the call to `ɵɵdefineNgModule()` from a call to\n * `ɵɵngDeclareNgModule()`.\n */\nexport function compileNgModuleDeclarationExpression(meta: R3DeclareNgModuleFacade): o.Expression {\n const definitionMap = new DefinitionMap();\n definitionMap.set('type', new o.WrappedNodeExpr(meta.type));\n if (meta.bootstrap !== undefined) {\n definitionMap.set('bootstrap', new o.WrappedNodeExpr(meta.bootstrap));\n }\n if (meta.declarations !== undefined) {\n definitionMap.set('declarations', new o.WrappedNodeExpr(meta.declarations));\n }\n if (meta.imports !== undefined) {\n definitionMap.set('imports', new o.WrappedNodeExpr(meta.imports));\n }\n if (meta.exports !== undefined) {\n definitionMap.set('exports', new o.WrappedNodeExpr(meta.exports));\n }\n if (meta.schemas !== undefined) {\n definitionMap.set('schemas', new o.WrappedNodeExpr(meta.schemas));\n }\n if (meta.id !== undefined) {\n definitionMap.set('id', new o.WrappedNodeExpr(meta.id));\n }\n return o.importExpr(R3.defineNgModule).callFn([definitionMap.toLiteralMap()]);\n}\n\nexport function createNgModuleType(meta: R3NgModuleMetadata): o.ExpressionType {\n if (meta.kind === R3NgModuleMetadataKind.Local) {\n return new o.ExpressionType(meta.type.value);\n }\n\n const {\n type: moduleType,\n declarations,\n exports,\n imports,\n includeImportTypes,\n publicDeclarationTypes\n } = meta;\n\n return new o.ExpressionType(o.importExpr(R3.NgModuleDeclaration, [\n new o.ExpressionType(moduleType.type),\n publicDeclarationTypes === null ? tupleTypeOf(declarations) :\n tupleOfTypes(publicDeclarationTypes),\n includeImportTypes ? tupleTypeOf(imports) : o.NONE_TYPE,\n tupleTypeOf(exports),\n ]));\n}\n\n/**\n * Generates a function call to `ɵɵsetNgModuleScope` with all necessary information so that the\n * transitive module scope can be computed during runtime in JIT mode. This call is marked pure\n * such that the references to declarations, imports and exports may be elided causing these\n * symbols to become tree-shakeable.\n */\nfunction generateSetNgModuleScopeCall(meta: R3NgModuleMetadata): o.Statement|null {\n const scopeMap = new DefinitionMap<{\n declarations: o.Expression,\n imports: o.Expression,\n exports: o.Expression,\n bootstrap: o.Expression\n }>();\n\n if (meta.kind === R3NgModuleMetadataKind.Global) {\n if (meta.declarations.length > 0) {\n scopeMap.set('declarations', refsToArray(meta.declarations, meta.containsForwardDecls));\n }\n } else {\n if (meta.declarationsExpression) {\n scopeMap.set('declarations', meta.declarationsExpression);\n }\n }\n\n if (meta.kind === R3NgModuleMetadataKind.Global) {\n if (meta.imports.length > 0) {\n scopeMap.set('imports', refsToArray(meta.imports, meta.containsForwardDecls));\n }\n } else {\n if (meta.importsExpression) {\n scopeMap.set('imports', meta.importsExpression);\n }\n }\n\n if (meta.kind === R3NgModuleMetadataKind.Global) {\n if (meta.exports.length > 0) {\n scopeMap.set('exports', refsToArray(meta.exports, meta.containsForwardDecls));\n }\n } else {\n if (meta.exportsExpression) {\n scopeMap.set('exports', meta.exportsExpression);\n }\n }\n\n if (meta.kind === R3NgModuleMetadataKind.Local && meta.bootstrapExpression) {\n scopeMap.set('bootstrap', meta.bootstrapExpression);\n }\n\n if (Object.keys(scopeMap.values).length === 0) {\n return null;\n }\n\n // setNgModuleScope(...)\n const fnCall = new o.InvokeFunctionExpr(\n /* fn */ o.importExpr(R3.setNgModuleScope),\n /* args */[meta.type.value, scopeMap.toLiteralMap()]);\n\n // (ngJitMode guard) && setNgModuleScope(...)\n const guardedCall = jitOnlyGuardedExpression(fnCall);\n\n // function() { (ngJitMode guard) && setNgModuleScope(...); }\n const iife = new o.FunctionExpr(\n /* params */[],\n /* statements */[guardedCall.toStmt()]);\n\n // (function() { (ngJitMode guard) && setNgModuleScope(...); })()\n const iifeCall = new o.InvokeFunctionExpr(\n /* fn */ iife,\n /* args */[]);\n\n return iifeCall.toStmt();\n}\n\nfunction tupleTypeOf(exp: R3Reference[]): o.Type {\n const types = exp.map(ref => o.typeofExpr(ref.type));\n return exp.length > 0 ? o.expressionType(o.literalArr(types)) : o.NONE_TYPE;\n}\n\nfunction tupleOfTypes(types: o.Expression[]): o.Type {\n const typeofTypes = types.map(type => o.typeofExpr(type));\n return types.length > 0 ? o.expressionType(o.literalArr(typeofTypes)) : o.NONE_TYPE;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport * as o from '../output/output_ast';\n\nimport {R3DependencyMetadata} from './r3_factory';\nimport {Identifiers as R3} from './r3_identifiers';\nimport {R3CompiledExpression, R3Reference, typeWithParameters} from './util';\n\nexport interface R3PipeMetadata {\n /**\n * Name of the pipe type.\n */\n name: string;\n\n /**\n * An expression representing a reference to the pipe itself.\n */\n type: R3Reference;\n\n /**\n * Number of generic type parameters of the type itself.\n */\n typeArgumentCount: number;\n\n /**\n * Name of the pipe.\n */\n pipeName: string;\n\n /**\n * Dependencies of the pipe's constructor.\n */\n deps: R3DependencyMetadata[]|null;\n\n /**\n * Whether the pipe is marked as pure.\n */\n pure: boolean;\n\n /**\n * Whether the pipe is standalone.\n */\n isStandalone: boolean;\n}\n\nexport function compilePipeFromMetadata(metadata: R3PipeMetadata): R3CompiledExpression {\n const definitionMapValues: {key: string, quoted: boolean, value: o.Expression}[] = [];\n\n // e.g. `name: 'myPipe'`\n definitionMapValues.push({key: 'name', value: o.literal(metadata.pipeName), quoted: false});\n\n // e.g. `type: MyPipe`\n definitionMapValues.push({key: 'type', value: metadata.type.value, quoted: false});\n\n // e.g. `pure: true`\n definitionMapValues.push({key: 'pure', value: o.literal(metadata.pure), quoted: false});\n\n if (metadata.isStandalone) {\n definitionMapValues.push({key: 'standalone', value: o.literal(true), quoted: false});\n }\n\n const expression =\n o.importExpr(R3.definePipe).callFn([o.literalMap(definitionMapValues)], undefined, true);\n const type = createPipeType(metadata);\n\n return {expression, type, statements: []};\n}\n\nexport function createPipeType(metadata: R3PipeMetadata): o.Type {\n return new o.ExpressionType(o.importExpr(R3.PipeDeclaration, [\n typeWithParameters(metadata.type.type, metadata.typeArgumentCount),\n new o.ExpressionType(new o.LiteralExpr(metadata.pipeName)),\n new o.ExpressionType(new o.LiteralExpr(metadata.isStandalone)),\n ]));\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ChangeDetectionStrategy, ViewEncapsulation} from '../../core';\nimport {InterpolationConfig} from '../../ml_parser/defaults';\nimport * as o from '../../output/output_ast';\nimport {ParseSourceSpan} from '../../parse_util';\nimport * as t from '../r3_ast';\nimport {R3DependencyMetadata} from '../r3_factory';\nimport {MaybeForwardRefExpression, R3Reference} from '../util';\n\n\n/**\n * Information needed to compile a directive for the render3 runtime.\n */\nexport interface R3DirectiveMetadata {\n /**\n * Name of the directive type.\n */\n name: string;\n\n /**\n * An expression representing a reference to the directive itself.\n */\n type: R3Reference;\n\n /**\n * Number of generic type parameters of the type itself.\n */\n typeArgumentCount: number;\n\n /**\n * A source span for the directive type.\n */\n typeSourceSpan: ParseSourceSpan;\n\n /**\n * Dependencies of the directive's constructor.\n */\n deps: R3DependencyMetadata[]|'invalid'|null;\n\n /**\n * Unparsed selector of the directive, or `null` if there was no selector.\n */\n selector: string|null;\n\n /**\n * Information about the content queries made by the directive.\n */\n queries: R3QueryMetadata[];\n\n /**\n * Information about the view queries made by the directive.\n */\n viewQueries: R3QueryMetadata[];\n\n /**\n * Mappings indicating how the directive interacts with its host element (host bindings,\n * listeners, etc).\n */\n host: R3HostMetadata;\n\n /**\n * Information about usage of specific lifecycle events which require special treatment in the\n * code generator.\n */\n lifecycle: {\n /**\n * Whether the directive uses NgOnChanges.\n */\n usesOnChanges: boolean;\n };\n\n /**\n * A mapping of inputs from class property names to binding property names, or to a tuple of\n * binding property name and class property name if the names are different.\n */\n inputs: {[field: string]: R3InputMetadata};\n\n /**\n * A mapping of outputs from class property names to binding property names, or to a tuple of\n * binding property name and class property name if the names are different.\n */\n outputs: {[field: string]: string};\n\n /**\n * Whether or not the component or directive inherits from another class\n */\n usesInheritance: boolean;\n\n /**\n * Whether or not the component or directive inherits its entire decorator from its base class.\n */\n fullInheritance: boolean;\n\n /**\n * Reference name under which to export the directive's type in a template,\n * if any.\n */\n exportAs: string[]|null;\n\n /**\n * The list of providers defined in the directive.\n */\n providers: o.Expression|null;\n\n /**\n * Whether or not the component or directive is standalone.\n */\n isStandalone: boolean;\n\n /**\n * Whether or not the component or directive is signal-based.\n */\n isSignal: boolean;\n\n /**\n * Additional directives applied to the directive host.\n */\n hostDirectives: R3HostDirectiveMetadata[]|null;\n}\n\n/**\n * Defines how dynamic imports for deferred dependencies should be emitted in the\n * generated output:\n * - either in a function on per-component basis (in case of local compilation)\n * - or in a function on per-block basis (in full compilation mode)\n */\nexport const enum DeferBlockDepsEmitMode {\n /**\n * Dynamic imports are grouped on per-block basis.\n *\n * This is used in full compilation mode, when compiler has more information\n * about particular dependencies that belong to this block.\n */\n PerBlock,\n\n /**\n * Dynamic imports are grouped on per-component basis.\n *\n * In local compilation, compiler doesn't have enough information to determine\n * which deferred dependencies belong to which block. In this case we group all\n * dynamic imports into a single file on per-component basis.\n */\n PerComponent,\n}\n\n/**\n * Specifies how a list of declaration type references should be emitted into the generated code.\n */\nexport const enum DeclarationListEmitMode {\n /**\n * The list of declarations is emitted into the generated code as is.\n *\n * ```\n * directives: [MyDir],\n * ```\n */\n Direct,\n\n /**\n * The list of declarations is emitted into the generated code wrapped inside a closure, which\n * is needed when at least one declaration is a forward reference.\n *\n * ```\n * directives: function () { return [MyDir, ForwardDir]; },\n * ```\n */\n Closure,\n\n /**\n * Similar to `Closure`, with the addition that the list of declarations can contain individual\n * items that are themselves forward references. This is relevant for JIT compilations, as\n * unwrapping the forwardRef cannot be done statically so must be deferred. This mode emits\n * the declaration list using a mapping transform through `resolveForwardRef` to ensure that\n * any forward references within the list are resolved when the outer closure is invoked.\n *\n * Consider the case where the runtime has captured two declarations in two distinct values:\n * ```\n * const dirA = MyDir;\n * const dirB = forwardRef(function() { return ForwardRef; });\n * ```\n *\n * This mode would emit the declarations captured in `dirA` and `dirB` as follows:\n * ```\n * directives: function () { return [dirA, dirB].map(ng.resolveForwardRef); },\n * ```\n */\n ClosureResolved,\n\n RuntimeResolved,\n}\n\n/**\n * Describes a dependency used within a `@defer` block.\n */\nexport interface R3DeferBlockTemplateDependency {\n /**\n * Reference to a dependency.\n */\n type: o.WrappedNodeExpr;\n\n /**\n * Dependency class name.\n */\n symbolName: string;\n\n /**\n * Whether this dependency can be defer-loaded.\n */\n isDeferrable: boolean;\n\n /**\n * Import path where this dependency is located.\n */\n importPath: string|null;\n\n /**\n * Whether the symbol is the default export.\n */\n isDefaultImport: boolean;\n}\n\n/**\n * Information necessary to compile a `defer` block.\n */\nexport interface R3DeferBlockMetadata {\n /** Dependencies used within the block. */\n deps: R3DeferBlockTemplateDependency[];\n\n /** Mapping between triggers and the DOM nodes they refer to. */\n triggerElements: Map;\n}\n\n/**\n * Information needed to compile a component for the render3 runtime.\n */\nexport interface R3ComponentMetadata extends\n R3DirectiveMetadata {\n /**\n * Information about the component's template.\n */\n template: {\n /**\n * Parsed nodes of the template.\n */\n nodes: t.Node[];\n\n /**\n * Any ng-content selectors extracted from the template. Contains `*` when an ng-content\n * element without selector is present.\n */\n ngContentSelectors: string[];\n\n /**\n * Whether the template preserves whitespaces from the user's code.\n */\n preserveWhitespaces?: boolean;\n };\n\n declarations: DeclarationT[];\n\n /**\n * Map of all types that can be defer loaded (ts.ClassDeclaration) ->\n * corresponding import declaration (ts.ImportDeclaration) within\n * the current source file.\n */\n deferrableDeclToImportDecl: Map;\n\n /**\n * Map of `@defer` blocks -> their corresponding metadata.\n */\n deferBlocks: Map;\n\n /**\n * Defines how dynamic imports for deferred dependencies should be grouped:\n * - either in a function on per-component basis (in case of local compilation)\n * - or in a function on per-block basis (in full compilation mode)\n */\n deferBlockDepsEmitMode: DeferBlockDepsEmitMode;\n\n /**\n * Map of deferrable symbol names -> corresponding import paths.\n */\n deferrableTypes: Map;\n\n /**\n * Specifies how the 'directives' and/or `pipes` array, if generated, need to be emitted.\n */\n declarationListEmitMode: DeclarationListEmitMode;\n\n /**\n * A collection of styling data that will be applied and scoped to the component.\n */\n styles: string[];\n\n /**\n * An encapsulation policy for the component's styling.\n * Possible values:\n * - `ViewEncapsulation.Emulated`: Apply modified component styles in order to emulate\n * a native Shadow DOM CSS encapsulation behavior.\n * - `ViewEncapsulation.None`: Apply component styles globally without any sort of encapsulation.\n * - `ViewEncapsulation.ShadowDom`: Use the browser's native Shadow DOM API to encapsulate styles.\n */\n encapsulation: ViewEncapsulation;\n\n /**\n * A collection of animation triggers that will be used in the component template.\n */\n animations: o.Expression|null;\n\n /**\n * The list of view providers defined in the component.\n */\n viewProviders: o.Expression|null;\n\n /**\n * Path to the .ts file in which this template's generated code will be included, relative to\n * the compilation root. This will be used to generate identifiers that need to be globally\n * unique in certain contexts (such as g3).\n */\n relativeContextFilePath: string;\n\n /**\n * Whether translation variable name should contain external message id\n * (used by Closure Compiler's output of `goog.getMsg` for transition period).\n */\n i18nUseExternalIds: boolean;\n\n /**\n * Overrides the default interpolation start and end delimiters ({{ and }}).\n */\n interpolation: InterpolationConfig;\n\n /**\n * Strategy used for detecting changes in the component.\n *\n * In global compilation mode the value is ChangeDetectionStrategy if available as it is\n * statically resolved during analysis phase. Whereas in local compilation mode the value is the\n * expression as appears in the decorator.\n */\n changeDetection: ChangeDetectionStrategy|o.Expression|null;\n\n /**\n * The imports expression as appears on the component decorate for standalone component. This\n * field is currently needed only for local compilation, and so in other compilation modes it may\n * not be set. If component has empty array imports then this field is not set.\n */\n rawImports?: o.Expression;\n}\n\n/**\n * Metadata for an individual input on a directive.\n */\nexport interface R3InputMetadata {\n classPropertyName: string;\n bindingPropertyName: string;\n required: boolean;\n isSignal: boolean;\n /**\n * Transform function for the input.\n *\n * Null if there is no transform, or if this is a signal input.\n * Signal inputs capture their transform as part of the `InputSignal`.\n */\n transformFunction: o.Expression|null;\n}\n\nexport enum R3TemplateDependencyKind {\n Directive = 0,\n Pipe = 1,\n NgModule = 2,\n}\n\n/**\n * A dependency that's used within a component template.\n */\nexport interface R3TemplateDependency {\n kind: R3TemplateDependencyKind;\n\n /**\n * The type of the dependency as an expression.\n */\n type: o.Expression;\n}\n\n/**\n * A dependency that's used within a component template\n */\nexport type R3TemplateDependencyMetadata =\n R3DirectiveDependencyMetadata|R3PipeDependencyMetadata|R3NgModuleDependencyMetadata;\n\n/**\n * Information about a directive that is used in a component template. Only the stable, public\n * facing information of the directive is stored here.\n */\nexport interface R3DirectiveDependencyMetadata extends R3TemplateDependency {\n kind: R3TemplateDependencyKind.Directive;\n\n /**\n * The selector of the directive.\n */\n selector: string;\n\n /**\n * The binding property names of the inputs of the directive.\n */\n inputs: string[];\n\n /**\n * The binding property names of the outputs of the directive.\n */\n outputs: string[];\n\n /**\n * Name under which the directive is exported, if any (exportAs in Angular). Null otherwise.\n */\n exportAs: string[]|null;\n\n /**\n * If true then this directive is actually a component; otherwise it is not.\n */\n isComponent: boolean;\n}\n\nexport interface R3PipeDependencyMetadata extends R3TemplateDependency {\n kind: R3TemplateDependencyKind.Pipe;\n\n name: string;\n}\n\nexport interface R3NgModuleDependencyMetadata extends R3TemplateDependency {\n kind: R3TemplateDependencyKind.NgModule;\n}\n\n/**\n * Information needed to compile a query (view or content).\n */\nexport interface R3QueryMetadata {\n /**\n * Name of the property on the class to update with query results.\n */\n propertyName: string;\n\n /**\n * Whether to read only the first matching result, or an array of results.\n */\n first: boolean;\n\n /**\n * Either an expression representing a type or `InjectionToken` for the query\n * predicate, or a set of string selectors.\n */\n predicate: MaybeForwardRefExpression|string[];\n\n /**\n * Whether to include only direct children or all descendants.\n */\n descendants: boolean;\n\n /**\n * If the `QueryList` should fire change event only if actual change to query was computed (vs old\n * behavior where the change was fired whenever the query was recomputed, even if the recomputed\n * query resulted in the same list.)\n */\n emitDistinctChangesOnly: boolean;\n\n /**\n * An expression representing a type to read from each matched node, or null if the default value\n * for a given node is to be returned.\n */\n read: o.Expression|null;\n\n /**\n * Whether or not this query should collect only static results.\n *\n * If static is true, the query's results will be set on the component after nodes are created,\n * but before change detection runs. This means that any results that relied upon change detection\n * to run (e.g. results inside *ngIf or *ngFor views) will not be collected. Query results are\n * available in the ngOnInit hook.\n *\n * If static is false, the query's results will be set on the component after change detection\n * runs. This means that the query results can contain nodes inside *ngIf or *ngFor views, but\n * the results will not be available in the ngOnInit hook (only in the ngAfterContentInit for\n * content hooks and ngAfterViewInit for view hooks).\n */\n static: boolean;\n}\n\n/**\n * Mappings indicating how the class interacts with its\n * host element (host bindings, listeners, etc).\n */\nexport interface R3HostMetadata {\n /**\n * A mapping of attribute binding keys to `o.Expression`s.\n */\n attributes: {[key: string]: o.Expression};\n\n /**\n * A mapping of event binding keys to unparsed expressions.\n */\n listeners: {[key: string]: string};\n\n /**\n * A mapping of property binding keys to unparsed expressions.\n */\n properties: {[key: string]: string};\n\n specialAttributes: {styleAttr?: string; classAttr?: string;};\n}\n\n/**\n * Information needed to compile a host directive for the render3 runtime.\n */\nexport interface R3HostDirectiveMetadata {\n /** An expression representing the host directive class itself. */\n directive: R3Reference;\n\n /** Whether the expression referring to the host directive is a forward reference. */\n isForwardReference: boolean;\n\n /** Inputs from the host directive that will be exposed on the host. */\n inputs: {[publicName: string]: string}|null;\n\n /** Outputs from the host directive that will be exposed on the host. */\n outputs: {[publicName: string]: string}|null;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {SecurityContext} from '../core';\nimport {ParseSourceSpan} from '../parse_util';\n\nexport class ParserError {\n public message: string;\n constructor(\n message: string, public input: string, public errLocation: string, public ctxLocation?: any) {\n this.message = `Parser Error: ${message} ${errLocation} [${input}] in ${ctxLocation}`;\n }\n}\n\nexport class ParseSpan {\n constructor(public start: number, public end: number) {}\n toAbsolute(absoluteOffset: number): AbsoluteSourceSpan {\n return new AbsoluteSourceSpan(absoluteOffset + this.start, absoluteOffset + this.end);\n }\n}\n\nexport abstract class AST {\n constructor(\n public span: ParseSpan,\n /**\n * Absolute location of the expression AST in a source code file.\n */\n public sourceSpan: AbsoluteSourceSpan) {}\n\n abstract visit(visitor: AstVisitor, context?: any): any;\n\n toString(): string {\n return 'AST';\n }\n}\n\nexport abstract class ASTWithName extends AST {\n constructor(\n span: ParseSpan, sourceSpan: AbsoluteSourceSpan, public nameSpan: AbsoluteSourceSpan) {\n super(span, sourceSpan);\n }\n}\n\nexport class EmptyExpr extends AST {\n override visit(visitor: AstVisitor, context: any = null) {\n // do nothing\n }\n}\n\nexport class ImplicitReceiver extends AST {\n override visit(visitor: AstVisitor, context: any = null): any {\n return visitor.visitImplicitReceiver(this, context);\n }\n}\n\n/**\n * Receiver when something is accessed through `this` (e.g. `this.foo`). Note that this class\n * inherits from `ImplicitReceiver`, because accessing something through `this` is treated the\n * same as accessing it implicitly inside of an Angular template (e.g. `[attr.title]=\"this.title\"`\n * is the same as `[attr.title]=\"title\"`.). Inheriting allows for the `this` accesses to be treated\n * the same as implicit ones, except for a couple of exceptions like `$event` and `$any`.\n * TODO: we should find a way for this class not to extend from `ImplicitReceiver` in the future.\n */\nexport class ThisReceiver extends ImplicitReceiver {\n override visit(visitor: AstVisitor, context: any = null): any {\n return visitor.visitThisReceiver?.(this, context);\n }\n}\n\n/**\n * Multiple expressions separated by a semicolon.\n */\nexport class Chain extends AST {\n constructor(span: ParseSpan, sourceSpan: AbsoluteSourceSpan, public expressions: any[]) {\n super(span, sourceSpan);\n }\n override visit(visitor: AstVisitor, context: any = null): any {\n return visitor.visitChain(this, context);\n }\n}\n\nexport class Conditional extends AST {\n constructor(\n span: ParseSpan, sourceSpan: AbsoluteSourceSpan, public condition: AST, public trueExp: AST,\n public falseExp: AST) {\n super(span, sourceSpan);\n }\n override visit(visitor: AstVisitor, context: any = null): any {\n return visitor.visitConditional(this, context);\n }\n}\n\nexport class PropertyRead extends ASTWithName {\n constructor(\n span: ParseSpan, sourceSpan: AbsoluteSourceSpan, nameSpan: AbsoluteSourceSpan,\n public receiver: AST, public name: string) {\n super(span, sourceSpan, nameSpan);\n }\n override visit(visitor: AstVisitor, context: any = null): any {\n return visitor.visitPropertyRead(this, context);\n }\n}\n\nexport class PropertyWrite extends ASTWithName {\n constructor(\n span: ParseSpan, sourceSpan: AbsoluteSourceSpan, nameSpan: AbsoluteSourceSpan,\n public receiver: AST, public name: string, public value: AST) {\n super(span, sourceSpan, nameSpan);\n }\n override visit(visitor: AstVisitor, context: any = null): any {\n return visitor.visitPropertyWrite(this, context);\n }\n}\n\nexport class SafePropertyRead extends ASTWithName {\n constructor(\n span: ParseSpan, sourceSpan: AbsoluteSourceSpan, nameSpan: AbsoluteSourceSpan,\n public receiver: AST, public name: string) {\n super(span, sourceSpan, nameSpan);\n }\n override visit(visitor: AstVisitor, context: any = null): any {\n return visitor.visitSafePropertyRead(this, context);\n }\n}\n\nexport class KeyedRead extends AST {\n constructor(\n span: ParseSpan, sourceSpan: AbsoluteSourceSpan, public receiver: AST, public key: AST) {\n super(span, sourceSpan);\n }\n override visit(visitor: AstVisitor, context: any = null): any {\n return visitor.visitKeyedRead(this, context);\n }\n}\n\nexport class SafeKeyedRead extends AST {\n constructor(\n span: ParseSpan, sourceSpan: AbsoluteSourceSpan, public receiver: AST, public key: AST) {\n super(span, sourceSpan);\n }\n override visit(visitor: AstVisitor, context: any = null): any {\n return visitor.visitSafeKeyedRead(this, context);\n }\n}\n\nexport class KeyedWrite extends AST {\n constructor(\n span: ParseSpan, sourceSpan: AbsoluteSourceSpan, public receiver: AST, public key: AST,\n public value: AST) {\n super(span, sourceSpan);\n }\n override visit(visitor: AstVisitor, context: any = null): any {\n return visitor.visitKeyedWrite(this, context);\n }\n}\n\nexport class BindingPipe extends ASTWithName {\n constructor(\n span: ParseSpan, sourceSpan: AbsoluteSourceSpan, public exp: AST, public name: string,\n public args: any[], nameSpan: AbsoluteSourceSpan) {\n super(span, sourceSpan, nameSpan);\n }\n override visit(visitor: AstVisitor, context: any = null): any {\n return visitor.visitPipe(this, context);\n }\n}\n\nexport class LiteralPrimitive extends AST {\n constructor(span: ParseSpan, sourceSpan: AbsoluteSourceSpan, public value: any) {\n super(span, sourceSpan);\n }\n override visit(visitor: AstVisitor, context: any = null): any {\n return visitor.visitLiteralPrimitive(this, context);\n }\n}\n\nexport class LiteralArray extends AST {\n constructor(span: ParseSpan, sourceSpan: AbsoluteSourceSpan, public expressions: any[]) {\n super(span, sourceSpan);\n }\n override visit(visitor: AstVisitor, context: any = null): any {\n return visitor.visitLiteralArray(this, context);\n }\n}\n\nexport type LiteralMapKey = {\n key: string; quoted: boolean;\n};\n\nexport class LiteralMap extends AST {\n constructor(\n span: ParseSpan, sourceSpan: AbsoluteSourceSpan, public keys: LiteralMapKey[],\n public values: any[]) {\n super(span, sourceSpan);\n }\n override visit(visitor: AstVisitor, context: any = null): any {\n return visitor.visitLiteralMap(this, context);\n }\n}\n\nexport class Interpolation extends AST {\n constructor(\n span: ParseSpan, sourceSpan: AbsoluteSourceSpan, public strings: string[],\n public expressions: AST[]) {\n super(span, sourceSpan);\n }\n override visit(visitor: AstVisitor, context: any = null): any {\n return visitor.visitInterpolation(this, context);\n }\n}\n\nexport class Binary extends AST {\n constructor(\n span: ParseSpan, sourceSpan: AbsoluteSourceSpan, public operation: string, public left: AST,\n public right: AST) {\n super(span, sourceSpan);\n }\n override visit(visitor: AstVisitor, context: any = null): any {\n return visitor.visitBinary(this, context);\n }\n}\n\n/**\n * For backwards compatibility reasons, `Unary` inherits from `Binary` and mimics the binary AST\n * node that was originally used. This inheritance relation can be deleted in some future major,\n * after consumers have been given a chance to fully support Unary.\n */\nexport class Unary extends Binary {\n // Redeclare the properties that are inherited from `Binary` as `never`, as consumers should not\n // depend on these fields when operating on `Unary`.\n override left: never = null as never;\n override right: never = null as never;\n override operation: never = null as never;\n\n /**\n * Creates a unary minus expression \"-x\", represented as `Binary` using \"0 - x\".\n */\n static createMinus(span: ParseSpan, sourceSpan: AbsoluteSourceSpan, expr: AST): Unary {\n return new Unary(\n span, sourceSpan, '-', expr, '-', new LiteralPrimitive(span, sourceSpan, 0), expr);\n }\n\n /**\n * Creates a unary plus expression \"+x\", represented as `Binary` using \"x - 0\".\n */\n static createPlus(span: ParseSpan, sourceSpan: AbsoluteSourceSpan, expr: AST): Unary {\n return new Unary(\n span, sourceSpan, '+', expr, '-', expr, new LiteralPrimitive(span, sourceSpan, 0));\n }\n\n /**\n * During the deprecation period this constructor is private, to avoid consumers from creating\n * a `Unary` with the fallback properties for `Binary`.\n */\n private constructor(\n span: ParseSpan, sourceSpan: AbsoluteSourceSpan, public operator: string, public expr: AST,\n binaryOp: string, binaryLeft: AST, binaryRight: AST) {\n super(span, sourceSpan, binaryOp, binaryLeft, binaryRight);\n }\n\n override visit(visitor: AstVisitor, context: any = null): any {\n if (visitor.visitUnary !== undefined) {\n return visitor.visitUnary(this, context);\n }\n return visitor.visitBinary(this, context);\n }\n}\n\nexport class PrefixNot extends AST {\n constructor(span: ParseSpan, sourceSpan: AbsoluteSourceSpan, public expression: AST) {\n super(span, sourceSpan);\n }\n override visit(visitor: AstVisitor, context: any = null): any {\n return visitor.visitPrefixNot(this, context);\n }\n}\n\nexport class NonNullAssert extends AST {\n constructor(span: ParseSpan, sourceSpan: AbsoluteSourceSpan, public expression: AST) {\n super(span, sourceSpan);\n }\n override visit(visitor: AstVisitor, context: any = null): any {\n return visitor.visitNonNullAssert(this, context);\n }\n}\n\nexport class Call extends AST {\n constructor(\n span: ParseSpan, sourceSpan: AbsoluteSourceSpan, public receiver: AST, public args: AST[],\n public argumentSpan: AbsoluteSourceSpan) {\n super(span, sourceSpan);\n }\n override visit(visitor: AstVisitor, context: any = null): any {\n return visitor.visitCall(this, context);\n }\n}\n\nexport class SafeCall extends AST {\n constructor(\n span: ParseSpan, sourceSpan: AbsoluteSourceSpan, public receiver: AST, public args: AST[],\n public argumentSpan: AbsoluteSourceSpan) {\n super(span, sourceSpan);\n }\n override visit(visitor: AstVisitor, context: any = null): any {\n return visitor.visitSafeCall(this, context);\n }\n}\n\n\n/**\n * Records the absolute position of a text span in a source file, where `start` and `end` are the\n * starting and ending byte offsets, respectively, of the text span in a source file.\n */\nexport class AbsoluteSourceSpan {\n constructor(public readonly start: number, public readonly end: number) {}\n}\n\nexport class ASTWithSource extends AST {\n constructor(\n public ast: AST, public source: string|null, public location: string, absoluteOffset: number,\n public errors: ParserError[]) {\n super(\n new ParseSpan(0, source === null ? 0 : source.length),\n new AbsoluteSourceSpan(\n absoluteOffset, source === null ? absoluteOffset : absoluteOffset + source.length));\n }\n override visit(visitor: AstVisitor, context: any = null): any {\n if (visitor.visitASTWithSource) {\n return visitor.visitASTWithSource(this, context);\n }\n return this.ast.visit(visitor, context);\n }\n override toString(): string {\n return `${this.source} in ${this.location}`;\n }\n}\n\n/**\n * TemplateBinding refers to a particular key-value pair in a microsyntax\n * expression. A few examples are:\n *\n * |---------------------|--------------|---------|--------------|\n * | expression | key | value | binding type |\n * |---------------------|--------------|---------|--------------|\n * | 1. let item | item | null | variable |\n * | 2. of items | ngForOf | items | expression |\n * | 3. let x = y | x | y | variable |\n * | 4. index as i | i | index | variable |\n * | 5. trackBy: func | ngForTrackBy | func | expression |\n * | 6. *ngIf=\"cond\" | ngIf | cond | expression |\n * |---------------------|--------------|---------|--------------|\n *\n * (6) is a notable exception because it is a binding from the template key in\n * the LHS of a HTML attribute to the expression in the RHS. All other bindings\n * in the example above are derived solely from the RHS.\n */\nexport type TemplateBinding = VariableBinding|ExpressionBinding;\n\nexport class VariableBinding {\n /**\n * @param sourceSpan entire span of the binding.\n * @param key name of the LHS along with its span.\n * @param value optional value for the RHS along with its span.\n */\n constructor(\n public readonly sourceSpan: AbsoluteSourceSpan,\n public readonly key: TemplateBindingIdentifier,\n public readonly value: TemplateBindingIdentifier|null) {}\n}\n\nexport class ExpressionBinding {\n /**\n * @param sourceSpan entire span of the binding.\n * @param key binding name, like ngForOf, ngForTrackBy, ngIf, along with its\n * span. Note that the length of the span may not be the same as\n * `key.source.length`. For example,\n * 1. key.source = ngFor, key.span is for \"ngFor\"\n * 2. key.source = ngForOf, key.span is for \"of\"\n * 3. key.source = ngForTrackBy, key.span is for \"trackBy\"\n * @param value optional expression for the RHS.\n */\n constructor(\n public readonly sourceSpan: AbsoluteSourceSpan,\n public readonly key: TemplateBindingIdentifier, public readonly value: ASTWithSource|null) {}\n}\n\nexport interface TemplateBindingIdentifier {\n source: string;\n span: AbsoluteSourceSpan;\n}\n\nexport interface AstVisitor {\n /**\n * The `visitUnary` method is declared as optional for backwards compatibility. In an upcoming\n * major release, this method will be made required.\n */\n visitUnary?(ast: Unary, context: any): any;\n visitBinary(ast: Binary, context: any): any;\n visitChain(ast: Chain, context: any): any;\n visitConditional(ast: Conditional, context: any): any;\n /**\n * The `visitThisReceiver` method is declared as optional for backwards compatibility.\n * In an upcoming major release, this method will be made required.\n */\n visitThisReceiver?(ast: ThisReceiver, context: any): any;\n visitImplicitReceiver(ast: ImplicitReceiver, context: any): any;\n visitInterpolation(ast: Interpolation, context: any): any;\n visitKeyedRead(ast: KeyedRead, context: any): any;\n visitKeyedWrite(ast: KeyedWrite, context: any): any;\n visitLiteralArray(ast: LiteralArray, context: any): any;\n visitLiteralMap(ast: LiteralMap, context: any): any;\n visitLiteralPrimitive(ast: LiteralPrimitive, context: any): any;\n visitPipe(ast: BindingPipe, context: any): any;\n visitPrefixNot(ast: PrefixNot, context: any): any;\n visitNonNullAssert(ast: NonNullAssert, context: any): any;\n visitPropertyRead(ast: PropertyRead, context: any): any;\n visitPropertyWrite(ast: PropertyWrite, context: any): any;\n visitSafePropertyRead(ast: SafePropertyRead, context: any): any;\n visitSafeKeyedRead(ast: SafeKeyedRead, context: any): any;\n visitCall(ast: Call, context: any): any;\n visitSafeCall(ast: SafeCall, context: any): any;\n visitASTWithSource?(ast: ASTWithSource, context: any): any;\n /**\n * This function is optionally defined to allow classes that implement this\n * interface to selectively decide if the specified `ast` should be visited.\n * @param ast node to visit\n * @param context context that gets passed to the node and all its children\n */\n visit?(ast: AST, context?: any): any;\n}\n\nexport class RecursiveAstVisitor implements AstVisitor {\n visit(ast: AST, context?: any): any {\n // The default implementation just visits every node.\n // Classes that extend RecursiveAstVisitor should override this function\n // to selectively visit the specified node.\n ast.visit(this, context);\n }\n visitUnary(ast: Unary, context: any): any {\n this.visit(ast.expr, context);\n }\n visitBinary(ast: Binary, context: any): any {\n this.visit(ast.left, context);\n this.visit(ast.right, context);\n }\n visitChain(ast: Chain, context: any): any {\n this.visitAll(ast.expressions, context);\n }\n visitConditional(ast: Conditional, context: any): any {\n this.visit(ast.condition, context);\n this.visit(ast.trueExp, context);\n this.visit(ast.falseExp, context);\n }\n visitPipe(ast: BindingPipe, context: any): any {\n this.visit(ast.exp, context);\n this.visitAll(ast.args, context);\n }\n visitImplicitReceiver(ast: ThisReceiver, context: any): any {}\n visitThisReceiver(ast: ThisReceiver, context: any): any {}\n visitInterpolation(ast: Interpolation, context: any): any {\n this.visitAll(ast.expressions, context);\n }\n visitKeyedRead(ast: KeyedRead, context: any): any {\n this.visit(ast.receiver, context);\n this.visit(ast.key, context);\n }\n visitKeyedWrite(ast: KeyedWrite, context: any): any {\n this.visit(ast.receiver, context);\n this.visit(ast.key, context);\n this.visit(ast.value, context);\n }\n visitLiteralArray(ast: LiteralArray, context: any): any {\n this.visitAll(ast.expressions, context);\n }\n visitLiteralMap(ast: LiteralMap, context: any): any {\n this.visitAll(ast.values, context);\n }\n visitLiteralPrimitive(ast: LiteralPrimitive, context: any): any {}\n visitPrefixNot(ast: PrefixNot, context: any): any {\n this.visit(ast.expression, context);\n }\n visitNonNullAssert(ast: NonNullAssert, context: any): any {\n this.visit(ast.expression, context);\n }\n visitPropertyRead(ast: PropertyRead, context: any): any {\n this.visit(ast.receiver, context);\n }\n visitPropertyWrite(ast: PropertyWrite, context: any): any {\n this.visit(ast.receiver, context);\n this.visit(ast.value, context);\n }\n visitSafePropertyRead(ast: SafePropertyRead, context: any): any {\n this.visit(ast.receiver, context);\n }\n visitSafeKeyedRead(ast: SafeKeyedRead, context: any): any {\n this.visit(ast.receiver, context);\n this.visit(ast.key, context);\n }\n visitCall(ast: Call, context: any): any {\n this.visit(ast.receiver, context);\n this.visitAll(ast.args, context);\n }\n visitSafeCall(ast: SafeCall, context: any): any {\n this.visit(ast.receiver, context);\n this.visitAll(ast.args, context);\n }\n // This is not part of the AstVisitor interface, just a helper method\n visitAll(asts: AST[], context: any): any {\n for (const ast of asts) {\n this.visit(ast, context);\n }\n }\n}\n\nexport class AstTransformer implements AstVisitor {\n visitImplicitReceiver(ast: ImplicitReceiver, context: any): AST {\n return ast;\n }\n\n visitThisReceiver(ast: ThisReceiver, context: any): AST {\n return ast;\n }\n\n visitInterpolation(ast: Interpolation, context: any): AST {\n return new Interpolation(ast.span, ast.sourceSpan, ast.strings, this.visitAll(ast.expressions));\n }\n\n visitLiteralPrimitive(ast: LiteralPrimitive, context: any): AST {\n return new LiteralPrimitive(ast.span, ast.sourceSpan, ast.value);\n }\n\n visitPropertyRead(ast: PropertyRead, context: any): AST {\n return new PropertyRead(\n ast.span, ast.sourceSpan, ast.nameSpan, ast.receiver.visit(this), ast.name);\n }\n\n visitPropertyWrite(ast: PropertyWrite, context: any): AST {\n return new PropertyWrite(\n ast.span, ast.sourceSpan, ast.nameSpan, ast.receiver.visit(this), ast.name,\n ast.value.visit(this));\n }\n\n visitSafePropertyRead(ast: SafePropertyRead, context: any): AST {\n return new SafePropertyRead(\n ast.span, ast.sourceSpan, ast.nameSpan, ast.receiver.visit(this), ast.name);\n }\n\n visitLiteralArray(ast: LiteralArray, context: any): AST {\n return new LiteralArray(ast.span, ast.sourceSpan, this.visitAll(ast.expressions));\n }\n\n visitLiteralMap(ast: LiteralMap, context: any): AST {\n return new LiteralMap(ast.span, ast.sourceSpan, ast.keys, this.visitAll(ast.values));\n }\n\n visitUnary(ast: Unary, context: any): AST {\n switch (ast.operator) {\n case '+':\n return Unary.createPlus(ast.span, ast.sourceSpan, ast.expr.visit(this));\n case '-':\n return Unary.createMinus(ast.span, ast.sourceSpan, ast.expr.visit(this));\n default:\n throw new Error(`Unknown unary operator ${ast.operator}`);\n }\n }\n\n visitBinary(ast: Binary, context: any): AST {\n return new Binary(\n ast.span, ast.sourceSpan, ast.operation, ast.left.visit(this), ast.right.visit(this));\n }\n\n visitPrefixNot(ast: PrefixNot, context: any): AST {\n return new PrefixNot(ast.span, ast.sourceSpan, ast.expression.visit(this));\n }\n\n visitNonNullAssert(ast: NonNullAssert, context: any): AST {\n return new NonNullAssert(ast.span, ast.sourceSpan, ast.expression.visit(this));\n }\n\n visitConditional(ast: Conditional, context: any): AST {\n return new Conditional(\n ast.span, ast.sourceSpan, ast.condition.visit(this), ast.trueExp.visit(this),\n ast.falseExp.visit(this));\n }\n\n visitPipe(ast: BindingPipe, context: any): AST {\n return new BindingPipe(\n ast.span, ast.sourceSpan, ast.exp.visit(this), ast.name, this.visitAll(ast.args),\n ast.nameSpan);\n }\n\n visitKeyedRead(ast: KeyedRead, context: any): AST {\n return new KeyedRead(ast.span, ast.sourceSpan, ast.receiver.visit(this), ast.key.visit(this));\n }\n\n visitKeyedWrite(ast: KeyedWrite, context: any): AST {\n return new KeyedWrite(\n ast.span, ast.sourceSpan, ast.receiver.visit(this), ast.key.visit(this),\n ast.value.visit(this));\n }\n\n visitCall(ast: Call, context: any): AST {\n return new Call(\n ast.span, ast.sourceSpan, ast.receiver.visit(this), this.visitAll(ast.args),\n ast.argumentSpan);\n }\n\n visitSafeCall(ast: SafeCall, context: any): AST {\n return new SafeCall(\n ast.span, ast.sourceSpan, ast.receiver.visit(this), this.visitAll(ast.args),\n ast.argumentSpan);\n }\n\n visitAll(asts: any[]): any[] {\n const res = [];\n for (let i = 0; i < asts.length; ++i) {\n res[i] = asts[i].visit(this);\n }\n return res;\n }\n\n visitChain(ast: Chain, context: any): AST {\n return new Chain(ast.span, ast.sourceSpan, this.visitAll(ast.expressions));\n }\n\n visitSafeKeyedRead(ast: SafeKeyedRead, context: any): AST {\n return new SafeKeyedRead(\n ast.span, ast.sourceSpan, ast.receiver.visit(this), ast.key.visit(this));\n }\n}\n\n// A transformer that only creates new nodes if the transformer makes a change or\n// a change is made a child node.\nexport class AstMemoryEfficientTransformer implements AstVisitor {\n visitImplicitReceiver(ast: ImplicitReceiver, context: any): AST {\n return ast;\n }\n\n visitThisReceiver(ast: ThisReceiver, context: any): AST {\n return ast;\n }\n\n visitInterpolation(ast: Interpolation, context: any): Interpolation {\n const expressions = this.visitAll(ast.expressions);\n if (expressions !== ast.expressions)\n return new Interpolation(ast.span, ast.sourceSpan, ast.strings, expressions);\n return ast;\n }\n\n visitLiteralPrimitive(ast: LiteralPrimitive, context: any): AST {\n return ast;\n }\n\n visitPropertyRead(ast: PropertyRead, context: any): AST {\n const receiver = ast.receiver.visit(this);\n if (receiver !== ast.receiver) {\n return new PropertyRead(ast.span, ast.sourceSpan, ast.nameSpan, receiver, ast.name);\n }\n return ast;\n }\n\n visitPropertyWrite(ast: PropertyWrite, context: any): AST {\n const receiver = ast.receiver.visit(this);\n const value = ast.value.visit(this);\n if (receiver !== ast.receiver || value !== ast.value) {\n return new PropertyWrite(ast.span, ast.sourceSpan, ast.nameSpan, receiver, ast.name, value);\n }\n return ast;\n }\n\n visitSafePropertyRead(ast: SafePropertyRead, context: any): AST {\n const receiver = ast.receiver.visit(this);\n if (receiver !== ast.receiver) {\n return new SafePropertyRead(ast.span, ast.sourceSpan, ast.nameSpan, receiver, ast.name);\n }\n return ast;\n }\n\n visitLiteralArray(ast: LiteralArray, context: any): AST {\n const expressions = this.visitAll(ast.expressions);\n if (expressions !== ast.expressions) {\n return new LiteralArray(ast.span, ast.sourceSpan, expressions);\n }\n return ast;\n }\n\n visitLiteralMap(ast: LiteralMap, context: any): AST {\n const values = this.visitAll(ast.values);\n if (values !== ast.values) {\n return new LiteralMap(ast.span, ast.sourceSpan, ast.keys, values);\n }\n return ast;\n }\n\n visitUnary(ast: Unary, context: any): AST {\n const expr = ast.expr.visit(this);\n if (expr !== ast.expr) {\n switch (ast.operator) {\n case '+':\n return Unary.createPlus(ast.span, ast.sourceSpan, expr);\n case '-':\n return Unary.createMinus(ast.span, ast.sourceSpan, expr);\n default:\n throw new Error(`Unknown unary operator ${ast.operator}`);\n }\n }\n return ast;\n }\n\n visitBinary(ast: Binary, context: any): AST {\n const left = ast.left.visit(this);\n const right = ast.right.visit(this);\n if (left !== ast.left || right !== ast.right) {\n return new Binary(ast.span, ast.sourceSpan, ast.operation, left, right);\n }\n return ast;\n }\n\n visitPrefixNot(ast: PrefixNot, context: any): AST {\n const expression = ast.expression.visit(this);\n if (expression !== ast.expression) {\n return new PrefixNot(ast.span, ast.sourceSpan, expression);\n }\n return ast;\n }\n\n visitNonNullAssert(ast: NonNullAssert, context: any): AST {\n const expression = ast.expression.visit(this);\n if (expression !== ast.expression) {\n return new NonNullAssert(ast.span, ast.sourceSpan, expression);\n }\n return ast;\n }\n\n visitConditional(ast: Conditional, context: any): AST {\n const condition = ast.condition.visit(this);\n const trueExp = ast.trueExp.visit(this);\n const falseExp = ast.falseExp.visit(this);\n if (condition !== ast.condition || trueExp !== ast.trueExp || falseExp !== ast.falseExp) {\n return new Conditional(ast.span, ast.sourceSpan, condition, trueExp, falseExp);\n }\n return ast;\n }\n\n visitPipe(ast: BindingPipe, context: any): AST {\n const exp = ast.exp.visit(this);\n const args = this.visitAll(ast.args);\n if (exp !== ast.exp || args !== ast.args) {\n return new BindingPipe(ast.span, ast.sourceSpan, exp, ast.name, args, ast.nameSpan);\n }\n return ast;\n }\n\n visitKeyedRead(ast: KeyedRead, context: any): AST {\n const obj = ast.receiver.visit(this);\n const key = ast.key.visit(this);\n if (obj !== ast.receiver || key !== ast.key) {\n return new KeyedRead(ast.span, ast.sourceSpan, obj, key);\n }\n return ast;\n }\n\n visitKeyedWrite(ast: KeyedWrite, context: any): AST {\n const obj = ast.receiver.visit(this);\n const key = ast.key.visit(this);\n const value = ast.value.visit(this);\n if (obj !== ast.receiver || key !== ast.key || value !== ast.value) {\n return new KeyedWrite(ast.span, ast.sourceSpan, obj, key, value);\n }\n return ast;\n }\n\n visitAll(asts: any[]): any[] {\n const res = [];\n let modified = false;\n for (let i = 0; i < asts.length; ++i) {\n const original = asts[i];\n const value = original.visit(this);\n res[i] = value;\n modified = modified || value !== original;\n }\n return modified ? res : asts;\n }\n\n visitChain(ast: Chain, context: any): AST {\n const expressions = this.visitAll(ast.expressions);\n if (expressions !== ast.expressions) {\n return new Chain(ast.span, ast.sourceSpan, expressions);\n }\n return ast;\n }\n\n\n visitCall(ast: Call, context: any): AST {\n const receiver = ast.receiver.visit(this);\n const args = this.visitAll(ast.args);\n if (receiver !== ast.receiver || args !== ast.args) {\n return new Call(ast.span, ast.sourceSpan, receiver, args, ast.argumentSpan);\n }\n return ast;\n }\n\n visitSafeCall(ast: SafeCall, context: any): AST {\n const receiver = ast.receiver.visit(this);\n const args = this.visitAll(ast.args);\n if (receiver !== ast.receiver || args !== ast.args) {\n return new SafeCall(ast.span, ast.sourceSpan, receiver, args, ast.argumentSpan);\n }\n return ast;\n }\n\n visitSafeKeyedRead(ast: SafeKeyedRead, context: any): AST {\n const obj = ast.receiver.visit(this);\n const key = ast.key.visit(this);\n if (obj !== ast.receiver || key !== ast.key) {\n return new SafeKeyedRead(ast.span, ast.sourceSpan, obj, key);\n }\n return ast;\n }\n}\n\n// Bindings\n\nexport class ParsedProperty {\n public readonly isLiteral: boolean;\n public readonly isAnimation: boolean;\n\n constructor(\n public name: string, public expression: ASTWithSource, public type: ParsedPropertyType,\n public sourceSpan: ParseSourceSpan, readonly keySpan: ParseSourceSpan,\n public valueSpan: ParseSourceSpan|undefined) {\n this.isLiteral = this.type === ParsedPropertyType.LITERAL_ATTR;\n this.isAnimation = this.type === ParsedPropertyType.ANIMATION;\n }\n}\n\nexport enum ParsedPropertyType {\n DEFAULT,\n LITERAL_ATTR,\n ANIMATION,\n TWO_WAY,\n}\n\nexport const enum ParsedEventType {\n // DOM or Directive event\n Regular,\n // Animation specific event\n Animation,\n // Event side of a two-way binding (e.g. `[(property)]=\"expression\"`).\n TwoWay,\n}\n\nexport class ParsedEvent {\n // Regular events have a target\n // Animation events have a phase\n constructor(\n public name: string, public targetOrPhase: string, public type: ParsedEventType,\n public handler: ASTWithSource, public sourceSpan: ParseSourceSpan,\n public handlerSpan: ParseSourceSpan, readonly keySpan: ParseSourceSpan) {}\n}\n\n/**\n * ParsedVariable represents a variable declaration in a microsyntax expression.\n */\nexport class ParsedVariable {\n constructor(\n public readonly name: string, public readonly value: string,\n public readonly sourceSpan: ParseSourceSpan, public readonly keySpan: ParseSourceSpan,\n public readonly valueSpan?: ParseSourceSpan) {}\n}\n\nexport const enum BindingType {\n // A regular binding to a property (e.g. `[property]=\"expression\"`).\n Property,\n // A binding to an element attribute (e.g. `[attr.name]=\"expression\"`).\n Attribute,\n // A binding to a CSS class (e.g. `[class.name]=\"condition\"`).\n Class,\n // A binding to a style rule (e.g. `[style.rule]=\"expression\"`).\n Style,\n // A binding to an animation reference (e.g. `[animate.key]=\"expression\"`).\n Animation,\n // Property side of a two-way binding (e.g. `[(property)]=\"expression\"`).\n TwoWay,\n}\n\nexport class BoundElementProperty {\n constructor(\n public name: string, public type: BindingType, public securityContext: SecurityContext,\n public value: ASTWithSource, public unit: string|null, public sourceSpan: ParseSourceSpan,\n readonly keySpan: ParseSourceSpan|undefined, public valueSpan: ParseSourceSpan|undefined) {}\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport * as cdAst from '../expression_parser/ast';\nimport * as o from '../output/output_ast';\nimport {ParseSourceSpan} from '../parse_util';\n\nexport class EventHandlerVars {\n static event = o.variable('$event');\n}\n\nexport interface LocalResolver {\n getLocal(name: string): o.Expression|null;\n notifyImplicitReceiverUse(): void;\n globals?: Set;\n maybeRestoreView(): void;\n}\n\n/**\n * Converts the given expression AST into an executable output AST, assuming the expression is\n * used in an action binding (e.g. an event handler).\n */\nexport function convertActionBinding(\n localResolver: LocalResolver|null, implicitReceiver: o.Expression, action: cdAst.AST,\n bindingId: string, baseSourceSpan?: ParseSourceSpan, implicitReceiverAccesses?: Set,\n globals?: Set): o.Statement[] {\n if (!localResolver) {\n localResolver = new DefaultLocalResolver(globals);\n }\n const actionWithoutBuiltins = convertPropertyBindingBuiltins(\n {\n createLiteralArrayConverter: (argCount: number) => {\n // Note: no caching for literal arrays in actions.\n return (args: o.Expression[]) => o.literalArr(args);\n },\n createLiteralMapConverter: (keys: {key: string, quoted: boolean}[]) => {\n // Note: no caching for literal maps in actions.\n return (values: o.Expression[]) => {\n const entries = keys.map((k, i) => ({\n key: k.key,\n value: values[i],\n quoted: k.quoted,\n }));\n return o.literalMap(entries);\n };\n },\n createPipeConverter: (name: string) => {\n throw new Error(`Illegal State: Actions are not allowed to contain pipes. Pipe: ${name}`);\n }\n },\n action);\n\n const visitor = new _AstToIrVisitor(\n localResolver, implicitReceiver, bindingId, /* supportsInterpolation */ false, baseSourceSpan,\n implicitReceiverAccesses);\n const actionStmts: o.Statement[] = [];\n flattenStatements(actionWithoutBuiltins.visit(visitor, _Mode.Statement), actionStmts);\n prependTemporaryDecls(visitor.temporaryCount, bindingId, actionStmts);\n\n if (visitor.usesImplicitReceiver) {\n localResolver.notifyImplicitReceiverUse();\n }\n\n const lastIndex = actionStmts.length - 1;\n if (lastIndex >= 0) {\n const lastStatement = actionStmts[lastIndex];\n // Ensure that the value of the last expression statement is returned\n if (lastStatement instanceof o.ExpressionStatement) {\n actionStmts[lastIndex] = new o.ReturnStatement(lastStatement.expr);\n }\n }\n return actionStmts;\n}\n\nexport interface BuiltinConverter {\n (args: o.Expression[]): o.Expression;\n}\n\nexport interface BuiltinConverterFactory {\n createLiteralArrayConverter(argCount: number): BuiltinConverter;\n createLiteralMapConverter(keys: {key: string, quoted: boolean}[]): BuiltinConverter;\n createPipeConverter(name: string, argCount: number): BuiltinConverter;\n}\n\nfunction convertPropertyBindingBuiltins(\n converterFactory: BuiltinConverterFactory, ast: cdAst.AST): cdAst.AST {\n return convertBuiltins(converterFactory, ast);\n}\n\nexport class ConvertPropertyBindingResult {\n constructor(public stmts: o.Statement[], public currValExpr: o.Expression) {}\n}\n\n/**\n * Converts the given expression AST into an executable output AST, assuming the expression\n * is used in property binding. The expression has to be preprocessed via\n * `convertPropertyBindingBuiltins`.\n */\nexport function convertPropertyBinding(\n localResolver: LocalResolver|null, implicitReceiver: o.Expression,\n expressionWithoutBuiltins: cdAst.AST, bindingId: string): ConvertPropertyBindingResult {\n if (!localResolver) {\n localResolver = new DefaultLocalResolver();\n }\n const visitor = new _AstToIrVisitor(\n localResolver, implicitReceiver, bindingId, /* supportsInterpolation */ false);\n const outputExpr: o.Expression = expressionWithoutBuiltins.visit(visitor, _Mode.Expression);\n const stmts: o.Statement[] = getStatementsFromVisitor(visitor, bindingId);\n\n if (visitor.usesImplicitReceiver) {\n localResolver.notifyImplicitReceiverUse();\n }\n\n return new ConvertPropertyBindingResult(stmts, outputExpr);\n}\n\n/** Converts an AST to a pure function that may have access to the component scope. */\nexport function convertPureComponentScopeFunction(\n ast: cdAst.AST, localResolver: LocalResolver, implicitReceiver: o.Expression,\n bindingId: string): o.Statement[] {\n const converted = convertPropertyBindingBuiltins(\n {\n createLiteralArrayConverter: () => args => o.literalArr(args),\n createLiteralMapConverter: keys => values => o.literalMap(keys.map((key, index) => {\n return ({\n key: key.key,\n value: values[index],\n quoted: key.quoted,\n });\n })),\n createPipeConverter: () => {\n throw new Error('Illegal State: Pipes are not allowed in this context');\n }\n },\n ast);\n\n const visitor = new _AstToIrVisitor(localResolver, implicitReceiver, bindingId, false);\n const statements: o.Statement[] = [];\n flattenStatements(converted.visit(visitor, _Mode.Statement), statements);\n return statements;\n}\n\n/**\n * Given some expression, such as a binding or interpolation expression, and a context expression to\n * look values up on, visit each facet of the given expression resolving values from the context\n * expression such that a list of arguments can be derived from the found values that can be used as\n * arguments to an external update instruction.\n *\n * @param localResolver The resolver to use to look up expressions by name appropriately\n * @param contextVariableExpression The expression representing the context variable used to create\n * the final argument expressions\n * @param expressionWithArgumentsToExtract The expression to visit to figure out what values need to\n * be resolved and what arguments list to build.\n * @param bindingId A name prefix used to create temporary variable names if they're needed for the\n * arguments generated\n * @returns An array of expressions that can be passed as arguments to instruction expressions like\n * `o.importExpr(R3.propertyInterpolate).callFn(result)`\n */\nexport function convertUpdateArguments(\n localResolver: LocalResolver, contextVariableExpression: o.Expression,\n expressionWithArgumentsToExtract: cdAst.Interpolation, bindingId: string) {\n const visitor = new _AstToIrVisitor(\n localResolver, contextVariableExpression, bindingId, /* supportsInterpolation */ true);\n const outputExpr = visitor.visitInterpolation(expressionWithArgumentsToExtract, _Mode.Expression);\n\n if (visitor.usesImplicitReceiver) {\n localResolver.notifyImplicitReceiverUse();\n }\n\n const stmts = getStatementsFromVisitor(visitor, bindingId);\n const args = outputExpr.args;\n return {stmts, args};\n}\n\nfunction getStatementsFromVisitor(visitor: _AstToIrVisitor, bindingId: string) {\n const stmts: o.Statement[] = [];\n for (let i = 0; i < visitor.temporaryCount; i++) {\n stmts.push(temporaryDeclaration(bindingId, i));\n }\n return stmts;\n}\n\nfunction convertBuiltins(converterFactory: BuiltinConverterFactory, ast: cdAst.AST): cdAst.AST {\n const visitor = new _BuiltinAstConverter(converterFactory);\n return ast.visit(visitor);\n}\n\nfunction temporaryName(bindingId: string, temporaryNumber: number): string {\n return `tmp_${bindingId}_${temporaryNumber}`;\n}\n\nfunction temporaryDeclaration(bindingId: string, temporaryNumber: number): o.Statement {\n return new o.DeclareVarStmt(temporaryName(bindingId, temporaryNumber));\n}\n\nfunction prependTemporaryDecls(\n temporaryCount: number, bindingId: string, statements: o.Statement[]) {\n for (let i = temporaryCount - 1; i >= 0; i--) {\n statements.unshift(temporaryDeclaration(bindingId, i));\n }\n}\n\nenum _Mode {\n Statement,\n Expression\n}\n\nfunction ensureStatementMode(mode: _Mode, ast: cdAst.AST) {\n if (mode !== _Mode.Statement) {\n throw new Error(`Expected a statement, but saw ${ast}`);\n }\n}\n\nfunction ensureExpressionMode(mode: _Mode, ast: cdAst.AST) {\n if (mode !== _Mode.Expression) {\n throw new Error(`Expected an expression, but saw ${ast}`);\n }\n}\n\nfunction convertToStatementIfNeeded(mode: _Mode, expr: o.Expression): o.Expression|o.Statement {\n if (mode === _Mode.Statement) {\n return expr.toStmt();\n } else {\n return expr;\n }\n}\n\nclass _BuiltinAstConverter extends cdAst.AstTransformer {\n constructor(private _converterFactory: BuiltinConverterFactory) {\n super();\n }\n override visitPipe(ast: cdAst.BindingPipe, context: any): any {\n const args = [ast.exp, ...ast.args].map(ast => ast.visit(this, context));\n return new BuiltinFunctionCall(\n ast.span, ast.sourceSpan, args,\n this._converterFactory.createPipeConverter(ast.name, args.length));\n }\n override visitLiteralArray(ast: cdAst.LiteralArray, context: any): any {\n const args = ast.expressions.map(ast => ast.visit(this, context));\n return new BuiltinFunctionCall(\n ast.span, ast.sourceSpan, args,\n this._converterFactory.createLiteralArrayConverter(ast.expressions.length));\n }\n override visitLiteralMap(ast: cdAst.LiteralMap, context: any): any {\n const args = ast.values.map(ast => ast.visit(this, context));\n\n return new BuiltinFunctionCall(\n ast.span, ast.sourceSpan, args, this._converterFactory.createLiteralMapConverter(ast.keys));\n }\n}\n\nclass _AstToIrVisitor implements cdAst.AstVisitor {\n private _nodeMap = new Map();\n private _resultMap = new Map();\n private _currentTemporary: number = 0;\n public temporaryCount: number = 0;\n public usesImplicitReceiver: boolean = false;\n\n constructor(\n private _localResolver: LocalResolver, private _implicitReceiver: o.Expression,\n private bindingId: string, private supportsInterpolation: boolean,\n private baseSourceSpan?: ParseSourceSpan, private implicitReceiverAccesses?: Set) {}\n\n visitUnary(ast: cdAst.Unary, mode: _Mode): any {\n let op: o.UnaryOperator;\n switch (ast.operator) {\n case '+':\n op = o.UnaryOperator.Plus;\n break;\n case '-':\n op = o.UnaryOperator.Minus;\n break;\n default:\n throw new Error(`Unsupported operator ${ast.operator}`);\n }\n\n return convertToStatementIfNeeded(\n mode,\n new o.UnaryOperatorExpr(\n op, this._visit(ast.expr, _Mode.Expression), undefined,\n this.convertSourceSpan(ast.span)));\n }\n\n visitBinary(ast: cdAst.Binary, mode: _Mode): any {\n let op: o.BinaryOperator;\n switch (ast.operation) {\n case '+':\n op = o.BinaryOperator.Plus;\n break;\n case '-':\n op = o.BinaryOperator.Minus;\n break;\n case '*':\n op = o.BinaryOperator.Multiply;\n break;\n case '/':\n op = o.BinaryOperator.Divide;\n break;\n case '%':\n op = o.BinaryOperator.Modulo;\n break;\n case '&&':\n op = o.BinaryOperator.And;\n break;\n case '||':\n op = o.BinaryOperator.Or;\n break;\n case '==':\n op = o.BinaryOperator.Equals;\n break;\n case '!=':\n op = o.BinaryOperator.NotEquals;\n break;\n case '===':\n op = o.BinaryOperator.Identical;\n break;\n case '!==':\n op = o.BinaryOperator.NotIdentical;\n break;\n case '<':\n op = o.BinaryOperator.Lower;\n break;\n case '>':\n op = o.BinaryOperator.Bigger;\n break;\n case '<=':\n op = o.BinaryOperator.LowerEquals;\n break;\n case '>=':\n op = o.BinaryOperator.BiggerEquals;\n break;\n case '??':\n return this.convertNullishCoalesce(ast, mode);\n default:\n throw new Error(`Unsupported operation ${ast.operation}`);\n }\n\n return convertToStatementIfNeeded(\n mode,\n new o.BinaryOperatorExpr(\n op, this._visit(ast.left, _Mode.Expression), this._visit(ast.right, _Mode.Expression),\n undefined, this.convertSourceSpan(ast.span)));\n }\n\n visitChain(ast: cdAst.Chain, mode: _Mode): any {\n ensureStatementMode(mode, ast);\n return this.visitAll(ast.expressions, mode);\n }\n\n visitConditional(ast: cdAst.Conditional, mode: _Mode): any {\n const value: o.Expression = this._visit(ast.condition, _Mode.Expression);\n return convertToStatementIfNeeded(\n mode,\n value.conditional(\n this._visit(ast.trueExp, _Mode.Expression), this._visit(ast.falseExp, _Mode.Expression),\n this.convertSourceSpan(ast.span)));\n }\n\n visitPipe(ast: cdAst.BindingPipe, mode: _Mode): any {\n throw new Error(\n `Illegal state: Pipes should have been converted into functions. Pipe: ${ast.name}`);\n }\n\n visitImplicitReceiver(ast: cdAst.ImplicitReceiver, mode: _Mode): any {\n ensureExpressionMode(mode, ast);\n this.usesImplicitReceiver = true;\n return this._implicitReceiver;\n }\n\n visitThisReceiver(ast: cdAst.ThisReceiver, mode: _Mode): any {\n return this.visitImplicitReceiver(ast, mode);\n }\n\n visitInterpolation(ast: cdAst.Interpolation, mode: _Mode): InterpolationExpression {\n if (!this.supportsInterpolation) {\n throw new Error('Unexpected interpolation');\n }\n\n ensureExpressionMode(mode, ast);\n let args: o.Expression[] = [];\n for (let i = 0; i < ast.strings.length - 1; i++) {\n args.push(o.literal(ast.strings[i]));\n args.push(this._visit(ast.expressions[i], _Mode.Expression));\n }\n args.push(o.literal(ast.strings[ast.strings.length - 1]));\n\n // If we're dealing with an interpolation of 1 value with an empty prefix and suffix, reduce the\n // args returned to just the value, because we're going to pass it to a special instruction.\n const strings = ast.strings;\n if (strings.length === 2 && strings[0] === '' && strings[1] === '') {\n // Single argument interpolate instructions.\n args = [args[1]];\n } else if (ast.expressions.length >= 9) {\n // 9 or more arguments must be passed to the `interpolateV`-style instructions, which accept\n // an array of arguments\n args = [o.literalArr(args)];\n }\n\n return new InterpolationExpression(args);\n }\n\n visitKeyedRead(ast: cdAst.KeyedRead, mode: _Mode): any {\n const leftMostSafe = this.leftMostSafeNode(ast);\n if (leftMostSafe) {\n return this.convertSafeAccess(ast, leftMostSafe, mode);\n } else {\n return convertToStatementIfNeeded(\n mode,\n this._visit(ast.receiver, _Mode.Expression).key(this._visit(ast.key, _Mode.Expression)));\n }\n }\n\n visitKeyedWrite(ast: cdAst.KeyedWrite, mode: _Mode): any {\n const obj: o.Expression = this._visit(ast.receiver, _Mode.Expression);\n const key: o.Expression = this._visit(ast.key, _Mode.Expression);\n const value: o.Expression = this._visit(ast.value, _Mode.Expression);\n\n if (obj === this._implicitReceiver) {\n this._localResolver.maybeRestoreView();\n }\n\n return convertToStatementIfNeeded(mode, obj.key(key).set(value));\n }\n\n visitLiteralArray(ast: cdAst.LiteralArray, mode: _Mode): any {\n throw new Error(`Illegal State: literal arrays should have been converted into functions`);\n }\n\n visitLiteralMap(ast: cdAst.LiteralMap, mode: _Mode): any {\n throw new Error(`Illegal State: literal maps should have been converted into functions`);\n }\n\n visitLiteralPrimitive(ast: cdAst.LiteralPrimitive, mode: _Mode): any {\n // For literal values of null, undefined, true, or false allow type interference\n // to infer the type.\n const type =\n ast.value === null || ast.value === undefined || ast.value === true || ast.value === true ?\n o.INFERRED_TYPE :\n undefined;\n return convertToStatementIfNeeded(\n mode, o.literal(ast.value, type, this.convertSourceSpan(ast.span)));\n }\n\n private _getLocal(name: string, receiver: cdAst.AST): o.Expression|null {\n if (this._localResolver.globals?.has(name) && receiver instanceof cdAst.ThisReceiver) {\n return null;\n }\n\n return this._localResolver.getLocal(name);\n }\n\n visitPrefixNot(ast: cdAst.PrefixNot, mode: _Mode): any {\n return convertToStatementIfNeeded(mode, o.not(this._visit(ast.expression, _Mode.Expression)));\n }\n\n visitNonNullAssert(ast: cdAst.NonNullAssert, mode: _Mode): any {\n return convertToStatementIfNeeded(mode, this._visit(ast.expression, _Mode.Expression));\n }\n\n visitPropertyRead(ast: cdAst.PropertyRead, mode: _Mode): any {\n const leftMostSafe = this.leftMostSafeNode(ast);\n if (leftMostSafe) {\n return this.convertSafeAccess(ast, leftMostSafe, mode);\n } else {\n let result: any = null;\n const prevUsesImplicitReceiver = this.usesImplicitReceiver;\n const receiver = this._visit(ast.receiver, _Mode.Expression);\n if (receiver === this._implicitReceiver) {\n result = this._getLocal(ast.name, ast.receiver);\n if (result) {\n // Restore the previous \"usesImplicitReceiver\" state since the implicit\n // receiver has been replaced with a resolved local expression.\n this.usesImplicitReceiver = prevUsesImplicitReceiver;\n this.addImplicitReceiverAccess(ast.name);\n }\n }\n if (result == null) {\n result = receiver.prop(ast.name, this.convertSourceSpan(ast.span));\n }\n return convertToStatementIfNeeded(mode, result);\n }\n }\n\n visitPropertyWrite(ast: cdAst.PropertyWrite, mode: _Mode): any {\n const receiver: o.Expression = this._visit(ast.receiver, _Mode.Expression);\n const prevUsesImplicitReceiver = this.usesImplicitReceiver;\n\n let varExpr: o.ReadPropExpr|null = null;\n if (receiver === this._implicitReceiver) {\n const localExpr = this._getLocal(ast.name, ast.receiver);\n if (localExpr) {\n if (localExpr instanceof o.ReadPropExpr) {\n // If the local variable is a property read expression, it's a reference\n // to a 'context.property' value and will be used as the target of the\n // write expression.\n varExpr = localExpr;\n // Restore the previous \"usesImplicitReceiver\" state since the implicit\n // receiver has been replaced with a resolved local expression.\n this.usesImplicitReceiver = prevUsesImplicitReceiver;\n this.addImplicitReceiverAccess(ast.name);\n } else {\n // Otherwise it's an error.\n const receiver = ast.name;\n const value = (ast.value instanceof cdAst.PropertyRead) ? ast.value.name : undefined;\n throw new Error(`Cannot assign value \"${value}\" to template variable \"${\n receiver}\". Template variables are read-only.`);\n }\n }\n }\n // If no local expression could be produced, use the original receiver's\n // property as the target.\n if (varExpr === null) {\n varExpr = receiver.prop(ast.name, this.convertSourceSpan(ast.span));\n }\n return convertToStatementIfNeeded(mode, varExpr.set(this._visit(ast.value, _Mode.Expression)));\n }\n\n visitSafePropertyRead(ast: cdAst.SafePropertyRead, mode: _Mode): any {\n return this.convertSafeAccess(ast, this.leftMostSafeNode(ast), mode);\n }\n\n visitSafeKeyedRead(ast: cdAst.SafeKeyedRead, mode: _Mode): any {\n return this.convertSafeAccess(ast, this.leftMostSafeNode(ast), mode);\n }\n\n visitAll(asts: cdAst.AST[], mode: _Mode): any {\n return asts.map(ast => this._visit(ast, mode));\n }\n\n visitCall(ast: cdAst.Call, mode: _Mode): any {\n const leftMostSafe = this.leftMostSafeNode(ast);\n if (leftMostSafe) {\n return this.convertSafeAccess(ast, leftMostSafe, mode);\n }\n\n const convertedArgs = this.visitAll(ast.args, _Mode.Expression);\n\n if (ast instanceof BuiltinFunctionCall) {\n return convertToStatementIfNeeded(mode, ast.converter(convertedArgs));\n }\n\n const receiver = ast.receiver;\n if (receiver instanceof cdAst.PropertyRead &&\n receiver.receiver instanceof cdAst.ImplicitReceiver &&\n !(receiver.receiver instanceof cdAst.ThisReceiver) && receiver.name === '$any') {\n if (convertedArgs.length !== 1) {\n throw new Error(`Invalid call to $any, expected 1 argument but received ${\n convertedArgs.length || 'none'}`);\n }\n return convertToStatementIfNeeded(mode, convertedArgs[0] as o.Expression);\n }\n\n const call = this._visit(receiver, _Mode.Expression)\n .callFn(convertedArgs, this.convertSourceSpan(ast.span));\n return convertToStatementIfNeeded(mode, call);\n }\n\n visitSafeCall(ast: cdAst.SafeCall, mode: _Mode): any {\n return this.convertSafeAccess(ast, this.leftMostSafeNode(ast), mode);\n }\n\n private _visit(ast: cdAst.AST, mode: _Mode): any {\n const result = this._resultMap.get(ast);\n if (result) return result;\n return (this._nodeMap.get(ast) || ast).visit(this, mode);\n }\n\n private convertSafeAccess(\n ast: cdAst.AST, leftMostSafe: cdAst.SafePropertyRead|cdAst.SafeKeyedRead|cdAst.SafeCall,\n mode: _Mode): any {\n // If the expression contains a safe access node on the left it needs to be converted to\n // an expression that guards the access to the member by checking the receiver for blank. As\n // execution proceeds from left to right, the left most part of the expression must be guarded\n // first but, because member access is left associative, the right side of the expression is at\n // the top of the AST. The desired result requires lifting a copy of the left part of the\n // expression up to test it for blank before generating the unguarded version.\n\n // Consider, for example the following expression: a?.b.c?.d.e\n\n // This results in the ast:\n // .\n // / \\\n // ?. e\n // / \\\n // . d\n // / \\\n // ?. c\n // / \\\n // a b\n\n // The following tree should be generated:\n //\n // /---- ? ----\\\n // / | \\\n // a /--- ? ---\\ null\n // / | \\\n // . . null\n // / \\ / \\\n // . c . e\n // / \\ / \\\n // a b . d\n // / \\\n // . c\n // / \\\n // a b\n //\n // Notice that the first guard condition is the left hand of the left most safe access node\n // which comes in as leftMostSafe to this routine.\n\n let guardedExpression = this._visit(leftMostSafe.receiver, _Mode.Expression);\n let temporary: o.ReadVarExpr|undefined = undefined;\n if (this.needsTemporaryInSafeAccess(leftMostSafe.receiver)) {\n // If the expression has method calls or pipes then we need to save the result into a\n // temporary variable to avoid calling stateful or impure code more than once.\n temporary = this.allocateTemporary();\n\n // Preserve the result in the temporary variable\n guardedExpression = temporary.set(guardedExpression);\n\n // Ensure all further references to the guarded expression refer to the temporary instead.\n this._resultMap.set(leftMostSafe.receiver, temporary);\n }\n const condition = guardedExpression.isBlank();\n\n // Convert the ast to an unguarded access to the receiver's member. The map will substitute\n // leftMostNode with its unguarded version in the call to `this.visit()`.\n if (leftMostSafe instanceof cdAst.SafeCall) {\n this._nodeMap.set(\n leftMostSafe,\n new cdAst.Call(\n leftMostSafe.span, leftMostSafe.sourceSpan, leftMostSafe.receiver, leftMostSafe.args,\n leftMostSafe.argumentSpan));\n } else if (leftMostSafe instanceof cdAst.SafeKeyedRead) {\n this._nodeMap.set(\n leftMostSafe,\n new cdAst.KeyedRead(\n leftMostSafe.span, leftMostSafe.sourceSpan, leftMostSafe.receiver, leftMostSafe.key));\n } else {\n this._nodeMap.set(\n leftMostSafe,\n new cdAst.PropertyRead(\n leftMostSafe.span, leftMostSafe.sourceSpan, leftMostSafe.nameSpan,\n leftMostSafe.receiver, leftMostSafe.name));\n }\n\n // Recursively convert the node now without the guarded member access.\n const access = this._visit(ast, _Mode.Expression);\n\n // Remove the mapping. This is not strictly required as the converter only traverses each node\n // once but is safer if the conversion is changed to traverse the nodes more than once.\n this._nodeMap.delete(leftMostSafe);\n\n // If we allocated a temporary, release it.\n if (temporary) {\n this.releaseTemporary(temporary);\n }\n\n // Produce the conditional\n return convertToStatementIfNeeded(mode, condition.conditional(o.NULL_EXPR, access));\n }\n\n private convertNullishCoalesce(ast: cdAst.Binary, mode: _Mode): any {\n const left: o.Expression = this._visit(ast.left, _Mode.Expression);\n const right: o.Expression = this._visit(ast.right, _Mode.Expression);\n const temporary = this.allocateTemporary();\n this.releaseTemporary(temporary);\n\n // Generate the following expression. It is identical to how TS\n // transpiles binary expressions with a nullish coalescing operator.\n // let temp;\n // (temp = a) !== null && temp !== undefined ? temp : b;\n return convertToStatementIfNeeded(\n mode,\n temporary.set(left)\n .notIdentical(o.NULL_EXPR)\n .and(temporary.notIdentical(o.literal(undefined)))\n .conditional(temporary, right));\n }\n\n // Given an expression of the form a?.b.c?.d.e then the left most safe node is\n // the (a?.b). The . and ?. are left associative thus can be rewritten as:\n // ((((a?.c).b).c)?.d).e. This returns the most deeply nested safe read or\n // safe method call as this needs to be transformed initially to:\n // a == null ? null : a.c.b.c?.d.e\n // then to:\n // a == null ? null : a.b.c == null ? null : a.b.c.d.e\n private leftMostSafeNode(ast: cdAst.AST): cdAst.SafePropertyRead|cdAst.SafeKeyedRead {\n const visit = (visitor: cdAst.AstVisitor, ast: cdAst.AST): any => {\n return (this._nodeMap.get(ast) || ast).visit(visitor);\n };\n return ast.visit({\n visitUnary(ast: cdAst.Unary) {\n return null;\n },\n visitBinary(ast: cdAst.Binary) {\n return null;\n },\n visitChain(ast: cdAst.Chain) {\n return null;\n },\n visitConditional(ast: cdAst.Conditional) {\n return null;\n },\n visitCall(ast: cdAst.Call) {\n return visit(this, ast.receiver);\n },\n visitSafeCall(ast: cdAst.SafeCall) {\n return visit(this, ast.receiver) || ast;\n },\n visitImplicitReceiver(ast: cdAst.ImplicitReceiver) {\n return null;\n },\n visitThisReceiver(ast: cdAst.ThisReceiver) {\n return null;\n },\n visitInterpolation(ast: cdAst.Interpolation) {\n return null;\n },\n visitKeyedRead(ast: cdAst.KeyedRead) {\n return visit(this, ast.receiver);\n },\n visitKeyedWrite(ast: cdAst.KeyedWrite) {\n return null;\n },\n visitLiteralArray(ast: cdAst.LiteralArray) {\n return null;\n },\n visitLiteralMap(ast: cdAst.LiteralMap) {\n return null;\n },\n visitLiteralPrimitive(ast: cdAst.LiteralPrimitive) {\n return null;\n },\n visitPipe(ast: cdAst.BindingPipe) {\n return null;\n },\n visitPrefixNot(ast: cdAst.PrefixNot) {\n return null;\n },\n visitNonNullAssert(ast: cdAst.NonNullAssert) {\n return visit(this, ast.expression);\n },\n visitPropertyRead(ast: cdAst.PropertyRead) {\n return visit(this, ast.receiver);\n },\n visitPropertyWrite(ast: cdAst.PropertyWrite) {\n return null;\n },\n visitSafePropertyRead(ast: cdAst.SafePropertyRead) {\n return visit(this, ast.receiver) || ast;\n },\n visitSafeKeyedRead(ast: cdAst.SafeKeyedRead) {\n return visit(this, ast.receiver) || ast;\n }\n });\n }\n\n // Returns true of the AST includes a method or a pipe indicating that, if the\n // expression is used as the target of a safe property or method access then\n // the expression should be stored into a temporary variable.\n private needsTemporaryInSafeAccess(ast: cdAst.AST): boolean {\n const visit = (visitor: cdAst.AstVisitor, ast: cdAst.AST): boolean => {\n return ast && (this._nodeMap.get(ast) || ast).visit(visitor);\n };\n const visitSome = (visitor: cdAst.AstVisitor, ast: cdAst.AST[]): boolean => {\n return ast.some(ast => visit(visitor, ast));\n };\n return ast.visit({\n visitUnary(ast: cdAst.Unary): boolean {\n return visit(this, ast.expr);\n },\n visitBinary(ast: cdAst.Binary): boolean {\n return visit(this, ast.left) || visit(this, ast.right);\n },\n visitChain(ast: cdAst.Chain) {\n return false;\n },\n visitConditional(ast: cdAst.Conditional): boolean {\n return visit(this, ast.condition) || visit(this, ast.trueExp) || visit(this, ast.falseExp);\n },\n visitCall(ast: cdAst.Call) {\n return true;\n },\n visitSafeCall(ast: cdAst.SafeCall) {\n return true;\n },\n visitImplicitReceiver(ast: cdAst.ImplicitReceiver) {\n return false;\n },\n visitThisReceiver(ast: cdAst.ThisReceiver) {\n return false;\n },\n visitInterpolation(ast: cdAst.Interpolation) {\n return visitSome(this, ast.expressions);\n },\n visitKeyedRead(ast: cdAst.KeyedRead) {\n return false;\n },\n visitKeyedWrite(ast: cdAst.KeyedWrite) {\n return false;\n },\n visitLiteralArray(ast: cdAst.LiteralArray) {\n return true;\n },\n visitLiteralMap(ast: cdAst.LiteralMap) {\n return true;\n },\n visitLiteralPrimitive(ast: cdAst.LiteralPrimitive) {\n return false;\n },\n visitPipe(ast: cdAst.BindingPipe) {\n return true;\n },\n visitPrefixNot(ast: cdAst.PrefixNot) {\n return visit(this, ast.expression);\n },\n visitNonNullAssert(ast: cdAst.PrefixNot) {\n return visit(this, ast.expression);\n },\n visitPropertyRead(ast: cdAst.PropertyRead) {\n return false;\n },\n visitPropertyWrite(ast: cdAst.PropertyWrite) {\n return false;\n },\n visitSafePropertyRead(ast: cdAst.SafePropertyRead) {\n return false;\n },\n visitSafeKeyedRead(ast: cdAst.SafeKeyedRead) {\n return false;\n }\n });\n }\n\n private allocateTemporary(): o.ReadVarExpr {\n const tempNumber = this._currentTemporary++;\n this.temporaryCount = Math.max(this._currentTemporary, this.temporaryCount);\n return new o.ReadVarExpr(temporaryName(this.bindingId, tempNumber));\n }\n\n private releaseTemporary(temporary: o.ReadVarExpr) {\n this._currentTemporary--;\n if (temporary.name != temporaryName(this.bindingId, this._currentTemporary)) {\n throw new Error(`Temporary ${temporary.name} released out of order`);\n }\n }\n\n /**\n * Creates an absolute `ParseSourceSpan` from the relative `ParseSpan`.\n *\n * `ParseSpan` objects are relative to the start of the expression.\n * This method converts these to full `ParseSourceSpan` objects that\n * show where the span is within the overall source file.\n *\n * @param span the relative span to convert.\n * @returns a `ParseSourceSpan` for the given span or null if no\n * `baseSourceSpan` was provided to this class.\n */\n private convertSourceSpan(span: cdAst.ParseSpan) {\n if (this.baseSourceSpan) {\n const start = this.baseSourceSpan.start.moveBy(span.start);\n const end = this.baseSourceSpan.start.moveBy(span.end);\n const fullStart = this.baseSourceSpan.fullStart.moveBy(span.start);\n return new ParseSourceSpan(start, end, fullStart);\n } else {\n return null;\n }\n }\n\n /** Adds the name of an AST to the list of implicit receiver accesses. */\n private addImplicitReceiverAccess(name: string) {\n if (this.implicitReceiverAccesses) {\n this.implicitReceiverAccesses.add(name);\n }\n }\n}\n\nfunction flattenStatements(arg: any, output: o.Statement[]) {\n if (Array.isArray(arg)) {\n (arg).forEach((entry) => flattenStatements(entry, output));\n } else {\n output.push(arg);\n }\n}\n\nfunction unsupported(): never {\n throw new Error('Unsupported operation');\n}\n\nclass InterpolationExpression extends o.Expression {\n constructor(public args: o.Expression[]) {\n super(null, null);\n }\n\n override isConstant = unsupported;\n override isEquivalent = unsupported;\n override visitExpression = unsupported;\n override clone = unsupported;\n}\n\nclass DefaultLocalResolver implements LocalResolver {\n constructor(public globals?: Set) {}\n notifyImplicitReceiverUse(): void {}\n maybeRestoreView(): void {}\n getLocal(name: string): o.Expression|null {\n if (name === EventHandlerVars.event.name) {\n return EventHandlerVars.event;\n }\n return null;\n }\n}\n\nexport class BuiltinFunctionCall extends cdAst.Call {\n constructor(\n span: cdAst.ParseSpan, sourceSpan: cdAst.AbsoluteSourceSpan, args: cdAst.AST[],\n public converter: BuiltinConverter) {\n super(span, sourceSpan, new cdAst.EmptyExpr(span, sourceSpan), args, null!);\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {SecurityContext} from '../core';\n\n// =================================================================================================\n// =================================================================================================\n// =========== S T O P - S T O P - S T O P - S T O P - S T O P - S T O P ===========\n// =================================================================================================\n// =================================================================================================\n//\n// DO NOT EDIT THIS LIST OF SECURITY SENSITIVE PROPERTIES WITHOUT A SECURITY REVIEW!\n// Reach out to mprobst for details.\n//\n// =================================================================================================\n\n/** Map from tagName|propertyName to SecurityContext. Properties applying to all tags use '*'. */\nlet _SECURITY_SCHEMA!: {[k: string]: SecurityContext};\n\nexport function SECURITY_SCHEMA(): {[k: string]: SecurityContext} {\n if (!_SECURITY_SCHEMA) {\n _SECURITY_SCHEMA = {};\n // Case is insignificant below, all element and attribute names are lower-cased for lookup.\n\n registerContext(SecurityContext.HTML, [\n 'iframe|srcdoc',\n '*|innerHTML',\n '*|outerHTML',\n ]);\n registerContext(SecurityContext.STYLE, ['*|style']);\n // NB: no SCRIPT contexts here, they are never allowed due to the parser stripping them.\n registerContext(SecurityContext.URL, [\n '*|formAction',\n 'area|href',\n 'area|ping',\n 'audio|src',\n 'a|href',\n 'a|ping',\n 'blockquote|cite',\n 'body|background',\n 'del|cite',\n 'form|action',\n 'img|src',\n 'input|src',\n 'ins|cite',\n 'q|cite',\n 'source|src',\n 'track|src',\n 'video|poster',\n 'video|src',\n ]);\n registerContext(SecurityContext.RESOURCE_URL, [\n 'applet|code',\n 'applet|codebase',\n 'base|href',\n 'embed|src',\n 'frame|src',\n 'head|profile',\n 'html|manifest',\n 'iframe|src',\n 'link|href',\n 'media|src',\n 'object|codebase',\n 'object|data',\n 'script|src',\n ]);\n }\n return _SECURITY_SCHEMA;\n}\n\nfunction registerContext(ctx: SecurityContext, specs: string[]) {\n for (const spec of specs) _SECURITY_SCHEMA[spec.toLowerCase()] = ctx;\n}\n\n/**\n * The set of security-sensitive attributes of an `