@angular/platform-server 20.3.23 → 20.3.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,12 +1,12 @@
1
1
  /**
2
- * @license Angular v20.3.23
2
+ * @license Angular v20.3.25
3
3
  * (c) 2010-2025 Google LLC. https://angular.dev/
4
4
  * License: MIT
5
5
  */
6
6
 
7
7
  import { PLATFORM_SERVER_PROVIDERS, PlatformState, BEFORE_APP_SERIALIZED, parseUrl, platformServer, INITIAL_CONFIG, createScript } from './server.mjs';
8
8
  export { ServerModule, DominoAdapter as ɵDominoAdapter, ENABLE_DOM_EMULATION as ɵENABLE_DOM_EMULATION, INTERNAL_SERVER_PLATFORM_PROVIDERS as ɵINTERNAL_SERVER_PLATFORM_PROVIDERS, SERVER_RENDER_PROVIDERS as ɵSERVER_RENDER_PROVIDERS } from './server.mjs';
9
- import { makeEnvironmentProviders, InjectionToken, ApplicationRef, ɵstartMeasuring as _startMeasuring, ɵstopMeasuring as _stopMeasuring, ɵIS_HYDRATION_DOM_REUSE_ENABLED as _IS_HYDRATION_DOM_REUSE_ENABLED, ɵannotateForHydration as _annotateForHydration, CSP_NONCE, APP_ID, ɵSSR_CONTENT_INTEGRITY_MARKER as _SSR_CONTENT_INTEGRITY_MARKER, Renderer2, Version } from '@angular/core';
9
+ import { makeEnvironmentProviders, InjectionToken, ApplicationRef, ɵstartMeasuring as _startMeasuring, ɵstopMeasuring as _stopMeasuring, ɵRuntimeError as _RuntimeError, ɵIS_HYDRATION_DOM_REUSE_ENABLED as _IS_HYDRATION_DOM_REUSE_ENABLED, ɵannotateForHydration as _annotateForHydration, CSP_NONCE, APP_ID, ɵSSR_CONTENT_INTEGRITY_MARKER as _SSR_CONTENT_INTEGRITY_MARKER, Renderer2, Version } from '@angular/core';
10
10
  import '@angular/common';
11
11
  import '@angular/platform-browser';
12
12
  import '@angular/common/http';
@@ -320,7 +320,9 @@ function validateAllowedHosts(url, allowedHosts) {
320
320
  const hostname = parsedUrl.hostname;
321
321
  const allowedHostsSet = new Set(allowedHosts);
322
322
  if (!isHostAllowed(hostname, allowedHostsSet)) {
323
- throw new Error(`Host ${url} is not allowed. You can configure \`allowedHosts\` option.`);
323
+ throw new _RuntimeError(5706 /* RuntimeErrorCode.HOST_NOT_ALLOWED */, typeof ngDevMode === 'undefined' || ngDevMode
324
+ ? `Host ${url} is not allowed. You can configure \`allowedHosts\` option.`
325
+ : url);
324
326
  }
325
327
  }
326
328
  }
@@ -357,7 +359,7 @@ function isHostAllowed(hostname, allowedHosts) {
357
359
  /**
358
360
  * @publicApi
359
361
  */
360
- const VERSION = /* @__PURE__ */ new Version('20.3.23');
362
+ const VERSION = /* @__PURE__ */ new Version('20.3.25');
361
363
 
362
364
  export { BEFORE_APP_SERIALIZED, INITIAL_CONFIG, PlatformState, VERSION, platformServer, provideServerRendering, renderApplication, renderModule, SERVER_CONTEXT as ɵSERVER_CONTEXT, isHostAllowed as ɵisHostAllowed, renderInternal as ɵrenderInternal };
363
365
  //# sourceMappingURL=platform-server.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"platform-server.mjs","sources":["../../../../../darwin_arm64-fastbuild-ST-199a4f3c4e20/bin/packages/platform-server/src/provide_server.ts","../../../../../darwin_arm64-fastbuild-ST-199a4f3c4e20/bin/packages/platform-server/src/utils.ts","../../../../../darwin_arm64-fastbuild-ST-199a4f3c4e20/bin/packages/platform-server/src/version.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\nimport {EnvironmentProviders, makeEnvironmentProviders} from '@angular/core';\n\nimport {PLATFORM_SERVER_PROVIDERS} from './server';\n\n/**\n * Sets up providers necessary to enable server rendering functionality for the application.\n *\n * @usageNotes\n *\n * Basic example of how you can add server support to your application:\n * ```ts\n * bootstrapApplication(AppComponent, {\n * providers: [provideServerRendering()]\n * });\n * ```\n *\n * @publicApi\n * @returns A set of providers to setup the server.\n */\nexport function provideServerRendering(): EnvironmentProviders {\n if (typeof ngServerMode === 'undefined') {\n globalThis['ngServerMode'] = true;\n }\n\n return makeEnvironmentProviders([...PLATFORM_SERVER_PROVIDERS]);\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 APP_ID,\n ApplicationRef,\n CSP_NONCE,\n InjectionToken,\n PlatformRef,\n Provider,\n Renderer2,\n StaticProvider,\n Type,\n ɵannotateForHydration as annotateForHydration,\n ɵIS_HYDRATION_DOM_REUSE_ENABLED as IS_HYDRATION_DOM_REUSE_ENABLED,\n ɵSSR_CONTENT_INTEGRITY_MARKER as SSR_CONTENT_INTEGRITY_MARKER,\n ɵstartMeasuring as startMeasuring,\n ɵstopMeasuring as stopMeasuring,\n} from '@angular/core';\nimport {BootstrapContext} from '@angular/platform-browser';\n\nimport {platformServer} from './server';\nimport {PlatformState} from './platform_state';\nimport {BEFORE_APP_SERIALIZED, INITIAL_CONFIG, PlatformConfig} from './tokens';\nimport {createScript} from './transfer_state';\nimport {parseUrl} from './url';\n\n/**\n * Event dispatch (JSAction) script is inlined into the HTML by the build\n * process to avoid extra blocking request on a page. The script looks like this:\n * ```html\n * <script type=\"text/javascript\" id=\"ng-event-dispatch-contract\">...</script>\n * ```\n * This const represents the \"id\" attribute value.\n */\nexport const EVENT_DISPATCH_SCRIPT_ID = 'ng-event-dispatch-contract';\n\ninterface PlatformOptions extends Omit<PlatformConfig, 'document'> {\n document?: string | Document;\n platformProviders?: Provider[];\n}\n\n/**\n * Creates an instance of a server platform (with or without JIT compiler support\n * depending on the `ngJitMode` global const value), using provided options.\n */\nfunction createServerPlatform(options: PlatformOptions): PlatformRef {\n const extraProviders = options.platformProviders ?? [];\n const measuringLabel = 'createServerPlatform';\n startMeasuring(measuringLabel);\n const {document, url} = options;\n\n const platform = platformServer([\n {\n provide: INITIAL_CONFIG,\n useValue: {\n document,\n url,\n },\n },\n extraProviders,\n ]);\n\n stopMeasuring(measuringLabel);\n return platform;\n}\n\n/**\n * Finds and returns inlined event dispatch script if it exists.\n * See the `EVENT_DISPATCH_SCRIPT_ID` const docs for additional info.\n */\nfunction findEventDispatchScript(doc: Document) {\n return doc.getElementById(EVENT_DISPATCH_SCRIPT_ID);\n}\n\n/**\n * Removes inlined event dispatch script if it exists.\n * See the `EVENT_DISPATCH_SCRIPT_ID` const docs for additional info.\n */\nfunction removeEventDispatchScript(doc: Document) {\n findEventDispatchScript(doc)?.remove();\n}\n\n/**\n * Annotate nodes for hydration and remove event dispatch script when not needed.\n */\nfunction prepareForHydration(platformState: PlatformState, applicationRef: ApplicationRef): void {\n const measuringLabel = 'prepareForHydration';\n startMeasuring(measuringLabel);\n const environmentInjector = applicationRef.injector;\n const doc = platformState.getDocument();\n\n if (!environmentInjector.get(IS_HYDRATION_DOM_REUSE_ENABLED, false)) {\n // Hydration is diabled, remove inlined event dispatch script.\n // (which was injected by the build process) from the HTML.\n removeEventDispatchScript(doc);\n\n return;\n }\n\n appendSsrContentIntegrityMarker(doc);\n\n const eventTypesToReplay = annotateForHydration(applicationRef, doc);\n if (eventTypesToReplay.regular.size || eventTypesToReplay.capture.size) {\n insertEventRecordScript(\n environmentInjector.get(APP_ID),\n doc,\n eventTypesToReplay,\n environmentInjector.get(CSP_NONCE, null),\n );\n } else {\n // No events to replay, we should remove inlined event dispatch script\n // (which was injected by the build process) from the HTML.\n removeEventDispatchScript(doc);\n }\n stopMeasuring(measuringLabel);\n}\n\n/**\n * Creates a marker comment node and append it into the `<body>`.\n * Some CDNs have mechanisms to remove all comment node from HTML.\n * This behaviour breaks hydration, so we'll detect on the client side if this\n * marker comment is still available or else throw an error\n */\nfunction appendSsrContentIntegrityMarker(doc: Document) {\n // Adding a ng hydration marker comment\n const comment = doc.createComment(SSR_CONTENT_INTEGRITY_MARKER);\n doc.body.firstChild\n ? doc.body.insertBefore(comment, doc.body.firstChild)\n : doc.body.append(comment);\n}\n\n/**\n * Adds the `ng-server-context` attribute to host elements of all bootstrapped components\n * within a given application.\n */\nfunction appendServerContextInfo(applicationRef: ApplicationRef) {\n const injector = applicationRef.injector;\n let serverContext = sanitizeServerContext(injector.get(SERVER_CONTEXT, DEFAULT_SERVER_CONTEXT));\n applicationRef.components.forEach((componentRef) => {\n const renderer = componentRef.injector.get(Renderer2);\n const element = componentRef.location.nativeElement;\n if (element) {\n renderer.setAttribute(element, 'ng-server-context', serverContext);\n }\n });\n}\n\nfunction insertEventRecordScript(\n appId: string,\n doc: Document,\n eventTypesToReplay: {regular: Set<string>; capture: Set<string>},\n nonce: string | null,\n): void {\n const measuringLabel = 'insertEventRecordScript';\n startMeasuring(measuringLabel);\n const {regular, capture} = eventTypesToReplay;\n const eventDispatchScript = findEventDispatchScript(doc);\n\n // Note: this is only true when build with the CLI tooling, which inserts the script in the HTML\n if (eventDispatchScript) {\n // This is defined in packages/core/primitives/event-dispatch/contract_binary.ts\n const replayScriptContents =\n `window.__jsaction_bootstrap(` +\n `document.body,` +\n `\"${appId}\",` +\n `${JSON.stringify(Array.from(regular))},` +\n `${JSON.stringify(Array.from(capture))}` +\n `);`;\n\n const replayScript = createScript(doc, replayScriptContents, nonce);\n\n // Insert replay script right after inlined event dispatch script, since it\n // relies on `__jsaction_bootstrap` to be defined in the global scope.\n eventDispatchScript.after(replayScript);\n }\n stopMeasuring(measuringLabel);\n}\n\n/**\n * Renders an Angular application to a string.\n *\n * @private\n *\n * @param platformRef - Reference to the Angular platform.\n * @param applicationRef - Reference to the Angular application.\n * @returns A promise that resolves to the rendered string.\n */\nexport async function renderInternal(\n platformRef: PlatformRef,\n applicationRef: ApplicationRef,\n): Promise<string> {\n const platformState = platformRef.injector.get(PlatformState);\n prepareForHydration(platformState, applicationRef);\n appendServerContextInfo(applicationRef);\n\n // Run any BEFORE_APP_SERIALIZED callbacks just before rendering to string.\n const environmentInjector = applicationRef.injector;\n const callbacks = environmentInjector.get(BEFORE_APP_SERIALIZED, null);\n if (callbacks) {\n const asyncCallbacks: Promise<void>[] = [];\n for (const callback of callbacks) {\n try {\n const callbackResult = callback();\n if (callbackResult) {\n asyncCallbacks.push(callbackResult);\n }\n } catch (e) {\n // Ignore exceptions.\n console.warn('Ignoring BEFORE_APP_SERIALIZED Exception: ', e);\n }\n }\n\n if (asyncCallbacks.length) {\n for (const result of await Promise.allSettled(asyncCallbacks)) {\n if (result.status === 'rejected') {\n console.warn('Ignoring BEFORE_APP_SERIALIZED Exception: ', result.reason);\n }\n }\n }\n }\n\n return platformState.renderToString();\n}\n\n/**\n * Destroy the application in a macrotask, this allows pending promises to be settled and errors\n * to be surfaced to the users.\n */\nfunction asyncDestroyPlatform(platformRef: PlatformRef): Promise<void> {\n return new Promise<void>((resolve) => {\n setTimeout(() => {\n platformRef.destroy();\n resolve();\n }, 0);\n });\n}\n\n/**\n * Specifies the value that should be used if no server context value has been provided.\n */\nconst DEFAULT_SERVER_CONTEXT = 'other';\n\n/**\n * An internal token that allows providing extra information about the server context\n * (e.g. whether SSR or SSG was used). The value is a string and characters other\n * than [a-zA-Z0-9\\-] are removed. See the default value in `DEFAULT_SERVER_CONTEXT` const.\n */\nexport const SERVER_CONTEXT = new InjectionToken<string>('SERVER_CONTEXT');\n\n/**\n * Sanitizes provided server context:\n * - removes all characters other than a-z, A-Z, 0-9 and `-`\n * - returns `other` if nothing is provided or the string is empty after sanitization\n */\nfunction sanitizeServerContext(serverContext: string): string {\n const context = serverContext.replace(/[^a-zA-Z0-9\\-]/g, '');\n return context.length > 0 ? context : DEFAULT_SERVER_CONTEXT;\n}\n\n/**\n * Bootstraps an application using provided NgModule and serializes the page content to string.\n *\n * @param moduleType A reference to an NgModule that should be used for bootstrap.\n * @param options Additional configuration for the render operation:\n * - `document` - the document of the page to render, either as an HTML string or\n * as a reference to the `document` instance.\n * - `url` - the URL for the current render request.\n * - `extraProviders` - set of platform level providers for the current render request.\n * - `allowedHosts` - the allowed hosts list for host validation in server-side rendering.\n * @publicApi\n */\nexport async function renderModule<T>(\n moduleType: Type<T>,\n options: {\n document?: string | Document;\n url?: string;\n extraProviders?: StaticProvider[];\n allowedHosts?: Readonly<string>[];\n },\n): Promise<string> {\n const {document, url, extraProviders: platformProviders, allowedHosts} = options;\n validateAllowedHosts(url, allowedHosts);\n const platformRef = createServerPlatform({document, url, platformProviders});\n try {\n const moduleRef = await platformRef.bootstrapModule(moduleType);\n const applicationRef = moduleRef.injector.get(ApplicationRef);\n\n const measuringLabel = 'whenStable';\n startMeasuring(measuringLabel);\n // Block until application is stable.\n await applicationRef.whenStable();\n stopMeasuring(measuringLabel);\n\n return await renderInternal(platformRef, applicationRef);\n } finally {\n await asyncDestroyPlatform(platformRef);\n }\n}\n\n/**\n * Bootstraps an instance of an Angular application and renders it to a string.\n *\n * @usageNotes\n *\n * ```ts\n * import { BootstrapContext, bootstrapApplication } from '@angular/platform-browser';\n * import { renderApplication } from '@angular/platform-server';\n * import { ApplicationConfig } from '@angular/core';\n * import { AppComponent } from './app.component';\n *\n * const appConfig: ApplicationConfig = { providers: [...] };\n * const bootstrap = (context: BootstrapContext) =>\n * bootstrapApplication(AppComponent, config, context);\n * const output = await renderApplication(bootstrap);\n * ```\n *\n * @param bootstrap A method that when invoked returns a promise that returns an `ApplicationRef`\n * instance once resolved. The method is invoked with an `Injector` instance that\n * provides access to the platform-level dependency injection context.\n * @param options Additional configuration for the render operation:\n * - `document` - the document of the page to render, either as an HTML string or\n * as a reference to the `document` instance.\n * - `url` - the URL for the current render request.\n * - `platformProviders` - the platform level providers for the current render request.\n * - `allowedHosts` - the allowed hosts list for host validation in server-side rendering.\n *\n * @returns A Promise, that returns serialized (to a string) rendered page, once resolved.\n *\n * @publicApi\n */\nexport async function renderApplication(\n bootstrap: (context: BootstrapContext) => Promise<ApplicationRef>,\n options: {\n document?: string | Document;\n url?: string;\n platformProviders?: Provider[];\n allowedHosts?: Readonly<string>[];\n },\n): Promise<string> {\n const renderAppLabel = 'renderApplication';\n const bootstrapLabel = 'bootstrap';\n const _renderLabel = '_render';\n const {url, allowedHosts} = options;\n\n validateAllowedHosts(url, allowedHosts);\n\n startMeasuring(renderAppLabel);\n const platformRef = createServerPlatform(options);\n try {\n startMeasuring(bootstrapLabel);\n const applicationRef = await bootstrap({platformRef});\n stopMeasuring(bootstrapLabel);\n\n startMeasuring(_renderLabel);\n\n const measuringLabel = 'whenStable';\n startMeasuring(measuringLabel);\n // Block until application is stable.\n await applicationRef.whenStable();\n stopMeasuring(measuringLabel);\n\n const rendered = await renderInternal(platformRef, applicationRef);\n stopMeasuring(_renderLabel);\n return rendered;\n } finally {\n await asyncDestroyPlatform(platformRef);\n stopMeasuring(renderAppLabel);\n }\n}\n\nfunction validateAllowedHosts(url: string | undefined, allowedHosts: string[] | undefined) {\n if (typeof url === 'string') {\n const parsedUrl = parseUrl(url);\n if (parsedUrl !== null) {\n const hostname = parsedUrl.hostname;\n const allowedHostsSet: ReadonlySet<string> = new Set(allowedHosts);\n if (!isHostAllowed(hostname, allowedHostsSet)) {\n throw new Error(`Host ${url} is not allowed. You can configure \\`allowedHosts\\` option.`);\n }\n }\n }\n}\n\n/**\n * Checks if the hostname is allowed.\n * @param hostname - The hostname to check.\n * @param allowedHosts - A set of allowed hostnames.\n * @returns `true` if the hostname is allowed, `false` otherwise.\n * @note Used also in `@angular/ssr`.\n * @private\n */\nexport function isHostAllowed(hostname: string, allowedHosts: ReadonlySet<string>): boolean {\n if (allowedHosts.has('*') || allowedHosts.has(hostname)) {\n return true;\n }\n\n for (const allowedHost of allowedHosts) {\n if (!allowedHost.startsWith('*.')) {\n continue;\n }\n\n const domain = allowedHost.slice(1);\n if (hostname.endsWith(domain)) {\n return true;\n }\n }\n\n return false;\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 * @module\n * @description\n * Entry point for all public APIs of the platform-server package.\n */\n\nimport {Version} from '@angular/core';\n\n/**\n * @publicApi\n */\nexport const VERSION = /* @__PURE__ */ new Version('20.3.23');\n"],"names":["startMeasuring","stopMeasuring","IS_HYDRATION_DOM_REUSE_ENABLED","annotateForHydration","SSR_CONTENT_INTEGRITY_MARKER"],"mappings":"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"}
1
+ {"version":3,"file":"platform-server.mjs","sources":["../../../../../k8-fastbuild-ST-199a4f3c4e20/bin/packages/platform-server/src/provide_server.ts","../../../../../k8-fastbuild-ST-199a4f3c4e20/bin/packages/platform-server/src/utils.ts","../../../../../k8-fastbuild-ST-199a4f3c4e20/bin/packages/platform-server/src/version.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\nimport {EnvironmentProviders, makeEnvironmentProviders} from '@angular/core';\n\nimport {PLATFORM_SERVER_PROVIDERS} from './server';\n\n/**\n * Sets up providers necessary to enable server rendering functionality for the application.\n *\n * @usageNotes\n *\n * Basic example of how you can add server support to your application:\n * ```ts\n * bootstrapApplication(AppComponent, {\n * providers: [provideServerRendering()]\n * });\n * ```\n *\n * @publicApi\n * @returns A set of providers to setup the server.\n */\nexport function provideServerRendering(): EnvironmentProviders {\n if (typeof ngServerMode === 'undefined') {\n globalThis['ngServerMode'] = true;\n }\n\n return makeEnvironmentProviders([...PLATFORM_SERVER_PROVIDERS]);\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 APP_ID,\n ApplicationRef,\n CSP_NONCE,\n InjectionToken,\n PlatformRef,\n Provider,\n Renderer2,\n StaticProvider,\n Type,\n ɵannotateForHydration as annotateForHydration,\n ɵIS_HYDRATION_DOM_REUSE_ENABLED as IS_HYDRATION_DOM_REUSE_ENABLED,\n ɵSSR_CONTENT_INTEGRITY_MARKER as SSR_CONTENT_INTEGRITY_MARKER,\n ɵstartMeasuring as startMeasuring,\n ɵstopMeasuring as stopMeasuring,\n ɵRuntimeError as RuntimeError,\n} from '@angular/core';\nimport {BootstrapContext} from '@angular/platform-browser';\n\nimport {RuntimeErrorCode} from './errors';\nimport {platformServer} from './server';\nimport {PlatformState} from './platform_state';\nimport {BEFORE_APP_SERIALIZED, INITIAL_CONFIG, PlatformConfig} from './tokens';\nimport {createScript} from './transfer_state';\nimport {parseUrl} from './url';\n\n/**\n * Event dispatch (JSAction) script is inlined into the HTML by the build\n * process to avoid extra blocking request on a page. The script looks like this:\n * ```html\n * <script type=\"text/javascript\" id=\"ng-event-dispatch-contract\">...</script>\n * ```\n * This const represents the \"id\" attribute value.\n */\nexport const EVENT_DISPATCH_SCRIPT_ID = 'ng-event-dispatch-contract';\n\ninterface PlatformOptions extends Omit<PlatformConfig, 'document'> {\n document?: string | Document;\n platformProviders?: Provider[];\n}\n\n/**\n * Creates an instance of a server platform (with or without JIT compiler support\n * depending on the `ngJitMode` global const value), using provided options.\n */\nfunction createServerPlatform(options: PlatformOptions): PlatformRef {\n const extraProviders = options.platformProviders ?? [];\n const measuringLabel = 'createServerPlatform';\n startMeasuring(measuringLabel);\n const {document, url} = options;\n\n const platform = platformServer([\n {\n provide: INITIAL_CONFIG,\n useValue: {\n document,\n url,\n },\n },\n extraProviders,\n ]);\n\n stopMeasuring(measuringLabel);\n return platform;\n}\n\n/**\n * Finds and returns inlined event dispatch script if it exists.\n * See the `EVENT_DISPATCH_SCRIPT_ID` const docs for additional info.\n */\nfunction findEventDispatchScript(doc: Document) {\n return doc.getElementById(EVENT_DISPATCH_SCRIPT_ID);\n}\n\n/**\n * Removes inlined event dispatch script if it exists.\n * See the `EVENT_DISPATCH_SCRIPT_ID` const docs for additional info.\n */\nfunction removeEventDispatchScript(doc: Document) {\n findEventDispatchScript(doc)?.remove();\n}\n\n/**\n * Annotate nodes for hydration and remove event dispatch script when not needed.\n */\nfunction prepareForHydration(platformState: PlatformState, applicationRef: ApplicationRef): void {\n const measuringLabel = 'prepareForHydration';\n startMeasuring(measuringLabel);\n const environmentInjector = applicationRef.injector;\n const doc = platformState.getDocument();\n\n if (!environmentInjector.get(IS_HYDRATION_DOM_REUSE_ENABLED, false)) {\n // Hydration is diabled, remove inlined event dispatch script.\n // (which was injected by the build process) from the HTML.\n removeEventDispatchScript(doc);\n\n return;\n }\n\n appendSsrContentIntegrityMarker(doc);\n\n const eventTypesToReplay = annotateForHydration(applicationRef, doc);\n if (eventTypesToReplay.regular.size || eventTypesToReplay.capture.size) {\n insertEventRecordScript(\n environmentInjector.get(APP_ID),\n doc,\n eventTypesToReplay,\n environmentInjector.get(CSP_NONCE, null),\n );\n } else {\n // No events to replay, we should remove inlined event dispatch script\n // (which was injected by the build process) from the HTML.\n removeEventDispatchScript(doc);\n }\n stopMeasuring(measuringLabel);\n}\n\n/**\n * Creates a marker comment node and append it into the `<body>`.\n * Some CDNs have mechanisms to remove all comment node from HTML.\n * This behaviour breaks hydration, so we'll detect on the client side if this\n * marker comment is still available or else throw an error\n */\nfunction appendSsrContentIntegrityMarker(doc: Document) {\n // Adding a ng hydration marker comment\n const comment = doc.createComment(SSR_CONTENT_INTEGRITY_MARKER);\n doc.body.firstChild\n ? doc.body.insertBefore(comment, doc.body.firstChild)\n : doc.body.append(comment);\n}\n\n/**\n * Adds the `ng-server-context` attribute to host elements of all bootstrapped components\n * within a given application.\n */\nfunction appendServerContextInfo(applicationRef: ApplicationRef) {\n const injector = applicationRef.injector;\n let serverContext = sanitizeServerContext(injector.get(SERVER_CONTEXT, DEFAULT_SERVER_CONTEXT));\n applicationRef.components.forEach((componentRef) => {\n const renderer = componentRef.injector.get(Renderer2);\n const element = componentRef.location.nativeElement;\n if (element) {\n renderer.setAttribute(element, 'ng-server-context', serverContext);\n }\n });\n}\n\nfunction insertEventRecordScript(\n appId: string,\n doc: Document,\n eventTypesToReplay: {regular: Set<string>; capture: Set<string>},\n nonce: string | null,\n): void {\n const measuringLabel = 'insertEventRecordScript';\n startMeasuring(measuringLabel);\n const {regular, capture} = eventTypesToReplay;\n const eventDispatchScript = findEventDispatchScript(doc);\n\n // Note: this is only true when build with the CLI tooling, which inserts the script in the HTML\n if (eventDispatchScript) {\n // This is defined in packages/core/primitives/event-dispatch/contract_binary.ts\n const replayScriptContents =\n `window.__jsaction_bootstrap(` +\n `document.body,` +\n `\"${appId}\",` +\n `${JSON.stringify(Array.from(regular))},` +\n `${JSON.stringify(Array.from(capture))}` +\n `);`;\n\n const replayScript = createScript(doc, replayScriptContents, nonce);\n\n // Insert replay script right after inlined event dispatch script, since it\n // relies on `__jsaction_bootstrap` to be defined in the global scope.\n eventDispatchScript.after(replayScript);\n }\n stopMeasuring(measuringLabel);\n}\n\n/**\n * Renders an Angular application to a string.\n *\n * @private\n *\n * @param platformRef - Reference to the Angular platform.\n * @param applicationRef - Reference to the Angular application.\n * @returns A promise that resolves to the rendered string.\n */\nexport async function renderInternal(\n platformRef: PlatformRef,\n applicationRef: ApplicationRef,\n): Promise<string> {\n const platformState = platformRef.injector.get(PlatformState);\n prepareForHydration(platformState, applicationRef);\n appendServerContextInfo(applicationRef);\n\n // Run any BEFORE_APP_SERIALIZED callbacks just before rendering to string.\n const environmentInjector = applicationRef.injector;\n const callbacks = environmentInjector.get(BEFORE_APP_SERIALIZED, null);\n if (callbacks) {\n const asyncCallbacks: Promise<void>[] = [];\n for (const callback of callbacks) {\n try {\n const callbackResult = callback();\n if (callbackResult) {\n asyncCallbacks.push(callbackResult);\n }\n } catch (e) {\n // Ignore exceptions.\n console.warn('Ignoring BEFORE_APP_SERIALIZED Exception: ', e);\n }\n }\n\n if (asyncCallbacks.length) {\n for (const result of await Promise.allSettled(asyncCallbacks)) {\n if (result.status === 'rejected') {\n console.warn('Ignoring BEFORE_APP_SERIALIZED Exception: ', result.reason);\n }\n }\n }\n }\n\n return platformState.renderToString();\n}\n\n/**\n * Destroy the application in a macrotask, this allows pending promises to be settled and errors\n * to be surfaced to the users.\n */\nfunction asyncDestroyPlatform(platformRef: PlatformRef): Promise<void> {\n return new Promise<void>((resolve) => {\n setTimeout(() => {\n platformRef.destroy();\n resolve();\n }, 0);\n });\n}\n\n/**\n * Specifies the value that should be used if no server context value has been provided.\n */\nconst DEFAULT_SERVER_CONTEXT = 'other';\n\n/**\n * An internal token that allows providing extra information about the server context\n * (e.g. whether SSR or SSG was used). The value is a string and characters other\n * than [a-zA-Z0-9\\-] are removed. See the default value in `DEFAULT_SERVER_CONTEXT` const.\n */\nexport const SERVER_CONTEXT = new InjectionToken<string>('SERVER_CONTEXT');\n\n/**\n * Sanitizes provided server context:\n * - removes all characters other than a-z, A-Z, 0-9 and `-`\n * - returns `other` if nothing is provided or the string is empty after sanitization\n */\nfunction sanitizeServerContext(serverContext: string): string {\n const context = serverContext.replace(/[^a-zA-Z0-9\\-]/g, '');\n return context.length > 0 ? context : DEFAULT_SERVER_CONTEXT;\n}\n\n/**\n * Bootstraps an application using provided NgModule and serializes the page content to string.\n *\n * @param moduleType A reference to an NgModule that should be used for bootstrap.\n * @param options Additional configuration for the render operation:\n * - `document` - the document of the page to render, either as an HTML string or\n * as a reference to the `document` instance.\n * - `url` - the URL for the current render request.\n * - `extraProviders` - set of platform level providers for the current render request.\n * - `allowedHosts` - the allowed hosts list for host validation in server-side rendering.\n * @publicApi\n */\nexport async function renderModule<T>(\n moduleType: Type<T>,\n options: {\n document?: string | Document;\n url?: string;\n extraProviders?: StaticProvider[];\n allowedHosts?: Readonly<string>[];\n },\n): Promise<string> {\n const {document, url, extraProviders: platformProviders, allowedHosts} = options;\n validateAllowedHosts(url, allowedHosts);\n const platformRef = createServerPlatform({document, url, platformProviders});\n try {\n const moduleRef = await platformRef.bootstrapModule(moduleType);\n const applicationRef = moduleRef.injector.get(ApplicationRef);\n\n const measuringLabel = 'whenStable';\n startMeasuring(measuringLabel);\n // Block until application is stable.\n await applicationRef.whenStable();\n stopMeasuring(measuringLabel);\n\n return await renderInternal(platformRef, applicationRef);\n } finally {\n await asyncDestroyPlatform(platformRef);\n }\n}\n\n/**\n * Bootstraps an instance of an Angular application and renders it to a string.\n *\n * @usageNotes\n *\n * ```ts\n * import { BootstrapContext, bootstrapApplication } from '@angular/platform-browser';\n * import { renderApplication } from '@angular/platform-server';\n * import { ApplicationConfig } from '@angular/core';\n * import { AppComponent } from './app.component';\n *\n * const appConfig: ApplicationConfig = { providers: [...] };\n * const bootstrap = (context: BootstrapContext) =>\n * bootstrapApplication(AppComponent, config, context);\n * const output = await renderApplication(bootstrap);\n * ```\n *\n * @param bootstrap A method that when invoked returns a promise that returns an `ApplicationRef`\n * instance once resolved. The method is invoked with an `Injector` instance that\n * provides access to the platform-level dependency injection context.\n * @param options Additional configuration for the render operation:\n * - `document` - the document of the page to render, either as an HTML string or\n * as a reference to the `document` instance.\n * - `url` - the URL for the current render request.\n * - `platformProviders` - the platform level providers for the current render request.\n * - `allowedHosts` - the allowed hosts list for host validation in server-side rendering.\n *\n * @returns A Promise, that returns serialized (to a string) rendered page, once resolved.\n *\n * @publicApi\n */\nexport async function renderApplication(\n bootstrap: (context: BootstrapContext) => Promise<ApplicationRef>,\n options: {\n document?: string | Document;\n url?: string;\n platformProviders?: Provider[];\n allowedHosts?: Readonly<string>[];\n },\n): Promise<string> {\n const renderAppLabel = 'renderApplication';\n const bootstrapLabel = 'bootstrap';\n const _renderLabel = '_render';\n const {url, allowedHosts} = options;\n\n validateAllowedHosts(url, allowedHosts);\n\n startMeasuring(renderAppLabel);\n const platformRef = createServerPlatform(options);\n try {\n startMeasuring(bootstrapLabel);\n const applicationRef = await bootstrap({platformRef});\n stopMeasuring(bootstrapLabel);\n\n startMeasuring(_renderLabel);\n\n const measuringLabel = 'whenStable';\n startMeasuring(measuringLabel);\n // Block until application is stable.\n await applicationRef.whenStable();\n stopMeasuring(measuringLabel);\n\n const rendered = await renderInternal(platformRef, applicationRef);\n stopMeasuring(_renderLabel);\n return rendered;\n } finally {\n await asyncDestroyPlatform(platformRef);\n stopMeasuring(renderAppLabel);\n }\n}\n\nfunction validateAllowedHosts(url: string | undefined, allowedHosts: string[] | undefined) {\n if (typeof url === 'string') {\n const parsedUrl = parseUrl(url);\n if (parsedUrl !== null) {\n const hostname = parsedUrl.hostname;\n const allowedHostsSet: ReadonlySet<string> = new Set(allowedHosts);\n if (!isHostAllowed(hostname, allowedHostsSet)) {\n throw new RuntimeError(\n RuntimeErrorCode.HOST_NOT_ALLOWED,\n typeof ngDevMode === 'undefined' || ngDevMode\n ? `Host ${url} is not allowed. You can configure \\`allowedHosts\\` option.`\n : url,\n );\n }\n }\n }\n}\n\n/**\n * Checks if the hostname is allowed.\n * @param hostname - The hostname to check.\n * @param allowedHosts - A set of allowed hostnames.\n * @returns `true` if the hostname is allowed, `false` otherwise.\n * @note Used also in `@angular/ssr`.\n * @private\n */\nexport function isHostAllowed(hostname: string, allowedHosts: ReadonlySet<string>): boolean {\n if (allowedHosts.has('*') || allowedHosts.has(hostname)) {\n return true;\n }\n\n for (const allowedHost of allowedHosts) {\n if (!allowedHost.startsWith('*.')) {\n continue;\n }\n\n const domain = allowedHost.slice(1);\n if (hostname.endsWith(domain)) {\n return true;\n }\n }\n\n return false;\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 * @module\n * @description\n * Entry point for all public APIs of the platform-server package.\n */\n\nimport {Version} from '@angular/core';\n\n/**\n * @publicApi\n */\nexport const VERSION = /* @__PURE__ */ new Version('20.3.25');\n"],"names":["startMeasuring","stopMeasuring","IS_HYDRATION_DOM_REUSE_ENABLED","annotateForHydration","SSR_CONTENT_INTEGRITY_MARKER","RuntimeError"],"mappings":";;;;;;;;;;;;;;AAYA;;;;;;;;;;;;;;AAcG;SACa,sBAAsB,GAAA;AACpC,IAAA,IAAI,OAAO,YAAY,KAAK,WAAW,EAAE;AACvC,QAAA,UAAU,CAAC,cAAc,CAAC,GAAG,IAAI;;AAGnC,IAAA,OAAO,wBAAwB,CAAC,CAAC,GAAG,yBAAyB,CAAC,CAAC;AACjE;;ACCA;;;;;;;AAOG;AACI,MAAM,wBAAwB,GAAG,4BAA4B;AAOpE;;;AAGG;AACH,SAAS,oBAAoB,CAAC,OAAwB,EAAA;AACpD,IAAA,MAAM,cAAc,GAAG,OAAO,CAAC,iBAAiB,IAAI,EAAE;IACtD,MAAM,cAAc,GAAG,sBAAsB;IAC7CA,eAAc,CAAC,cAAc,CAAC;AAC9B,IAAA,MAAM,EAAC,QAAQ,EAAE,GAAG,EAAC,GAAG,OAAO;IAE/B,MAAM,QAAQ,GAAG,cAAc,CAAC;AAC9B,QAAA;AACE,YAAA,OAAO,EAAE,cAAc;AACvB,YAAA,QAAQ,EAAE;gBACR,QAAQ;gBACR,GAAG;AACJ,aAAA;AACF,SAAA;QACD,cAAc;AACf,KAAA,CAAC;IAEFC,cAAa,CAAC,cAAc,CAAC;AAC7B,IAAA,OAAO,QAAQ;AACjB;AAEA;;;AAGG;AACH,SAAS,uBAAuB,CAAC,GAAa,EAAA;AAC5C,IAAA,OAAO,GAAG,CAAC,cAAc,CAAC,wBAAwB,CAAC;AACrD;AAEA;;;AAGG;AACH,SAAS,yBAAyB,CAAC,GAAa,EAAA;AAC9C,IAAA,uBAAuB,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE;AACxC;AAEA;;AAEG;AACH,SAAS,mBAAmB,CAAC,aAA4B,EAAE,cAA8B,EAAA;IACvF,MAAM,cAAc,GAAG,qBAAqB;IAC5CD,eAAc,CAAC,cAAc,CAAC;AAC9B,IAAA,MAAM,mBAAmB,GAAG,cAAc,CAAC,QAAQ;AACnD,IAAA,MAAM,GAAG,GAAG,aAAa,CAAC,WAAW,EAAE;IAEvC,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAACE,+BAA8B,EAAE,KAAK,CAAC,EAAE;;;QAGnE,yBAAyB,CAAC,GAAG,CAAC;QAE9B;;IAGF,+BAA+B,CAAC,GAAG,CAAC;IAEpC,MAAM,kBAAkB,GAAGC,qBAAoB,CAAC,cAAc,EAAE,GAAG,CAAC;AACpE,IAAA,IAAI,kBAAkB,CAAC,OAAO,CAAC,IAAI,IAAI,kBAAkB,CAAC,OAAO,CAAC,IAAI,EAAE;QACtE,uBAAuB,CACrB,mBAAmB,CAAC,GAAG,CAAC,MAAM,CAAC,EAC/B,GAAG,EACH,kBAAkB,EAClB,mBAAmB,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,CACzC;;SACI;;;QAGL,yBAAyB,CAAC,GAAG,CAAC;;IAEhCF,cAAa,CAAC,cAAc,CAAC;AAC/B;AAEA;;;;;AAKG;AACH,SAAS,+BAA+B,CAAC,GAAa,EAAA;;IAEpD,MAAM,OAAO,GAAG,GAAG,CAAC,aAAa,CAACG,6BAA4B,CAAC;IAC/D,GAAG,CAAC,IAAI,CAAC;AACP,UAAE,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,GAAG,CAAC,IAAI,CAAC,UAAU;UAClD,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;AAC9B;AAEA;;;AAGG;AACH,SAAS,uBAAuB,CAAC,cAA8B,EAAA;AAC7D,IAAA,MAAM,QAAQ,GAAG,cAAc,CAAC,QAAQ;AACxC,IAAA,IAAI,aAAa,GAAG,qBAAqB,CAAC,QAAQ,CAAC,GAAG,CAAC,cAAc,EAAE,sBAAsB,CAAC,CAAC;IAC/F,cAAc,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,YAAY,KAAI;QACjD,MAAM,QAAQ,GAAG,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC;AACrD,QAAA,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,CAAC,aAAa;QACnD,IAAI,OAAO,EAAE;YACX,QAAQ,CAAC,YAAY,CAAC,OAAO,EAAE,mBAAmB,EAAE,aAAa,CAAC;;AAEtE,KAAC,CAAC;AACJ;AAEA,SAAS,uBAAuB,CAC9B,KAAa,EACb,GAAa,EACb,kBAAgE,EAChE,KAAoB,EAAA;IAEpB,MAAM,cAAc,GAAG,yBAAyB;IAChDJ,eAAc,CAAC,cAAc,CAAC;AAC9B,IAAA,MAAM,EAAC,OAAO,EAAE,OAAO,EAAC,GAAG,kBAAkB;AAC7C,IAAA,MAAM,mBAAmB,GAAG,uBAAuB,CAAC,GAAG,CAAC;;IAGxD,IAAI,mBAAmB,EAAE;;QAEvB,MAAM,oBAAoB,GACxB,CAA8B,4BAAA,CAAA;YAC9B,CAAgB,cAAA,CAAA;AAChB,YAAA,CAAA,CAAA,EAAI,KAAK,CAAI,EAAA,CAAA;YACb,CAAG,EAAA,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAG,CAAA,CAAA;YACzC,CAAG,EAAA,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAE,CAAA;AACxC,YAAA,CAAA,EAAA,CAAI;QAEN,MAAM,YAAY,GAAG,YAAY,CAAC,GAAG,EAAE,oBAAoB,EAAE,KAAK,CAAC;;;AAInE,QAAA,mBAAmB,CAAC,KAAK,CAAC,YAAY,CAAC;;IAEzCC,cAAa,CAAC,cAAc,CAAC;AAC/B;AAEA;;;;;;;;AAQG;AACI,eAAe,cAAc,CAClC,WAAwB,EACxB,cAA8B,EAAA;IAE9B,MAAM,aAAa,GAAG,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC,aAAa,CAAC;AAC7D,IAAA,mBAAmB,CAAC,aAAa,EAAE,cAAc,CAAC;IAClD,uBAAuB,CAAC,cAAc,CAAC;;AAGvC,IAAA,MAAM,mBAAmB,GAAG,cAAc,CAAC,QAAQ;IACnD,MAAM,SAAS,GAAG,mBAAmB,CAAC,GAAG,CAAC,qBAAqB,EAAE,IAAI,CAAC;IACtE,IAAI,SAAS,EAAE;QACb,MAAM,cAAc,GAAoB,EAAE;AAC1C,QAAA,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE;AAChC,YAAA,IAAI;AACF,gBAAA,MAAM,cAAc,GAAG,QAAQ,EAAE;gBACjC,IAAI,cAAc,EAAE;AAClB,oBAAA,cAAc,CAAC,IAAI,CAAC,cAAc,CAAC;;;YAErC,OAAO,CAAC,EAAE;;AAEV,gBAAA,OAAO,CAAC,IAAI,CAAC,4CAA4C,EAAE,CAAC,CAAC;;;AAIjE,QAAA,IAAI,cAAc,CAAC,MAAM,EAAE;YACzB,KAAK,MAAM,MAAM,IAAI,MAAM,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE;AAC7D,gBAAA,IAAI,MAAM,CAAC,MAAM,KAAK,UAAU,EAAE;oBAChC,OAAO,CAAC,IAAI,CAAC,4CAA4C,EAAE,MAAM,CAAC,MAAM,CAAC;;;;;AAMjF,IAAA,OAAO,aAAa,CAAC,cAAc,EAAE;AACvC;AAEA;;;AAGG;AACH,SAAS,oBAAoB,CAAC,WAAwB,EAAA;AACpD,IAAA,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,KAAI;QACnC,UAAU,CAAC,MAAK;YACd,WAAW,CAAC,OAAO,EAAE;AACrB,YAAA,OAAO,EAAE;SACV,EAAE,CAAC,CAAC;AACP,KAAC,CAAC;AACJ;AAEA;;AAEG;AACH,MAAM,sBAAsB,GAAG,OAAO;AAEtC;;;;AAIG;MACU,cAAc,GAAG,IAAI,cAAc,CAAS,gBAAgB;AAEzE;;;;AAIG;AACH,SAAS,qBAAqB,CAAC,aAAqB,EAAA;IAClD,MAAM,OAAO,GAAG,aAAa,CAAC,OAAO,CAAC,iBAAiB,EAAE,EAAE,CAAC;AAC5D,IAAA,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,GAAG,OAAO,GAAG,sBAAsB;AAC9D;AAEA;;;;;;;;;;;AAWG;AACI,eAAe,YAAY,CAChC,UAAmB,EACnB,OAKC,EAAA;AAED,IAAA,MAAM,EAAC,QAAQ,EAAE,GAAG,EAAE,cAAc,EAAE,iBAAiB,EAAE,YAAY,EAAC,GAAG,OAAO;AAChF,IAAA,oBAAoB,CAAC,GAAG,EAAE,YAAY,CAAC;AACvC,IAAA,MAAM,WAAW,GAAG,oBAAoB,CAAC,EAAC,QAAQ,EAAE,GAAG,EAAE,iBAAiB,EAAC,CAAC;AAC5E,IAAA,IAAI;QACF,MAAM,SAAS,GAAG,MAAM,WAAW,CAAC,eAAe,CAAC,UAAU,CAAC;QAC/D,MAAM,cAAc,GAAG,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,cAAc,CAAC;QAE7D,MAAM,cAAc,GAAG,YAAY;QACnCD,eAAc,CAAC,cAAc,CAAC;;AAE9B,QAAA,MAAM,cAAc,CAAC,UAAU,EAAE;QACjCC,cAAa,CAAC,cAAc,CAAC;AAE7B,QAAA,OAAO,MAAM,cAAc,CAAC,WAAW,EAAE,cAAc,CAAC;;YAChD;AACR,QAAA,MAAM,oBAAoB,CAAC,WAAW,CAAC;;AAE3C;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BG;AACI,eAAe,iBAAiB,CACrC,SAAiE,EACjE,OAKC,EAAA;IAED,MAAM,cAAc,GAAG,mBAAmB;IAC1C,MAAM,cAAc,GAAG,WAAW;IAClC,MAAM,YAAY,GAAG,SAAS;AAC9B,IAAA,MAAM,EAAC,GAAG,EAAE,YAAY,EAAC,GAAG,OAAO;AAEnC,IAAA,oBAAoB,CAAC,GAAG,EAAE,YAAY,CAAC;IAEvCD,eAAc,CAAC,cAAc,CAAC;AAC9B,IAAA,MAAM,WAAW,GAAG,oBAAoB,CAAC,OAAO,CAAC;AACjD,IAAA,IAAI;QACFA,eAAc,CAAC,cAAc,CAAC;QAC9B,MAAM,cAAc,GAAG,MAAM,SAAS,CAAC,EAAC,WAAW,EAAC,CAAC;QACrDC,cAAa,CAAC,cAAc,CAAC;QAE7BD,eAAc,CAAC,YAAY,CAAC;QAE5B,MAAM,cAAc,GAAG,YAAY;QACnCA,eAAc,CAAC,cAAc,CAAC;;AAE9B,QAAA,MAAM,cAAc,CAAC,UAAU,EAAE;QACjCC,cAAa,CAAC,cAAc,CAAC;QAE7B,MAAM,QAAQ,GAAG,MAAM,cAAc,CAAC,WAAW,EAAE,cAAc,CAAC;QAClEA,cAAa,CAAC,YAAY,CAAC;AAC3B,QAAA,OAAO,QAAQ;;YACP;AACR,QAAA,MAAM,oBAAoB,CAAC,WAAW,CAAC;QACvCA,cAAa,CAAC,cAAc,CAAC;;AAEjC;AAEA,SAAS,oBAAoB,CAAC,GAAuB,EAAE,YAAkC,EAAA;AACvF,IAAA,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE;AAC3B,QAAA,MAAM,SAAS,GAAG,QAAQ,CAAC,GAAG,CAAC;AAC/B,QAAA,IAAI,SAAS,KAAK,IAAI,EAAE;AACtB,YAAA,MAAM,QAAQ,GAAG,SAAS,CAAC,QAAQ;AACnC,YAAA,MAAM,eAAe,GAAwB,IAAI,GAAG,CAAC,YAAY,CAAC;YAClE,IAAI,CAAC,aAAa,CAAC,QAAQ,EAAE,eAAe,CAAC,EAAE;gBAC7C,MAAM,IAAII,aAAY,CAEpB,IAAA,0CAAA,OAAO,SAAS,KAAK,WAAW,IAAI;sBAChC,CAAQ,KAAA,EAAA,GAAG,CAA6D,2DAAA;sBACxE,GAAG,CACR;;;;AAIT;AAEA;;;;;;;AAOG;AACa,SAAA,aAAa,CAAC,QAAgB,EAAE,YAAiC,EAAA;AAC/E,IAAA,IAAI,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE;AACvD,QAAA,OAAO,IAAI;;AAGb,IAAA,KAAK,MAAM,WAAW,IAAI,YAAY,EAAE;QACtC,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE;YACjC;;QAGF,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC;AACnC,QAAA,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE;AAC7B,YAAA,OAAO,IAAI;;;AAIf,IAAA,OAAO,KAAK;AACd;;AC7ZA;;;;AAIG;AAIH;;AAEG;AACU,MAAA,OAAO,mBAAmB,IAAI,OAAO,CAAC,mBAAmB;;;;"}
@@ -1,12 +1,12 @@
1
1
  /**
2
- * @license Angular v20.3.23
2
+ * @license Angular v20.3.25
3
3
  * (c) 2010-2025 Google LLC. https://angular.dev/
4
4
  * License: MIT
5
5
  */
6
6
 
7
7
  import { ɵsetRootDomAdapter as _setRootDomAdapter, DOCUMENT, XhrFactory, PlatformLocation, ɵgetDOM as _getDOM, ɵPLATFORM_SERVER_ID as _PLATFORM_SERVER_ID, ViewportScroller, ɵNullViewportScroller as _NullViewportScroller } from '@angular/common';
8
8
  import * as i0 from '@angular/core';
9
- import { InjectionToken, inject, Injector, ɵstartMeasuring as _startMeasuring, ɵstopMeasuring as _stopMeasuring, Injectable, Inject, Optional, APP_ID, TransferState, PLATFORM_ID, PLATFORM_INITIALIZER, NgModule, ɵsetDocument as _setDocument, createPlatformFactory, platformCore, Testability, ɵTESTABILITY as _TESTABILITY } from '@angular/core';
9
+ import { ɵRuntimeError as _RuntimeError, InjectionToken, inject, Injector, ɵstartMeasuring as _startMeasuring, ɵstopMeasuring as _stopMeasuring, Injectable, Inject, Optional, APP_ID, TransferState, PLATFORM_ID, PLATFORM_INITIALIZER, NgModule, ɵsetDocument as _setDocument, createPlatformFactory, platformCore, Testability, ɵTESTABILITY as _TESTABILITY } from '@angular/core';
10
10
  import { ɵBrowserDomAdapter as _BrowserDomAdapter, EventManagerPlugin, EVENT_MANAGER_PLUGINS, BrowserModule } from '@angular/platform-browser';
11
11
  import { ɵHTTP_ROOT_INTERCEPTOR_FNS as _HTTP_ROOT_INTERCEPTOR_FNS } from '@angular/common/http';
12
12
  import { Subject } from 'rxjs';
@@ -757,6 +757,7 @@ function requireNodeUtils () {
757
757
  XMP: true,
758
758
  IFRAME: true,
759
759
  NOEMBED: true,
760
+ NOSCRIPT: true,
760
761
  NOFRAMES: true,
761
762
  PLAINTEXT: true
762
763
  };
@@ -865,12 +866,15 @@ function requireNodeUtils () {
865
866
  if (!rawText.toLowerCase().includes(parentClosingTag)) {
866
867
  return rawText; // fast path
867
868
  }
868
- const result = [...rawText];
869
- const matches = rawText.matchAll(new RegExp(parentClosingTag, 'ig'));
870
- for (const match of matches) {
871
- result[match.index] = '&lt;';
872
- }
873
- return result.join('');
869
+ // Replace via String.prototype.replace so we don't have to reconcile
870
+ // UTF-16 code-unit offsets (match.index) with code-point indexing
871
+ // (`[...rawText]`). Astral characters (e.g. emoji) before the match
872
+ // would otherwise shift the replacement and leave a real `</tag>`
873
+ // break-out in the output.
874
+ return rawText.replace(
875
+ new RegExp(parentClosingTag, 'ig'),
876
+ (m) => '&lt;' + m.slice(1)
877
+ );
874
878
  }
875
879
 
876
880
  const CLOSING_COMMENT_REGEXP = /--!?>/;
@@ -919,7 +923,8 @@ function requireNodeUtils () {
919
923
  var ss = kid.serialize();
920
924
  // If an element can have raw content, this content may
921
925
  // potentially require escaping to avoid XSS.
922
- if (hasRawContent[tagname.toUpperCase()]) {
926
+ var upperTag = tagname.toUpperCase();
927
+ if (hasRawContent[upperTag]) {
923
928
  ss = escapeMatchingClosingTag(ss, tagname);
924
929
  }
925
930
  if (html && extraNewLine[tagname] && ss.charAt(0)==='\n') s += '\n';
@@ -937,8 +942,7 @@ function requireNodeUtils () {
937
942
  else
938
943
  parenttag = '';
939
944
 
940
- if (hasRawContent[parenttag] ||
941
- (parenttag==='NOSCRIPT' && parent.ownerDocument._scripting_enabled)) {
945
+ if (hasRawContent[parenttag]) {
942
946
  s += kid.data;
943
947
  } else {
944
948
  s += escape(kid.data);
@@ -3618,9 +3622,9 @@ function requireElement () {
3618
3622
  ContainerNode.call(this);
3619
3623
  this.nodeType = Node.ELEMENT_NODE;
3620
3624
  this.ownerDocument = doc;
3621
- this.localName = localName;
3625
+ this._localName = localName;
3622
3626
  this.namespaceURI = namespaceURI;
3623
- this.prefix = prefix;
3627
+ this._prefix = prefix;
3624
3628
  this._tagName = undefined;
3625
3629
 
3626
3630
  // These properties maintain the set of attributes
@@ -3640,6 +3644,14 @@ function requireElement () {
3640
3644
  }
3641
3645
 
3642
3646
  Element.prototype = Object.create(ContainerNode.prototype, {
3647
+ localName: {
3648
+ get: function () { return this._localName; },
3649
+ set: function () { /* no-op per spec */ }
3650
+ },
3651
+ prefix: {
3652
+ get: function () { return this._prefix; },
3653
+ set: function () { /* no-op per spec */ }
3654
+ },
3643
3655
  isHTML: { get: function isHTML() {
3644
3656
  return this.namespaceURI === NAMESPACE.HTML && this.ownerDocument.isHTML;
3645
3657
  }},
@@ -3662,7 +3674,9 @@ function requireElement () {
3662
3674
  this._tagName = tn;
3663
3675
  }
3664
3676
  return this._tagName;
3665
- }},
3677
+ },
3678
+ set: function () { /* no-op per spec */ }
3679
+ },
3666
3680
  nodeName: { get: function() { return this.tagName; }},
3667
3681
  nodeValue: {
3668
3682
  get: function() {
@@ -4568,8 +4582,8 @@ function requireElement () {
4568
4582
  function Attr(elt, lname, prefix, namespace, value) {
4569
4583
  // localName and namespace are constant for any attr object.
4570
4584
  // But value may change. And so can prefix, and so, therefore can name.
4571
- this.localName = lname;
4572
- this.prefix = (prefix===null || prefix==='') ? null : ('' + prefix);
4585
+ this._localName = lname;
4586
+ this._prefix = (prefix===null || prefix==='') ? null : ('' + prefix);
4573
4587
  this.namespaceURI = (namespace===null || namespace==='') ? null : ('' + namespace);
4574
4588
  this.data = value;
4575
4589
  // Set ownerElement last to ensure it is hooked up to onchange handler
@@ -4578,6 +4592,14 @@ function requireElement () {
4578
4592
 
4579
4593
  // In DOM 3 Attr was supposed to extend Node; in DOM 4 that was abandoned.
4580
4594
  Attr.prototype = Object.create(Object.prototype, {
4595
+ localName: {
4596
+ get: function () { return this._localName; },
4597
+ set: function () { /* no-op per spec */ }
4598
+ },
4599
+ prefix: {
4600
+ get: function () { return this._prefix; },
4601
+ set: function () { /* no-op per spec */ }
4602
+ },
4581
4603
  ownerElement: {
4582
4604
  get: function() { return this._ownerElement; },
4583
4605
  },
@@ -5210,7 +5232,7 @@ function requireProcessingInstruction () {
5210
5232
  CharacterData.call(this);
5211
5233
  this.nodeType = Node.PROCESSING_INSTRUCTION_NODE;
5212
5234
  this.ownerDocument = doc;
5213
- this.target = target;
5235
+ this._target = target;
5214
5236
  this._data = data;
5215
5237
  }
5216
5238
 
@@ -5224,6 +5246,10 @@ function requireProcessingInstruction () {
5224
5246
  };
5225
5247
 
5226
5248
  ProcessingInstruction.prototype = Object.create(CharacterData.prototype, {
5249
+ target: {
5250
+ get: function () { return this._target; },
5251
+ set: function () { /* no-op per spec */ }
5252
+ },
5227
5253
  nodeName: { get: function() { return this.target; }},
5228
5254
  nodeValue: nodeValue,
5229
5255
  textContent: nodeValue,
@@ -9389,12 +9415,16 @@ function requireDocumentType () {
9389
9415
  Leaf.call(this);
9390
9416
  this.nodeType = Node.DOCUMENT_TYPE_NODE;
9391
9417
  this.ownerDocument = ownerDocument || null;
9392
- this.name = name;
9418
+ this._name = name;
9393
9419
  this.publicId = publicId || "";
9394
9420
  this.systemId = systemId || "";
9395
9421
  }
9396
9422
 
9397
9423
  DocumentType.prototype = Object.create(Leaf.prototype, {
9424
+ name: {
9425
+ get: function() { return this._name; },
9426
+ set: function() { /* no-op per spec */ }
9427
+ },
9398
9428
  nodeName: { get: function() { return this.name; }},
9399
9429
  nodeValue: {
9400
9430
  get: function() { return null; },
@@ -17154,7 +17184,7 @@ class DominoAdapter extends _BrowserDomAdapter {
17154
17184
  return 'Fake user agent';
17155
17185
  }
17156
17186
  getCookie(name) {
17157
- throw new Error('getCookie has not been implemented');
17187
+ throw new _RuntimeError(5700 /* RuntimeErrorCode.GET_COOKIE_NOT_IMPLEMENTED */, (typeof ngDevMode === 'undefined' || ngDevMode) && 'getCookie has not been implemented');
17158
17188
  }
17159
17189
  }
17160
17190
 
@@ -17190,7 +17220,8 @@ class PlatformState {
17190
17220
  */
17191
17221
  renderToString() {
17192
17222
  if (ngDevMode && !this._enableDomEmulation && !window?.document) {
17193
- throw new Error('Disabled DOM emulation should only run in browser environments');
17223
+ throw new _RuntimeError(5704 /* RuntimeErrorCode.DISABLED_DOM_EMULATION_IN_NON_BROWSER */, (typeof ngDevMode === 'undefined' || ngDevMode) &&
17224
+ 'Disabled DOM emulation should only run in browser environments');
17194
17225
  }
17195
17226
  const measuringLabel = 'renderToString';
17196
17227
  _startMeasuring(measuringLabel);
@@ -17207,10 +17238,10 @@ class PlatformState {
17207
17238
  getDocument() {
17208
17239
  return this._doc;
17209
17240
  }
17210
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: PlatformState, deps: [{ token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Injectable });
17211
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: PlatformState });
17241
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: PlatformState, deps: [{ token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Injectable });
17242
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: PlatformState });
17212
17243
  }
17213
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: PlatformState, decorators: [{
17244
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: PlatformState, decorators: [{
17214
17245
  type: Injectable
17215
17246
  }], ctorParameters: () => [{ type: undefined, decorators: [{
17216
17247
  type: Inject,
@@ -17220,6 +17251,89 @@ function enableDomEmulation(injector) {
17220
17251
  return injector.get(ENABLE_DOM_EMULATION, true);
17221
17252
  }
17222
17253
 
17254
+ /**
17255
+ * Matches http: or https:
17256
+ */
17257
+ const HTTP_OR_HTTPS_PROTOCOL_REGEX = /^https?:/i;
17258
+ function parseUrl(urlStr, origin, options = {}) {
17259
+ const originUrl = typeof origin === 'string' ? new URL('/', origin) : origin;
17260
+ if (!urlStr) {
17261
+ return originUrl || null;
17262
+ }
17263
+ urlStr = urlStr.trim();
17264
+ // Fast-path: if the URL is a valid, standard absolute URL, parse and return it immediately.
17265
+ let resolved;
17266
+ try {
17267
+ resolved = new URL(urlStr);
17268
+ }
17269
+ catch { }
17270
+ const { allowProtocolRelative = false, allowOriginChange = true } = options;
17271
+ if (resolved) {
17272
+ if (originUrl && !isSafeOriginChange(resolved, originUrl, urlStr, allowOriginChange)) {
17273
+ throwSuspiciousUrlError(urlStr);
17274
+ }
17275
+ return resolved;
17276
+ }
17277
+ // We identify and throw on malformed absolute URLs (like double port).
17278
+ // Per the WHATWG URL standard, parsing an input starting with a scheme (like 'http:') against
17279
+ // a standard base (like 'http://fake') ignores the base argument and parses strictly as an
17280
+ // absolute URL. Since it is malformed, the native URL constructor will throw a validation
17281
+ // error. Standard relative/protocol-relative paths parse successfully, allowing the flow to continue.
17282
+ if (!URL.canParse(urlStr, 'http://fake')) {
17283
+ throw new _RuntimeError(5701 /* RuntimeErrorCode.INVALID_URL */, typeof ngDevMode === 'undefined' || ngDevMode ? `Invalid URL: ${urlStr}` : urlStr);
17284
+ }
17285
+ if (!originUrl) {
17286
+ return null;
17287
+ }
17288
+ // Check if we have a legitimate protocol-relative URL (starts with '//' and not a duplicate/backslash bypass)
17289
+ // and we are configured to allow and preserve standard cross-origin protocol-relative requests.
17290
+ if (urlStr.startsWith('//')) {
17291
+ if (!allowProtocolRelative) {
17292
+ throw new _RuntimeError(5702 /* RuntimeErrorCode.PROTOCOL_RELATIVE_URL_NOT_ALLOWED */, typeof ngDevMode === 'undefined' || ngDevMode
17293
+ ? `Protocol relative URLs are not allowed in this context. URL: ${urlStr}`
17294
+ : urlStr);
17295
+ }
17296
+ return new URL(urlStr, origin);
17297
+ }
17298
+ resolved = new URL(urlStr, origin);
17299
+ if (!isSafeOriginChange(resolved, originUrl, urlStr, allowOriginChange)) {
17300
+ throwSuspiciousUrlError(urlStr);
17301
+ }
17302
+ return resolved;
17303
+ }
17304
+ /**
17305
+ * Throws a suspicious URL error indicating a security bypass attempt.
17306
+ */
17307
+ function throwSuspiciousUrlError(urlStr) {
17308
+ throw new _RuntimeError(5703 /* RuntimeErrorCode.SUSPICIOUS_URL_CHANGE_ORIGIN */, typeof ngDevMode === 'undefined' || ngDevMode
17309
+ ? `URL ${urlStr} changed origin unexpectedly. This is suspicious and may indicate a security bypass attempt.`
17310
+ : urlStr);
17311
+ }
17312
+ /**
17313
+ * Checks if the origin has changed in a safe way.
17314
+ *
17315
+ * @param resolved The resolved URL.
17316
+ * @param origin The origin URL.
17317
+ * @param urlStr The URL string.
17318
+ * @param allowOriginChange Whether to allow origin changes.
17319
+ * @returns True if the origin has changed in a safe way, false otherwise.
17320
+ */
17321
+ function isSafeOriginChange(resolved, origin, urlStr, allowOriginChange) {
17322
+ if (origin.origin === resolved.origin) {
17323
+ return true;
17324
+ }
17325
+ if (!allowOriginChange) {
17326
+ return false;
17327
+ }
17328
+ return HTTP_OR_HTTPS_PROTOCOL_REGEX.test(urlStr);
17329
+ }
17330
+
17331
+ /**
17332
+ * @deprecated Use the HttpClient fetch backend (by enabling `withFetch()`) instead.
17333
+ * XHR support in `@angular/platform-server` is deprecated because the underlying `xhr2`
17334
+ * library does not safely handle redirects (e.g. it can forward `Authorization` headers
17335
+ * on cross-origin redirects and is susceptible to denial-of-service (DoS) via redirect loops).
17336
+ */
17223
17337
  class ServerXhr {
17224
17338
  xhrImpl;
17225
17339
  // The `xhr2` dependency has a side-effect of accessing and modifying a
@@ -17228,6 +17342,13 @@ class ServerXhr {
17228
17342
  // server platform (via shims, etc).
17229
17343
  async ɵloadImpl() {
17230
17344
  if (!this.xhrImpl) {
17345
+ if (typeof ngDevMode === 'undefined' || ngDevMode) {
17346
+ console.warn('XHR support in `@angular/platform-server` is deprecated and will be removed ' +
17347
+ 'in a future version of Angular. It has known security and performance issues in server ' +
17348
+ 'environments, such as forwarding `Authorization` headers on cross-origin ' +
17349
+ 'redirects and susceptibility to denial-of-service (DoS) via redirect loops. ' +
17350
+ 'Please enable the HttpClient fetch backend instead by using `withFetch()`.');
17351
+ }
17231
17352
  const { default: xhr } = await import('xhr2');
17232
17353
  this.xhrImpl = xhr;
17233
17354
  }
@@ -17235,17 +17356,27 @@ class ServerXhr {
17235
17356
  build() {
17236
17357
  const impl = this.xhrImpl;
17237
17358
  if (!impl) {
17238
- throw new Error('Unexpected state in ServerXhr: XHR implementation is not loaded.');
17359
+ throw new _RuntimeError(5705 /* RuntimeErrorCode.XHR_NOT_LOADED */, (typeof ngDevMode === 'undefined' || ngDevMode) &&
17360
+ 'Unexpected state in ServerXhr: XHR implementation is not loaded.');
17239
17361
  }
17240
17362
  return new impl.XMLHttpRequest();
17241
17363
  }
17242
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: ServerXhr, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
17243
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: ServerXhr });
17364
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: ServerXhr, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
17365
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: ServerXhr });
17244
17366
  }
17245
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: ServerXhr, decorators: [{
17367
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: ServerXhr, decorators: [{
17246
17368
  type: Injectable
17247
17369
  }] });
17370
+ /**
17371
+ * Regex to match a URL schema.
17372
+ */
17373
+ const URL_SCHEMA_REGEXP = /^(?:[a-zA-Z][a-zA-Z0-9+\-.]*:)/;
17248
17374
  function relativeUrlsTransformerInterceptorFn(request, next) {
17375
+ const trimmedUrl = request.url.trim();
17376
+ if (URL_SCHEMA_REGEXP.test(trimmedUrl)) {
17377
+ // URLs with a schema should be left unchanged.
17378
+ return next(request);
17379
+ }
17249
17380
  const platformLocation = inject(PlatformLocation);
17250
17381
  const { href, protocol, hostname, port } = platformLocation;
17251
17382
  if (!protocol.startsWith('http')) {
@@ -17257,8 +17388,10 @@ function relativeUrlsTransformerInterceptorFn(request, next) {
17257
17388
  }
17258
17389
  const baseHref = platformLocation.getBaseHrefFromDOM() || href;
17259
17390
  const baseUrl = new URL(baseHref, urlPrefix);
17260
- const newUrl = new URL(request.url, baseUrl).toString();
17261
- return next(request.clone({ url: newUrl }));
17391
+ const parsedUrl = parseUrl(request.url, baseUrl, {
17392
+ allowProtocolRelative: true,
17393
+ });
17394
+ return next(request.clone({ url: parsedUrl.toString() }));
17262
17395
  }
17263
17396
  const SERVER_HTTP_PROVIDERS = [
17264
17397
  { provide: XhrFactory, useClass: ServerXhr },
@@ -17269,27 +17402,6 @@ const SERVER_HTTP_PROVIDERS = [
17269
17402
  },
17270
17403
  ];
17271
17404
 
17272
- const LEADING_SLASHES_REGEX = /^[/\\]+/;
17273
- function parseUrl(urlStr, origin) {
17274
- if (!urlStr) {
17275
- return origin !== undefined ? new URL('/', origin) : null;
17276
- }
17277
- if (URL.canParse(urlStr)) {
17278
- return new URL(urlStr);
17279
- }
17280
- if (/^[a-zA-Z][a-zA-Z0-9+.-]*:(\/\/|\\\\)/.test(urlStr)) {
17281
- throw new Error(`Invalid URL: ${urlStr}`);
17282
- }
17283
- if (origin === undefined) {
17284
- return null;
17285
- }
17286
- let normalizedPath = urlStr.replace(LEADING_SLASHES_REGEX, '/');
17287
- if (normalizedPath[0] !== '/') {
17288
- normalizedPath = `/${normalizedPath}`;
17289
- }
17290
- return new URL(normalizedPath, origin);
17291
- }
17292
-
17293
17405
  /**
17294
17406
  * Server-side implementation of URL state. Implements `pathname`, `search`, and `hash`
17295
17407
  * but not the state stack.
@@ -17304,14 +17416,13 @@ class ServerPlatformLocation {
17304
17416
  search = '';
17305
17417
  hash = '';
17306
17418
  _hashUpdate = new Subject();
17419
+ origin;
17307
17420
  constructor(_doc, _config) {
17308
17421
  this._doc = _doc;
17422
+ let origin = this._doc.location.origin;
17309
17423
  const config = _config;
17310
- if (!config) {
17311
- return;
17312
- }
17313
- if (config.url) {
17314
- const { protocol, hostname, port, pathname, search, hash, href } = parseUrl(config.url, this._doc.location.origin);
17424
+ if (config && config.url) {
17425
+ const { protocol, hostname, port, pathname, search, hash, href, origin: parsedOrigin, } = parseUrl(config.url, origin);
17315
17426
  this.protocol = protocol;
17316
17427
  this.hostname = hostname;
17317
17428
  this.port = port;
@@ -17319,7 +17430,9 @@ class ServerPlatformLocation {
17319
17430
  this.search = search;
17320
17431
  this.hash = hash;
17321
17432
  this.href = href;
17433
+ origin = parsedOrigin;
17322
17434
  }
17435
+ this.origin = origin;
17323
17436
  }
17324
17437
  getBaseHrefFromDOM() {
17325
17438
  return _getDOM().getBaseHref(this._doc);
@@ -17352,7 +17465,9 @@ class ServerPlatformLocation {
17352
17465
  }
17353
17466
  replaceState(state, title, newUrl) {
17354
17467
  const oldUrl = this.url;
17355
- const { pathname, search, hash, href, protocol } = parseUrl(newUrl, this._doc.location.origin);
17468
+ const { pathname, search, hash, href, protocol } = parseUrl(newUrl, this.origin, {
17469
+ allowOriginChange: false,
17470
+ });
17356
17471
  const writableThis = this;
17357
17472
  writableThis.pathname = pathname;
17358
17473
  writableThis.search = search;
@@ -17373,10 +17488,10 @@ class ServerPlatformLocation {
17373
17488
  getState() {
17374
17489
  return undefined;
17375
17490
  }
17376
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: ServerPlatformLocation, deps: [{ token: DOCUMENT }, { token: INITIAL_CONFIG, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
17377
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: ServerPlatformLocation });
17491
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: ServerPlatformLocation, deps: [{ token: DOCUMENT }, { token: INITIAL_CONFIG, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
17492
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: ServerPlatformLocation });
17378
17493
  }
17379
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: ServerPlatformLocation, decorators: [{
17494
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: ServerPlatformLocation, decorators: [{
17380
17495
  type: Injectable
17381
17496
  }], ctorParameters: () => [{ type: undefined, decorators: [{
17382
17497
  type: Inject,
@@ -17401,10 +17516,10 @@ class ServerEventManagerPlugin extends EventManagerPlugin {
17401
17516
  addEventListener(element, eventName, handler, options) {
17402
17517
  return _getDOM().onAndCancel(element, eventName, handler, options);
17403
17518
  }
17404
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: ServerEventManagerPlugin, deps: [{ token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Injectable });
17405
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: ServerEventManagerPlugin });
17519
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: ServerEventManagerPlugin, deps: [{ token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Injectable });
17520
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: ServerEventManagerPlugin });
17406
17521
  }
17407
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: ServerEventManagerPlugin, decorators: [{
17522
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: ServerEventManagerPlugin, decorators: [{
17408
17523
  type: Injectable
17409
17524
  }], ctorParameters: () => [{ type: undefined, decorators: [{
17410
17525
  type: Inject,
@@ -17517,11 +17632,11 @@ const PLATFORM_SERVER_PROVIDERS = [
17517
17632
  * @publicApi
17518
17633
  */
17519
17634
  class ServerModule {
17520
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: ServerModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
17521
- static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.23", ngImport: i0, type: ServerModule, exports: [BrowserModule] });
17522
- static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: ServerModule, providers: PLATFORM_SERVER_PROVIDERS, imports: [BrowserModule] });
17635
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: ServerModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
17636
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.25", ngImport: i0, type: ServerModule, exports: [BrowserModule] });
17637
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: ServerModule, providers: PLATFORM_SERVER_PROVIDERS, imports: [BrowserModule] });
17523
17638
  }
17524
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: ServerModule, decorators: [{
17639
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: ServerModule, decorators: [{
17525
17640
  type: NgModule,
17526
17641
  args: [{
17527
17642
  exports: [BrowserModule],
@@ -17536,7 +17651,12 @@ function _document(injector) {
17536
17651
  document =
17537
17652
  typeof config.document === 'string'
17538
17653
  ? _enableDomEmulation
17539
- ? parseDocument(config.document, config.url !== undefined ? parseUrl(config.url, 'http://localhost').href : undefined)
17654
+ ? parseDocument(config.document, config.url !== undefined
17655
+ ? // A fallback same-origin base ('http://localhost') is provided so that relative
17656
+ // page URLs are parsed and resolved as same-origin paths, preventing empty
17657
+ // or invalid location values in the parsed virtual DOM document.
17658
+ parseUrl(config.url, 'http://localhost').href
17659
+ : undefined)
17540
17660
  : window.document
17541
17661
  : config.document;
17542
17662
  }