@angular/upgrade
Version:
Angular - the library for easing update from v1 to v2
1 lines • 161 kB
Source Map (JSON)
{"version":3,"file":"static.mjs","sources":["../../../../../darwin_arm64-fastbuild-ST-199a4f3c4e20/bin/packages/upgrade/src/common/src/component_info.ts","../../../../../darwin_arm64-fastbuild-ST-199a4f3c4e20/bin/packages/upgrade/src/common/src/util.ts","../../../../../darwin_arm64-fastbuild-ST-199a4f3c4e20/bin/packages/upgrade/src/common/src/downgrade_component_adapter.ts","../../../../../darwin_arm64-fastbuild-ST-199a4f3c4e20/bin/packages/upgrade/src/common/src/promise_util.ts","../../../../../darwin_arm64-fastbuild-ST-199a4f3c4e20/bin/packages/upgrade/src/common/src/downgrade_component.ts","../../../../../darwin_arm64-fastbuild-ST-199a4f3c4e20/bin/packages/upgrade/src/common/src/downgrade_injectable.ts","../../../../../darwin_arm64-fastbuild-ST-199a4f3c4e20/bin/packages/upgrade/src/common/src/security/trusted_types.ts","../../../../../darwin_arm64-fastbuild-ST-199a4f3c4e20/bin/packages/upgrade/src/common/src/upgrade_helper.ts","../../../../../darwin_arm64-fastbuild-ST-199a4f3c4e20/bin/packages/upgrade/static/src/angular1_providers.ts","../../../../../darwin_arm64-fastbuild-ST-199a4f3c4e20/bin/packages/upgrade/static/src/util.ts","../../../../../darwin_arm64-fastbuild-ST-199a4f3c4e20/bin/packages/upgrade/static/src/downgrade_module.ts","../../../../../darwin_arm64-fastbuild-ST-199a4f3c4e20/bin/packages/upgrade/static/src/upgrade_component.ts","../../../../../darwin_arm64-fastbuild-ST-199a4f3c4e20/bin/packages/upgrade/static/src/upgrade_module.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.dev/license\n */\n\n/**\n * A `PropertyBinding` represents a mapping between a property name\n * and an attribute name. It is parsed from a string of the form\n * `\"prop: attr\"`; or simply `\"propAndAttr\" where the property\n * and attribute have the same identifier.\n */\nexport class PropertyBinding {\n bracketAttr: string;\n bracketParenAttr: string;\n parenAttr: string;\n onAttr: string;\n bindAttr: string;\n bindonAttr: string;\n\n constructor(\n public prop: string,\n public attr: string,\n ) {\n this.bracketAttr = `[${this.attr}]`;\n this.parenAttr = `(${this.attr})`;\n this.bracketParenAttr = `[(${this.attr})]`;\n const capitalAttr = this.attr.charAt(0).toUpperCase() + this.attr.slice(1);\n this.onAttr = `on${capitalAttr}`;\n this.bindAttr = `bind${capitalAttr}`;\n this.bindonAttr = `bindon${capitalAttr}`;\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.dev/license\n */\n\nimport {Injector, Type, ɵNG_MOD_DEF} from '@angular/core';\n\nimport {\n element as angularElement,\n IAugmentedJQuery,\n IInjectorService,\n INgModelController,\n IRootScopeService,\n} from './angular1';\nimport {\n $ROOT_ELEMENT,\n $ROOT_SCOPE,\n DOWNGRADED_MODULE_COUNT_KEY,\n UPGRADE_APP_TYPE_KEY,\n} from './constants';\n\nconst DIRECTIVE_PREFIX_REGEXP = /^(?:x|data)[:\\-_]/i;\nconst DIRECTIVE_SPECIAL_CHARS_REGEXP = /[:\\-_]+(.)/g;\n\nexport function onError(e: any) {\n // TODO: (misko): We seem to not have a stack trace here!\n console.error(e, e.stack);\n throw e;\n}\n\n/**\n * Clean the jqLite/jQuery data on the element and all its descendants.\n * Equivalent to how jqLite/jQuery invoke `cleanData()` on an Element when removed:\n * https://github.com/angular/angular.js/blob/2e72ea13fa98bebf6ed4b5e3c45eaf5f990ed16f/src/jqLite.js#L349-L355\n * https://github.com/jquery/jquery/blob/6984d1747623dbc5e87fd6c261a5b6b1628c107c/src/manipulation.js#L182\n *\n * NOTE:\n * `cleanData()` will also invoke the AngularJS `$destroy` DOM event on the element:\n * https://github.com/angular/angular.js/blob/2e72ea13fa98bebf6ed4b5e3c45eaf5f990ed16f/src/Angular.js#L1932-L1945\n *\n * @param node The DOM node whose data needs to be cleaned.\n */\nexport function cleanData(node: Node): void {\n angularElement.cleanData([node]);\n if (isParentNode(node)) {\n angularElement.cleanData(node.querySelectorAll('*'));\n }\n}\n\nexport function controllerKey(name: string): string {\n return '$' + name + 'Controller';\n}\n\n/**\n * Destroy an AngularJS app given the app `$injector`.\n *\n * NOTE: Destroying an app is not officially supported by AngularJS, but try to do our best by\n * destroying `$rootScope` and clean the jqLite/jQuery data on `$rootElement` and all\n * descendants.\n *\n * @param $injector The `$injector` of the AngularJS app to destroy.\n */\nexport function destroyApp($injector: IInjectorService): void {\n const $rootElement: IAugmentedJQuery = $injector.get($ROOT_ELEMENT);\n const $rootScope: IRootScopeService = $injector.get($ROOT_SCOPE);\n\n $rootScope.$destroy();\n cleanData($rootElement[0]);\n}\n\nexport function directiveNormalize(name: string): string {\n return name\n .replace(DIRECTIVE_PREFIX_REGEXP, '')\n .replace(DIRECTIVE_SPECIAL_CHARS_REGEXP, (_, letter) => letter.toUpperCase());\n}\n\nexport function getTypeName(type: Type<any>): string {\n // Return the name of the type or the first line of its stringified version.\n return (type as any).overriddenName || type.name || type.toString().split('\\n')[0];\n}\n\nexport function getDowngradedModuleCount($injector: IInjectorService): number {\n return $injector.has(DOWNGRADED_MODULE_COUNT_KEY)\n ? $injector.get(DOWNGRADED_MODULE_COUNT_KEY)\n : 0;\n}\n\nexport function getUpgradeAppType($injector: IInjectorService): UpgradeAppType {\n return $injector.has(UPGRADE_APP_TYPE_KEY)\n ? $injector.get(UPGRADE_APP_TYPE_KEY)\n : UpgradeAppType.None;\n}\n\nexport function isFunction(value: any): value is Function {\n return typeof value === 'function';\n}\n\nexport function isNgModuleType(value: any): value is Type<unknown> {\n // NgModule class should have the `ɵmod` static property attached by AOT or JIT compiler.\n return isFunction(value) && !!value[ɵNG_MOD_DEF];\n}\n\nfunction isParentNode(node: Node | ParentNode): node is ParentNode {\n return isFunction((node as unknown as ParentNode).querySelectorAll);\n}\n\nexport function validateInjectionKey(\n $injector: IInjectorService,\n downgradedModule: string,\n injectionKey: string,\n attemptedAction: string,\n): void {\n const upgradeAppType = getUpgradeAppType($injector);\n const downgradedModuleCount = getDowngradedModuleCount($injector);\n\n // Check for common errors.\n switch (upgradeAppType) {\n case UpgradeAppType.Dynamic:\n case UpgradeAppType.Static:\n if (downgradedModule) {\n throw new Error(\n `Error while ${attemptedAction}: 'downgradedModule' unexpectedly specified.\\n` +\n \"You should not specify a value for 'downgradedModule', unless you are downgrading \" +\n \"more than one Angular module (via 'downgradeModule()').\",\n );\n }\n break;\n case UpgradeAppType.Lite:\n if (!downgradedModule && downgradedModuleCount >= 2) {\n throw new Error(\n `Error while ${attemptedAction}: 'downgradedModule' not specified.\\n` +\n 'This application contains more than one downgraded Angular module, thus you need to ' +\n \"always specify 'downgradedModule' when downgrading components and injectables.\",\n );\n }\n\n if (!$injector.has(injectionKey)) {\n throw new Error(\n `Error while ${attemptedAction}: Unable to find the specified downgraded module.\\n` +\n 'Did you forget to downgrade an Angular module or include it in the AngularJS ' +\n 'application?',\n );\n }\n\n break;\n default:\n throw new Error(\n `Error while ${attemptedAction}: Not a valid '@angular/upgrade' application.\\n` +\n 'Did you forget to downgrade an Angular module or include it in the AngularJS ' +\n 'application?',\n );\n }\n}\n\nexport class Deferred<R> {\n promise: Promise<R>;\n resolve!: (value: R | PromiseLike<R>) => void;\n reject!: (error?: any) => void;\n\n constructor() {\n this.promise = new Promise((res, rej) => {\n this.resolve = res;\n this.reject = rej;\n });\n }\n}\n\nexport interface LazyModuleRef {\n injector?: Injector;\n promise?: Promise<Injector>;\n}\n\nexport const enum UpgradeAppType {\n // App NOT using `@angular/upgrade`. (This should never happen in an `ngUpgrade` app.)\n None,\n\n // App using the deprecated `@angular/upgrade` APIs (a.k.a. dynamic `ngUpgrade`).\n Dynamic,\n\n // App using `@angular/upgrade/static` with `UpgradeModule`.\n Static,\n\n // App using @angular/upgrade/static` with `downgradeModule()` (a.k.a `ngUpgrade`-lite ).\n Lite,\n}\n\n/**\n * @return Whether the passed-in component implements the subset of the\n * `ControlValueAccessor` interface needed for AngularJS `ng-model`\n * compatibility.\n */\nfunction supportsNgModel(component: any) {\n return (\n typeof component.writeValue === 'function' && typeof component.registerOnChange === 'function'\n );\n}\n\n/**\n * Glue the AngularJS `NgModelController` (if it exists) to the component\n * (if it implements the needed subset of the `ControlValueAccessor` interface).\n */\nexport function hookupNgModel(ngModel: INgModelController, component: any) {\n if (ngModel && supportsNgModel(component)) {\n ngModel.$render = () => {\n component.writeValue(ngModel.$viewValue);\n };\n component.registerOnChange(ngModel.$setViewValue.bind(ngModel));\n if (typeof component.registerOnTouched === 'function') {\n component.registerOnTouched(ngModel.$setTouched.bind(ngModel));\n }\n }\n}\n\n/**\n * Test two values for strict equality, accounting for the fact that `NaN !== NaN`.\n */\nexport function strictEquals(val1: any, val2: any): boolean {\n return val1 === val2 || (val1 !== val1 && val2 !== val2);\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.dev/license\n */\n\nimport {\n ApplicationRef,\n ChangeDetectorRef,\n ComponentFactory,\n ComponentRef,\n type EventEmitter,\n Injector,\n OnChanges,\n SimpleChange,\n SimpleChanges,\n StaticProvider,\n Testability,\n TestabilityRegistry,\n type OutputEmitterRef,\n type ɵInputSignalNode as InputSignalNode,\n ɵSIGNAL as SIGNAL,\n} from '@angular/core';\n\nimport {\n IAttributes,\n IAugmentedJQuery,\n ICompileService,\n INgModelController,\n IParseService,\n IScope,\n} from './angular1';\nimport {PropertyBinding} from './component_info';\nimport {$SCOPE} from './constants';\nimport {cleanData, getTypeName, hookupNgModel, strictEquals} from './util';\n\nconst INITIAL_VALUE = {\n __UNINITIALIZED__: true,\n};\n\nexport class DowngradeComponentAdapter {\n private implementsOnChanges = false;\n private inputChangeCount: number = 0;\n private inputChanges: SimpleChanges = {};\n private componentScope: IScope;\n\n constructor(\n private element: IAugmentedJQuery,\n private attrs: IAttributes,\n private scope: IScope,\n private ngModel: INgModelController,\n private parentInjector: Injector,\n private $compile: ICompileService,\n private $parse: IParseService,\n private componentFactory: ComponentFactory<any>,\n private wrapCallback: <T>(cb: () => T) => () => T,\n private readonly unsafelyOverwriteSignalInputs: boolean,\n ) {\n this.componentScope = scope.$new();\n }\n\n compileContents(): Node[][] {\n const compiledProjectableNodes: Node[][] = [];\n const projectableNodes: Node[][] = this.groupProjectableNodes();\n const linkFns = projectableNodes.map((nodes) => this.$compile(nodes));\n\n this.element.empty!();\n\n linkFns.forEach((linkFn) => {\n linkFn(this.scope, (clone: Node[]) => {\n compiledProjectableNodes.push(clone);\n this.element.append!(clone);\n });\n });\n\n return compiledProjectableNodes;\n }\n\n createComponentAndSetup(\n projectableNodes: Node[][],\n manuallyAttachView = false,\n propagateDigest = true,\n ): ComponentRef<any> {\n const component = this.createComponent(projectableNodes);\n this.setupInputs(manuallyAttachView, propagateDigest, component);\n this.setupOutputs(component.componentRef);\n this.registerCleanup(component.componentRef);\n\n return component.componentRef;\n }\n\n private createComponent(projectableNodes: Node[][]): ComponentInfo {\n const providers: StaticProvider[] = [{provide: $SCOPE, useValue: this.componentScope}];\n const childInjector = Injector.create({\n providers: providers,\n parent: this.parentInjector,\n name: 'DowngradeComponentAdapter',\n });\n\n const componentRef = this.componentFactory.create(\n childInjector,\n projectableNodes,\n this.element[0],\n );\n const viewChangeDetector = componentRef.injector.get(ChangeDetectorRef);\n const changeDetector = componentRef.changeDetectorRef;\n\n // testability hook is commonly added during component bootstrap in\n // packages/core/src/application_ref.bootstrap()\n // in downgraded application, component creation will take place here as well as adding the\n // testability hook.\n const testability = componentRef.injector.get(Testability, null);\n if (testability) {\n componentRef.injector\n .get(TestabilityRegistry)\n .registerApplication(componentRef.location.nativeElement, testability);\n }\n\n hookupNgModel(this.ngModel, componentRef.instance);\n\n return {viewChangeDetector, componentRef, changeDetector};\n }\n\n private setupInputs(\n manuallyAttachView: boolean,\n propagateDigest = true,\n {componentRef, changeDetector, viewChangeDetector}: ComponentInfo,\n ): void {\n const attrs = this.attrs;\n const inputs = this.componentFactory.inputs || [];\n for (const input of inputs) {\n const inputBinding = new PropertyBinding(input.propName, input.templateName);\n let expr: string | null = null;\n\n if (attrs.hasOwnProperty(inputBinding.attr)) {\n const observeFn = ((prop, isSignal) => {\n let prevValue = INITIAL_VALUE;\n return (currValue: any) => {\n // Initially, both `$observe()` and `$watch()` will call this function.\n if (!strictEquals(prevValue, currValue)) {\n if (prevValue === INITIAL_VALUE) {\n prevValue = currValue;\n }\n\n this.updateInput(componentRef, prop, prevValue, currValue, isSignal);\n prevValue = currValue;\n }\n };\n })(inputBinding.prop, input.isSignal);\n attrs.$observe(inputBinding.attr, observeFn);\n\n // Use `$watch()` (in addition to `$observe()`) in order to initialize the input in time\n // for `ngOnChanges()`. This is necessary if we are already in a `$digest`, which means that\n // `ngOnChanges()` (which is called by a watcher) will run before the `$observe()` callback.\n let unwatch: Function | null = this.componentScope.$watch(() => {\n unwatch!();\n unwatch = null;\n observeFn(attrs[inputBinding.attr]);\n });\n } else if (attrs.hasOwnProperty(inputBinding.bindAttr)) {\n expr = attrs[inputBinding.bindAttr];\n } else if (attrs.hasOwnProperty(inputBinding.bracketAttr)) {\n expr = attrs[inputBinding.bracketAttr];\n } else if (attrs.hasOwnProperty(inputBinding.bindonAttr)) {\n expr = attrs[inputBinding.bindonAttr];\n } else if (attrs.hasOwnProperty(inputBinding.bracketParenAttr)) {\n expr = attrs[inputBinding.bracketParenAttr];\n }\n if (expr != null) {\n const watchFn = (\n (prop, isSignal) => (currValue: unknown, prevValue: unknown) =>\n this.updateInput(componentRef, prop, prevValue, currValue, isSignal)\n )(inputBinding.prop, input.isSignal);\n this.componentScope.$watch(expr, watchFn);\n }\n }\n\n // Invoke `ngOnChanges()` and Change Detection (when necessary)\n const detectChanges = () => changeDetector.detectChanges();\n const prototype = this.componentFactory.componentType.prototype;\n this.implementsOnChanges = !!(prototype && (<OnChanges>prototype).ngOnChanges);\n\n this.componentScope.$watch(\n () => this.inputChangeCount,\n this.wrapCallback(() => {\n // Invoke `ngOnChanges()`\n if (this.implementsOnChanges) {\n const inputChanges = this.inputChanges;\n this.inputChanges = {};\n (<OnChanges>componentRef.instance).ngOnChanges(inputChanges);\n }\n\n viewChangeDetector.markForCheck();\n\n // If opted out of propagating digests, invoke change detection when inputs change.\n if (!propagateDigest) {\n detectChanges();\n }\n }),\n );\n\n // If not opted out of propagating digests, invoke change detection on every digest\n if (propagateDigest) {\n this.componentScope.$watch(this.wrapCallback(detectChanges));\n }\n\n // If necessary, attach the view so that it will be dirty-checked.\n // (Allow time for the initial input values to be set and `ngOnChanges()` to be called.)\n if (manuallyAttachView || !propagateDigest) {\n let unwatch: Function | null = this.componentScope.$watch(() => {\n unwatch!();\n unwatch = null;\n\n const appRef = this.parentInjector.get<ApplicationRef>(ApplicationRef);\n appRef.attachView(componentRef.hostView);\n });\n }\n }\n\n private setupOutputs(componentRef: ComponentRef<any>) {\n const attrs = this.attrs;\n const outputs = this.componentFactory.outputs || [];\n for (const output of outputs) {\n const outputBindings = new PropertyBinding(output.propName, output.templateName);\n const bindonAttr = outputBindings.bindonAttr.substring(\n 0,\n outputBindings.bindonAttr.length - 6,\n );\n const bracketParenAttr = `[(${outputBindings.bracketParenAttr.substring(\n 2,\n outputBindings.bracketParenAttr.length - 8,\n )})]`;\n // order below is important - first update bindings then evaluate expressions\n if (attrs.hasOwnProperty(bindonAttr)) {\n this.subscribeToOutput(componentRef, outputBindings, attrs[bindonAttr], true);\n }\n if (attrs.hasOwnProperty(bracketParenAttr)) {\n this.subscribeToOutput(componentRef, outputBindings, attrs[bracketParenAttr], true);\n }\n if (attrs.hasOwnProperty(outputBindings.onAttr)) {\n this.subscribeToOutput(componentRef, outputBindings, attrs[outputBindings.onAttr]);\n }\n if (attrs.hasOwnProperty(outputBindings.parenAttr)) {\n this.subscribeToOutput(componentRef, outputBindings, attrs[outputBindings.parenAttr]);\n }\n }\n }\n\n private subscribeToOutput(\n componentRef: ComponentRef<any>,\n output: PropertyBinding,\n expr: string,\n isAssignment: boolean = false,\n ) {\n const getter = this.$parse(expr);\n const setter = getter.assign;\n if (isAssignment && !setter) {\n throw new Error(`Expression '${expr}' is not assignable!`);\n }\n const emitter = componentRef.instance[output.prop] as EventEmitter<any> | OutputEmitterRef<any>;\n if (emitter) {\n const subscription = emitter.subscribe(\n isAssignment\n ? (v: any) => setter!(this.scope, v)\n : (v: any) => getter(this.scope, {'$event': v}),\n );\n componentRef.onDestroy(() => subscription.unsubscribe());\n } else {\n throw new Error(\n `Missing emitter '${output.prop}' on component '${getTypeName(\n this.componentFactory.componentType,\n )}'!`,\n );\n }\n }\n\n private registerCleanup(componentRef: ComponentRef<any>) {\n const testabilityRegistry = componentRef.injector.get(TestabilityRegistry);\n const destroyComponentRef = this.wrapCallback(() => componentRef.destroy());\n let destroyed = false;\n\n this.element.on!('$destroy', () => {\n // The `$destroy` event may have been triggered by the `cleanData()` call in the\n // `componentScope` `$destroy` handler below. In that case, we don't want to call\n // `componentScope.$destroy()` again.\n if (!destroyed) this.componentScope.$destroy();\n });\n this.componentScope.$on('$destroy', () => {\n if (!destroyed) {\n destroyed = true;\n testabilityRegistry.unregisterApplication(componentRef.location.nativeElement);\n\n // The `componentScope` might be getting destroyed, because an ancestor element is being\n // removed/destroyed. If that is the case, jqLite/jQuery would normally invoke `cleanData()`\n // on the removed element and all descendants.\n // https://github.com/angular/angular.js/blob/2e72ea13fa98bebf6ed4b5e3c45eaf5f990ed16f/src/jqLite.js#L349-L355\n // https://github.com/jquery/jquery/blob/6984d1747623dbc5e87fd6c261a5b6b1628c107c/src/manipulation.js#L182\n //\n // Here, however, `destroyComponentRef()` may under some circumstances remove the element\n // from the DOM and therefore it will no longer be a descendant of the removed element when\n // `cleanData()` is called. This would result in a memory leak, because the element's data\n // and event handlers (and all objects directly or indirectly referenced by them) would be\n // retained.\n //\n // To ensure the element is always properly cleaned up, we manually call `cleanData()` on\n // this element and its descendants before destroying the `ComponentRef`.\n cleanData(this.element[0]);\n\n destroyComponentRef();\n }\n });\n }\n\n private updateInput(\n componentRef: ComponentRef<any>,\n prop: string,\n prevValue: any,\n currValue: any,\n isSignal: boolean,\n ) {\n if (this.implementsOnChanges) {\n this.inputChanges[prop] = new SimpleChange(prevValue, currValue, prevValue === currValue);\n }\n\n this.inputChangeCount++;\n if (isSignal && !this.unsafelyOverwriteSignalInputs) {\n const node = componentRef.instance[prop][SIGNAL] as InputSignalNode<unknown, unknown>;\n node.applyValueToInputSignal(node, currValue);\n } else {\n componentRef.instance[prop] = currValue;\n }\n }\n\n private groupProjectableNodes() {\n let ngContentSelectors = this.componentFactory.ngContentSelectors;\n return groupNodesBySelector(ngContentSelectors, this.element.contents!());\n }\n}\n\n/**\n * Group a set of DOM nodes into `ngContent` groups, based on the given content selectors.\n */\nexport function groupNodesBySelector(ngContentSelectors: string[], nodes: Node[]): Node[][] {\n const projectableNodes: Node[][] = [];\n\n for (let i = 0, ii = ngContentSelectors.length; i < ii; ++i) {\n projectableNodes[i] = [];\n }\n\n for (let j = 0, jj = nodes.length; j < jj; ++j) {\n const node = nodes[j];\n const ngContentIndex = findMatchingNgContentIndex(node, ngContentSelectors);\n if (ngContentIndex != null) {\n projectableNodes[ngContentIndex].push(node);\n }\n }\n\n return projectableNodes;\n}\n\nfunction findMatchingNgContentIndex(element: any, ngContentSelectors: string[]): number | null {\n const ngContentIndices: number[] = [];\n let wildcardNgContentIndex: number = -1;\n for (let i = 0; i < ngContentSelectors.length; i++) {\n const selector = ngContentSelectors[i];\n if (selector === '*') {\n wildcardNgContentIndex = i;\n } else {\n if (matchesSelector(element, selector)) {\n ngContentIndices.push(i);\n }\n }\n }\n ngContentIndices.sort();\n\n if (wildcardNgContentIndex !== -1) {\n ngContentIndices.push(wildcardNgContentIndex);\n }\n return ngContentIndices.length ? ngContentIndices[0] : null;\n}\n\nfunction matchesSelector(el: any, selector: string): boolean {\n const elProto = <any>Element.prototype;\n\n return el.nodeType === Node.ELEMENT_NODE\n ? // matches is supported by all browsers from 2014 onwards except non-chromium edge\n (elProto.matches ?? elProto.msMatchesSelector).call(el, selector)\n : false;\n}\n\ninterface ComponentInfo {\n componentRef: ComponentRef<any>;\n changeDetector: ChangeDetectorRef;\n viewChangeDetector: ChangeDetectorRef;\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.dev/license\n */\n\nimport {isFunction} from './util';\n\nexport interface Thenable<T> {\n then(callback: (value: T) => any): any;\n}\n\nexport function isThenable<T>(obj: unknown): obj is Thenable<T> {\n return !!obj && isFunction((obj as any).then);\n}\n\n/**\n * Synchronous, promise-like object.\n */\nexport class SyncPromise<T> {\n protected value: T | undefined;\n private resolved = false;\n private callbacks: ((value: T) => unknown)[] = [];\n\n static all<T>(valuesOrPromises: (T | Thenable<T>)[]): SyncPromise<T[]> {\n const aggrPromise = new SyncPromise<T[]>();\n\n let resolvedCount = 0;\n const results: T[] = [];\n const resolve = (idx: number, value: T) => {\n results[idx] = value;\n if (++resolvedCount === valuesOrPromises.length) aggrPromise.resolve(results);\n };\n\n valuesOrPromises.forEach((p, idx) => {\n if (isThenable(p)) {\n p.then((v) => resolve(idx, v));\n } else {\n resolve(idx, p);\n }\n });\n\n return aggrPromise;\n }\n\n resolve(value: T): void {\n // Do nothing, if already resolved.\n if (this.resolved) return;\n\n this.value = value;\n this.resolved = true;\n\n // Run the queued callbacks.\n this.callbacks.forEach((callback) => callback(value));\n this.callbacks.length = 0;\n }\n\n then(callback: (value: T) => unknown): void {\n if (this.resolved) {\n callback(this.value!);\n } else {\n this.callbacks.push(callback);\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.dev/license\n */\n\nimport {ComponentFactory, ComponentFactoryResolver, Injector, NgZone, Type} from '@angular/core';\n\nimport {\n IAnnotatedFunction,\n IAttributes,\n IAugmentedJQuery,\n ICompileService,\n IDirective,\n IInjectorService,\n INgModelController,\n IParseService,\n IScope,\n} from './angular1';\nimport {\n $COMPILE,\n $INJECTOR,\n $PARSE,\n INJECTOR_KEY,\n LAZY_MODULE_REF,\n REQUIRE_INJECTOR,\n REQUIRE_NG_MODEL,\n} from './constants';\nimport {DowngradeComponentAdapter} from './downgrade_component_adapter';\nimport {SyncPromise, Thenable} from './promise_util';\nimport {\n controllerKey,\n getDowngradedModuleCount,\n getTypeName,\n getUpgradeAppType,\n LazyModuleRef,\n UpgradeAppType,\n validateInjectionKey,\n} from './util';\n\n/**\n * @description\n *\n * A helper function that allows an Angular component to be used from AngularJS.\n *\n * *Part of the [upgrade/static](api?query=upgrade%2Fstatic)\n * library for hybrid upgrade apps that support AOT compilation*\n *\n * This helper function returns a factory function to be used for registering\n * an AngularJS wrapper directive for \"downgrading\" an Angular component.\n *\n * @usageNotes\n * ### Examples\n *\n * Let's assume that you have an Angular component called `ng2Heroes` that needs\n * to be made available in AngularJS templates.\n *\n * {@example upgrade/static/ts/full/module.ts region=\"ng2-heroes\"}\n *\n * We must create an AngularJS [directive](https://docs.angularjs.org/guide/directive)\n * that will make this Angular component available inside AngularJS templates.\n * The `downgradeComponent()` function returns a factory function that we\n * can use to define the AngularJS directive that wraps the \"downgraded\" component.\n *\n * {@example upgrade/static/ts/full/module.ts region=\"ng2-heroes-wrapper\"}\n *\n * For more details and examples on downgrading Angular components to AngularJS components please\n * visit the [Upgrade guide](https://angular.io/guide/upgrade#using-angular-components-from-angularjs-code).\n *\n * @param info contains information about the Component that is being downgraded:\n *\n * - `component: Type<any>`: The type of the Component that will be downgraded\n * - `downgradedModule?: string`: The name of the downgraded module (if any) that the component\n * \"belongs to\", as returned by a call to `downgradeModule()`. It is the module, whose\n * corresponding Angular module will be bootstrapped, when the component needs to be instantiated.\n * <br />\n * (This option is only necessary when using `downgradeModule()` to downgrade more than one\n * Angular module.)\n * - `propagateDigest?: boolean`: Whether to perform {@link /api/core/ChangeDetectorRef#detectChanges detectChanges} on the\n * component on every {@link https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$digest $digest}.\n * If set to `false`, change detection will still be performed when any of the component's inputs changes.\n * (Default: true)\n *\n * @returns a factory function that can be used to register the component in an\n * AngularJS module.\n *\n * @publicApi\n */\nexport function downgradeComponent(info: {\n component: Type<any>;\n downgradedModule?: string;\n propagateDigest?: boolean;\n /** @deprecated since v4. This parameter is no longer used */\n inputs?: string[];\n /** @deprecated since v4. This parameter is no longer used */\n outputs?: string[];\n /** @deprecated since v4. This parameter is no longer used */\n selectors?: string[];\n}): any /* angular.IInjectable */ {\n const directiveFactory: IAnnotatedFunction = function (\n $compile: ICompileService,\n $injector: IInjectorService,\n $parse: IParseService,\n ): IDirective {\n const unsafelyOverwriteSignalInputs =\n (info as {unsafelyOverwriteSignalInputs?: boolean}).unsafelyOverwriteSignalInputs ?? false;\n // When using `downgradeModule()`, we need to handle certain things specially. For example:\n // - We always need to attach the component view to the `ApplicationRef` for it to be\n // dirty-checked.\n // - We need to ensure callbacks to Angular APIs (e.g. change detection) are run inside the\n // Angular zone.\n // NOTE: This is not needed, when using `UpgradeModule`, because `$digest()` will be run\n // inside the Angular zone (except if explicitly escaped, in which case we shouldn't\n // force it back in).\n const isNgUpgradeLite = getUpgradeAppType($injector) === UpgradeAppType.Lite;\n const wrapCallback: <T>(cb: () => T) => typeof cb = !isNgUpgradeLite\n ? (cb) => cb\n : (cb) => () => (NgZone.isInAngularZone() ? cb() : ngZone.run(cb));\n let ngZone: NgZone;\n\n // When downgrading multiple modules, special handling is needed wrt injectors.\n const hasMultipleDowngradedModules = isNgUpgradeLite && getDowngradedModuleCount($injector) > 1;\n\n return {\n restrict: 'E',\n terminal: true,\n require: [REQUIRE_INJECTOR, REQUIRE_NG_MODEL],\n // Controller needs to be set so that `angular-component-router.js` (from beta Angular 2)\n // configuration properties can be made available. See:\n // See G3: javascript/angular2/angular1_router_lib.js\n // https://github.com/angular/angular.js/blob/47bf11ee94664367a26ed8c91b9b586d3dd420f5/src/ng/compile.js#L1670-L1691.\n controller: function () {},\n link: (scope: IScope, element: IAugmentedJQuery, attrs: IAttributes, required: any[]) => {\n // We might have to compile the contents asynchronously, because this might have been\n // triggered by `UpgradeNg1ComponentAdapterBuilder`, before the Angular templates have\n // been compiled.\n\n const ngModel: INgModelController = required[1];\n const parentInjector: Injector | Thenable<Injector> | undefined = required[0];\n let moduleInjector: Injector | Thenable<Injector> | undefined = undefined;\n let ranAsync = false;\n\n if (!parentInjector || hasMultipleDowngradedModules) {\n const downgradedModule = info.downgradedModule || '';\n const lazyModuleRefKey = `${LAZY_MODULE_REF}${downgradedModule}`;\n const attemptedAction = `instantiating component '${getTypeName(info.component)}'`;\n\n validateInjectionKey($injector, downgradedModule, lazyModuleRefKey, attemptedAction);\n\n const lazyModuleRef = $injector.get(lazyModuleRefKey) as LazyModuleRef;\n moduleInjector = lazyModuleRef.injector ?? lazyModuleRef.promise;\n }\n\n // Notes:\n //\n // There are two injectors: `finalModuleInjector` and `finalParentInjector` (they might be\n // the same instance, but that is irrelevant):\n // - `finalModuleInjector` is used to retrieve `ComponentFactoryResolver`, thus it must be\n // on the same tree as the `NgModule` that declares this downgraded component.\n // - `finalParentInjector` is used for all other injection purposes.\n // (Note that Angular knows to only traverse the component-tree part of that injector,\n // when looking for an injectable and then switch to the module injector.)\n //\n // There are basically three cases:\n // - If there is no parent component (thus no `parentInjector`), we bootstrap the downgraded\n // `NgModule` and use its injector as both `finalModuleInjector` and\n // `finalParentInjector`.\n // - If there is a parent component (and thus a `parentInjector`) and we are sure that it\n // belongs to the same `NgModule` as this downgraded component (e.g. because there is only\n // one downgraded module, we use that `parentInjector` as both `finalModuleInjector` and\n // `finalParentInjector`.\n // - If there is a parent component, but it may belong to a different `NgModule`, then we\n // use the `parentInjector` as `finalParentInjector` and this downgraded component's\n // declaring `NgModule`'s injector as `finalModuleInjector`.\n // Note 1: If the `NgModule` is already bootstrapped, we just get its injector (we don't\n // bootstrap again).\n // Note 2: It is possible that (while there are multiple downgraded modules) this\n // downgraded component and its parent component both belong to the same NgModule.\n // In that case, we could have used the `parentInjector` as both\n // `finalModuleInjector` and `finalParentInjector`, but (for simplicity) we are\n // treating this case as if they belong to different `NgModule`s. That doesn't\n // really affect anything, since `parentInjector` has `moduleInjector` as ancestor\n // and trying to resolve `ComponentFactoryResolver` from either one will return\n // the same instance.\n\n // If there is a parent component, use its injector as parent injector.\n // If this is a \"top-level\" Angular component, use the module injector.\n const finalParentInjector = parentInjector || moduleInjector!;\n\n // If this is a \"top-level\" Angular component or the parent component may belong to a\n // different `NgModule`, use the module injector for module-specific dependencies.\n // If there is a parent component that belongs to the same `NgModule`, use its injector.\n const finalModuleInjector = moduleInjector || parentInjector!;\n\n const doDowngrade = (injector: Injector, moduleInjector: Injector) => {\n // Retrieve `ComponentFactoryResolver` from the injector tied to the `NgModule` this\n // component belongs to.\n const componentFactoryResolver: ComponentFactoryResolver =\n moduleInjector.get(ComponentFactoryResolver);\n const componentFactory: ComponentFactory<any> =\n componentFactoryResolver.resolveComponentFactory(info.component)!;\n\n if (!componentFactory) {\n throw new Error(`Expecting ComponentFactory for: ${getTypeName(info.component)}`);\n }\n\n const injectorPromise = new ParentInjectorPromise(element);\n const facade = new DowngradeComponentAdapter(\n element,\n attrs,\n scope,\n ngModel,\n injector,\n $compile,\n $parse,\n componentFactory,\n wrapCallback,\n unsafelyOverwriteSignalInputs,\n );\n\n const projectableNodes = facade.compileContents();\n const componentRef = facade.createComponentAndSetup(\n projectableNodes,\n isNgUpgradeLite,\n info.propagateDigest,\n );\n\n injectorPromise.resolve(componentRef.injector);\n\n if (ranAsync) {\n // If this is run async, it is possible that it is not run inside a\n // digest and initial input values will not be detected.\n scope.$evalAsync(() => {});\n }\n };\n\n const downgradeFn = !isNgUpgradeLite\n ? doDowngrade\n : (pInjector: Injector, mInjector: Injector) => {\n if (!ngZone) {\n ngZone = pInjector.get(NgZone);\n }\n\n wrapCallback(() => doDowngrade(pInjector, mInjector))();\n };\n\n // NOTE:\n // Not using `ParentInjectorPromise.all()` (which is inherited from `SyncPromise`), because\n // Closure Compiler (or some related tool) complains:\n // `TypeError: ...$src$downgrade_component_ParentInjectorPromise.all is not a function`\n SyncPromise.all([finalParentInjector, finalModuleInjector]).then(([pInjector, mInjector]) =>\n downgradeFn(pInjector, mInjector),\n );\n\n ranAsync = true;\n },\n };\n };\n\n // bracket-notation because of closure - see #14441\n directiveFactory['$inject'] = [$COMPILE, $INJECTOR, $PARSE];\n return directiveFactory;\n}\n\n/**\n * Synchronous promise-like object to wrap parent injectors,\n * to preserve the synchronous nature of AngularJS's `$compile`.\n */\nclass ParentInjectorPromise extends SyncPromise<Injector> {\n private injectorKey: string = controllerKey(INJECTOR_KEY);\n\n constructor(private element: IAugmentedJQuery) {\n super();\n\n // Store the promise on the element.\n element.data!(this.injectorKey, this);\n }\n\n override resolve(injector: Injector): void {\n // Store the real injector on the element.\n this.element.data!(this.injectorKey, injector);\n\n // Release the element to prevent memory leaks.\n this.element = null!;\n\n // Resolve the promise.\n super.resolve(injector);\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.dev/license\n */\n\nimport {Injector} from '@angular/core';\n\nimport {IInjectorService} from './angular1';\nimport {$INJECTOR, INJECTOR_KEY} from './constants';\nimport {getTypeName, isFunction, validateInjectionKey} from './util';\n\n/**\n * @description\n *\n * A helper function to allow an Angular service to be accessible from AngularJS.\n *\n * *Part of the [upgrade/static](api?query=upgrade%2Fstatic)\n * library for hybrid upgrade apps that support AOT compilation*\n *\n * This helper function returns a factory function that provides access to the Angular\n * service identified by the `token` parameter.\n *\n * @usageNotes\n * ### Examples\n *\n * First ensure that the service to be downgraded is provided in an `NgModule`\n * that will be part of the upgrade application. For example, let's assume we have\n * defined `HeroesService`\n *\n * {@example upgrade/static/ts/full/module.ts region=\"ng2-heroes-service\"}\n *\n * and that we have included this in our upgrade app `NgModule`\n *\n * {@example upgrade/static/ts/full/module.ts region=\"ng2-module\"}\n *\n * Now we can register the `downgradeInjectable` factory function for the service\n * on an AngularJS module.\n *\n * {@example upgrade/static/ts/full/module.ts region=\"downgrade-ng2-heroes-service\"}\n *\n * Inside an AngularJS component's controller we can get hold of the\n * downgraded service via the name we gave when downgrading.\n *\n * {@example upgrade/static/ts/full/module.ts region=\"example-app\"}\n *\n * <div class=\"docs-alert docs-alert-important\">\n *\n * When using `downgradeModule()`, downgraded injectables will not be available until the Angular\n * module that provides them is instantiated. In order to be safe, you need to ensure that the\n * downgraded injectables are not used anywhere _outside_ the part of the app where it is\n * guaranteed that their module has been instantiated.\n *\n * For example, it is _OK_ to use a downgraded service in an upgraded component that is only used\n * from a downgraded Angular component provided by the same Angular module as the injectable, but\n * it is _not OK_ to use it in an AngularJS component that may be used independently of Angular or\n * use it in a downgraded Angular component from a different module.\n *\n * </div>\n *\n * @param token an `InjectionToken` that identifies a service provided from Angular.\n * @param downgradedModule the name of the downgraded module (if any) that the injectable\n * \"belongs to\", as returned by a call to `downgradeModule()`. It is the module, whose injector will\n * be used for instantiating the injectable.<br />\n * (This option is only necessary when using `downgradeModule()` to downgrade more than one Angular\n * module.)\n *\n * @returns a [factory function](https://docs.angularjs.org/guide/di) that can be\n * used to register the service on an AngularJS module.\n *\n * @publicApi\n */\nexport function downgradeInjectable(token: any, downgradedModule: string = ''): Function {\n const factory = function ($injector: IInjectorService) {\n const injectorKey = `${INJECTOR_KEY}${downgradedModule}`;\n const injectableName = isFunction(token) ? getTypeName(token) : String(token);\n const attemptedAction = `instantiating injectable '${injectableName}'`;\n\n validateInjectionKey($injector, downgradedModule, injectorKey, attemptedAction);\n\n try {\n const injector: Injector = $injector.get(injectorKey);\n return injector.get(token);\n } catch (err) {\n throw new Error(`Error while ${attemptedAction}: ${(err as Error).message || err}`);\n }\n };\n (factory as any)['$inject'] = [$INJECTOR];\n\n return factory;\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.dev/license\n */\n\n/**\n * @fileoverview\n * A module to facilitate use of a Trusted Types policy internally within\n * the upgrade package. It lazily constructs the Trusted Types policy, providing\n * helper utilities for promoting strings to Trusted Types. When Trusted Types\n * are not 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 {TrustedHTML, TrustedTypePolicy, TrustedTypePolicyFactory} from './trusted_types_defs';\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 policy = null;\n const windowWithTrustedTypes = window as unknown as {trustedTypes?: TrustedTypePolicyFactory};\n if (windowWithTrustedTypes.trustedTypes) {\n try {\n policy = windowWithTrustedTypes.trustedTypes.createPolicy('angular#unsafe-upgrade', {\n createHTML: (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 legacy AngularJS template to a TrustedHTML, falling back\n * to strings when Trusted Types are not available.\n * @security This is a security-sensitive function; any use of this function\n * must go through security review. In particular, the template string should\n * always be under full control of the application author, as untrusted input\n * can cause an XSS vulnerability.\n */\nexport function trustedHTMLFromLegacyTemplate(html: string): TrustedHTML | string {\n return getPolicy()?.createHTML(html) || html;\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.dev/license\n */\n\nimport {ElementRef, Injector, SimpleChanges} from '@angular/core';\n\nimport {\n DirectiveRequireProperty,\n element as angularElement,\n IAugmentedJQuery,\n ICloneAttachFunction,\n ICompileService,\n IController,\n IControllerService,\n IDirective,\n IHttpBackendService,\n IInjectorService,\n ILinkFn,\n IScope,\n ITemplateCacheService,\n SingleOrListOrMap,\n} from './angular1';\nimport {$COMPILE, $CONTROLLER, $HTTP_BACKEND, $INJECTOR, $TEMPLATE_CACHE} from './constants';\nimport {cleanData, controllerKey, directiveNormalize, isFunction} from './util';\nimport {TrustedHTML} from './security/trusted_types_defs';\nimport {trustedHTMLFromLegacyTemplate} from './security/trusted_types';\n\n// Constants\nconst REQUIRE_PREFIX_RE = /^(\\^\\^?)?(\\?)?(\\^\\^?)?/;\n\n// Interfaces\nexport interface IBindingDestination {\n [key: string]: any;\n $onChanges?: (changes: SimpleChanges) => void;\n}\n\nexport interface IControllerInstance extends IBindingDestination {\n $doCheck?: () => void;\n $onDestroy?: () => void;\n $onInit?: () => void;\n $postLink?: () => void;\n}\n\n// Classes\nexport class UpgradeHelper {\n public readonly $injector: IInjectorService;\n public readonly element: Element;\n public readonly $element: IAugmentedJQuery;\n public readonly directive: IDirective;\n\n private readonly $compile: ICompileService;\n private readonly $controller: IControllerService;\n\n constructor(\n injector: Injector,\n private name: string,\n elementRef: ElementRef,\n directive?: IDirective,\n ) {\n this.$injector = injector.get($INJECTOR);\n this.$compile = this.$injector.get($COMPILE);\n this.$controller = this.$injector.get($CONTROLLER);\n\n this.element = elementRef.nativeElement;\n this.$element = angularElement(this.element);\n\n this.directive = directive ?? UpgradeHelper.getDirective(this.$injector, name);\n }\n\n static getDirective($injector: IInjectorService, name: string): IDirective {\n const directives: IDirective[] = $injector.get(name + 'Directive');\n if (directives.length > 1) {\n throw new Error(`Only support single directive definition for: ${name}`);\n }\n\n const directive = directives[0];\n\n // AngularJS will transform `link: xyz` to `compile: () => xyz`. So we can only tell there was a\n // user-defined `compile` if there is no `link`. In other cases, we will just ignore `compile`.\n if (directive.compile && !directive.link) notSupported(name, 'compile');\n if (directive.replace) notSupported(name, 'replace');\n if (directive.terminal) notSupported(name, 'terminal');\n\n return directive;\n }\n\n static getTemplate(\n $injector: IInjectorService,\n directive: IDirective,\n fetchRemoteTemplate = false,\n $element?: IAugmentedJQuery,\n ): string | TrustedHTML | Promise<string | TrustedHTML> {\n if (directive.template !== undefined) {\n return trustedHTMLFromLegacyTemplate(getOrCall<string>(directive.template, $element));\n } else if (directive.templateUrl) {\n const $templateCache = $injector.get($TEMPLATE_CACHE) as ITemplateCacheService;\n const url = getOrCall<string>(directive.templateUrl, $element);\n const template = $templateCache.get(url);\n\n if (template !== undefined) {\n return trustedHTMLFromLegacyTemplate(template);\n } else if (!fetchRemoteTemplate) {\n throw new Error('loading directive templates asynchronously is not supported');\n }\n\n return new Promise((resolve, reject) => {\n const $httpBackend = $injector.get($HTTP_BACKEND) as IHttpBackendService;\n $httpBackend('GET', url, null, (status: number, response: string) => {\n if (status === 200) {\n resolve(trustedHTMLFromLegacyTemplate($templateCache.put(url, response)));\n } else {\n reject(`GET component template from '${url}' returned '${status}: ${response}'`);\n }\n });\n });\n } else {\n throw new Error(`Directive '${directive.name}' is not a component, it is missing template.`);\n }\n }\n\n buildController(controllerType: IController, $scope: IScope) {\n // TODO: Document that we do not pre-assi