@angular/core 19.2.22 → 19.2.23

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.
Files changed (46) hide show
  1. package/event_dispatcher.d-K56StcHr.d.ts +1 -1
  2. package/fesm2022/core.mjs +270 -64
  3. package/fesm2022/core.mjs.map +1 -1
  4. package/fesm2022/primitives/di.mjs +1 -1
  5. package/fesm2022/primitives/event-dispatch.mjs +1 -1
  6. package/fesm2022/primitives/signals.mjs +1 -1
  7. package/fesm2022/rxjs-interop.mjs +1 -1
  8. package/fesm2022/testing.mjs +1 -1
  9. package/fesm2022/untracked-BKcld_ew.mjs +1 -1
  10. package/index.d.ts +7 -2
  11. package/navigation_types.d-fAxd92YV.d.ts +1 -1
  12. package/package.json +1 -1
  13. package/primitives/di/index.d.ts +1 -1
  14. package/primitives/event-dispatch/index.d.ts +1 -1
  15. package/primitives/signals/index.d.ts +1 -1
  16. package/rxjs-interop/index.d.ts +1 -1
  17. package/schematics/bundles/add-bootstrap-context-to-server-main.cjs +2 -2
  18. package/schematics/bundles/{apply_import_manager-QEWElZT-.cjs → apply_import_manager-D8er9283.cjs} +3 -3
  19. package/schematics/bundles/{change_tracker-BPk3UwXG.cjs → change_tracker-BMoOL0o6.cjs} +2 -2
  20. package/schematics/bundles/{checker-DLkGMJj-.cjs → checker-C9K-IOAk.cjs} +287 -213
  21. package/schematics/bundles/cleanup-unused-imports.cjs +5 -5
  22. package/schematics/bundles/compiler_host-CAfDJO3W.cjs +1 -1
  23. package/schematics/bundles/control-flow-migration.cjs +3 -3
  24. package/schematics/bundles/explicit-standalone-flag.cjs +3 -3
  25. package/schematics/bundles/imports-CIX-JgAN.cjs +1 -1
  26. package/schematics/bundles/{index-BPwBW8Gv.cjs → index-C0sKgTb6.cjs} +4 -4
  27. package/schematics/bundles/{index-iQYWEThN.cjs → index-C55Aq2GC.cjs} +12 -12
  28. package/schematics/bundles/inject-migration.cjs +3 -3
  29. package/schematics/bundles/leading_space-D9nQ8UQC.cjs +1 -1
  30. package/schematics/bundles/{migrate_ts_type_references-BhOqwhYA.cjs → migrate_ts_type_references-CjUloDnc.cjs} +5 -5
  31. package/schematics/bundles/ng_decorators-B5HCqr20.cjs +1 -1
  32. package/schematics/bundles/nodes-B16H9JUd.cjs +1 -1
  33. package/schematics/bundles/output-migration.cjs +6 -6
  34. package/schematics/bundles/pending-tasks.cjs +3 -3
  35. package/schematics/bundles/{project_paths-DePtMwan.cjs → project_paths-D8qIpJ6r.cjs} +3 -3
  36. package/schematics/bundles/project_tsconfig_paths-CDVxT6Ov.cjs +1 -1
  37. package/schematics/bundles/property_name-BBwFuqMe.cjs +1 -1
  38. package/schematics/bundles/provide-initializer.cjs +3 -3
  39. package/schematics/bundles/route-lazy-loading.cjs +3 -3
  40. package/schematics/bundles/self-closing-tags-migration.cjs +4 -4
  41. package/schematics/bundles/signal-input-migration.cjs +7 -7
  42. package/schematics/bundles/signal-queries-migration.cjs +7 -7
  43. package/schematics/bundles/signals.cjs +7 -7
  44. package/schematics/bundles/standalone-migration.cjs +4 -4
  45. package/testing/index.d.ts +1 -1
  46. package/weak_ref.d-DWHPG08n.d.ts +1 -1
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Angular v19.2.22
2
+ * @license Angular v19.2.23
3
3
  * (c) 2010-2025 Google LLC. https://angular.io/
4
4
  * License: MIT
5
5
  */
package/fesm2022/core.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Angular v19.2.22
2
+ * @license Angular v19.2.23
3
3
  * (c) 2010-2025 Google LLC. https://angular.io/
4
4
  * License: MIT
5
5
  */
@@ -3195,8 +3195,8 @@ const profiler = function (event, instance = null, hookOrListener) {
3195
3195
  }
3196
3196
  };
3197
3197
 
3198
- const SVG_NAMESPACE = 'svg';
3199
- const MATH_ML_NAMESPACE = 'math';
3198
+ const SVG_NAMESPACE$1 = 'svg';
3199
+ const MATH_ML_NAMESPACE$1 = 'math';
3200
3200
 
3201
3201
  /**
3202
3202
  * For efficiency reasons we often put several different data types (`RNode`, `LView`, `LContainer`)
@@ -3981,7 +3981,7 @@ function getSelectedTNode() {
3981
3981
  * @codeGenApi
3982
3982
  */
3983
3983
  function ɵɵnamespaceSVG() {
3984
- instructionState.lFrame.currentNamespace = SVG_NAMESPACE;
3984
+ instructionState.lFrame.currentNamespace = SVG_NAMESPACE$1;
3985
3985
  }
3986
3986
  /**
3987
3987
  * Sets the namespace used to create elements to `'http://www.w3.org/1998/MathML/'` in global state.
@@ -3989,7 +3989,7 @@ function ɵɵnamespaceSVG() {
3989
3989
  * @codeGenApi
3990
3990
  */
3991
3991
  function ɵɵnamespaceMathML() {
3992
- instructionState.lFrame.currentNamespace = MATH_ML_NAMESPACE;
3992
+ instructionState.lFrame.currentNamespace = MATH_ML_NAMESPACE$1;
3993
3993
  }
3994
3994
  /**
3995
3995
  * Sets the namespace used to create elements to `null`, which forces element creation to use
@@ -10880,13 +10880,6 @@ const VALID_ATTRS = merge(URI_ATTRS, HTML_ATTRS, ARIA_ATTRS);
10880
10880
  // `Some content`, but strip `invalid-element` opening/closing tags. For some elements, though, we
10881
10881
  // don't want to preserve the content, if the elements themselves are going to be removed.
10882
10882
  const SKIP_TRAVERSING_CONTENT_IF_INVALID_ELEMENTS = tagSet('script,style,template');
10883
- /**
10884
- * Attributes that are potential attach vectors and may need to be sanitized.
10885
- */
10886
- const SENSITIVE_ATTRS = merge(URI_ATTRS,
10887
- // Note: we don't include these attributes in `URI_ATTRS`, because `URI_ATTRS` also
10888
- // determines whether an attribute should be dropped when sanitizing an HTML string.
10889
- tagSet('action,formaction,data,codebase'));
10890
10883
  /**
10891
10884
  * SanitizingHtmlSerializer serializes a DOM fragment, stripping out any unsafe elements and unsafe
10892
10885
  * attributes.
@@ -11298,7 +11291,132 @@ var SecurityContext;
11298
11291
  SecurityContext[SecurityContext["SCRIPT"] = 3] = "SCRIPT";
11299
11292
  SecurityContext[SecurityContext["URL"] = 4] = "URL";
11300
11293
  SecurityContext[SecurityContext["RESOURCE_URL"] = 5] = "RESOURCE_URL";
11294
+ SecurityContext[SecurityContext["ATTRIBUTE_NO_BINDING"] = 6] = "ATTRIBUTE_NO_BINDING";
11301
11295
  })(SecurityContext || (SecurityContext = {}));
11296
+ // =================================================================================================
11297
+ // =================================================================================================
11298
+ // =========== S T O P - S T O P - S T O P - S T O P - S T O P - S T O P ===========
11299
+ // =================================================================================================
11300
+ // =================================================================================================
11301
+ //
11302
+ // DO NOT EDIT THIS LIST OF SECURITY SENSITIVE PROPERTIES WITHOUT A SECURITY REVIEW!
11303
+ //
11304
+ // =================================================================================================
11305
+ /**
11306
+ * Map from tagName|propertyName to SecurityContext. Properties applying to all tags use '*'.
11307
+ */
11308
+ let _SECURITY_SCHEMA;
11309
+ const SVG_NAMESPACE = 'svg';
11310
+ const MATH_ML_NAMESPACE = 'math';
11311
+ /**
11312
+ * @remarks Keep is a copy of DOM Security Schema.
11313
+ * @see [SECURITY_SCHEMA](../../../compiler/src/schema/dom_security_schema.ts)
11314
+ */
11315
+ function SECURITY_SCHEMA() {
11316
+ if (!_SECURITY_SCHEMA) {
11317
+ _SECURITY_SCHEMA = {};
11318
+ // Case is insignificant below, all element and attribute names are lower-cased for lookup.
11319
+ registerContext(SecurityContext.HTML, /** Namespace */ undefined, [
11320
+ ['iframe', ['srcdoc']],
11321
+ ['*', ['innerHTML', 'outerHTML']],
11322
+ ]);
11323
+ registerContext(SecurityContext.STYLE, /** Namespace */ undefined, [['*', ['style']]]);
11324
+ // NB: no SCRIPT contexts here, they are never allowed due to the parser stripping them.
11325
+ registerContext(SecurityContext.URL, /** Namespace */ undefined, [
11326
+ ['*', ['formAction']],
11327
+ ['area', ['href']],
11328
+ ['a', ['href', 'xlink:href']],
11329
+ ['form', ['action']],
11330
+ // The below two items are safe and should be removed but they require a G3 clean-up as a small number of tests fail.
11331
+ ['img', ['src']],
11332
+ ['video', ['src']],
11333
+ ]);
11334
+ registerContext(SecurityContext.URL, MATH_ML_NAMESPACE, [
11335
+ // MathML namespace
11336
+ // https://crsrc.org/c/third_party/blink/renderer/core/sanitizer/sanitizer.cc;l=753-768;drc=b3eb16372dcd3317d65e9e0265015e322494edcd;bpv=1;bpt=1
11337
+ ['annotation', ['href', 'xlink:href']],
11338
+ ['annotation-xml', ['href', 'xlink:href']],
11339
+ ['maction', ['href', 'xlink:href']],
11340
+ ['malignmark', ['href', 'xlink:href']],
11341
+ ['math', ['href', 'xlink:href']],
11342
+ ['mroot', ['href', 'xlink:href']],
11343
+ ['msqrt', ['href', 'xlink:href']],
11344
+ ['merror', ['href', 'xlink:href']],
11345
+ ['mfrac', ['href', 'xlink:href']],
11346
+ ['mglyph', ['href', 'xlink:href']],
11347
+ ['msub', ['href', 'xlink:href']],
11348
+ ['msup', ['href', 'xlink:href']],
11349
+ ['msubsup', ['href', 'xlink:href']],
11350
+ ['mmultiscripts', ['href', 'xlink:href']],
11351
+ ['mprescripts', ['href', 'xlink:href']],
11352
+ ['mi', ['href', 'xlink:href']],
11353
+ ['mn', ['href', 'xlink:href']],
11354
+ ['mo', ['href', 'xlink:href']],
11355
+ ['mpadded', ['href', 'xlink:href']],
11356
+ ['mphantom', ['href', 'xlink:href']],
11357
+ ['mrow', ['href', 'xlink:href']],
11358
+ ['ms', ['href', 'xlink:href']],
11359
+ ['mspace', ['href', 'xlink:href']],
11360
+ ['mstyle', ['href', 'xlink:href']],
11361
+ ['mtable', ['href', 'xlink:href']],
11362
+ ['mtd', ['href', 'xlink:href']],
11363
+ ['mtr', ['href', 'xlink:href']],
11364
+ ['mtext', ['href', 'xlink:href']],
11365
+ ['mover', ['href', 'xlink:href']],
11366
+ ['munder', ['href', 'xlink:href']],
11367
+ ['munderover', ['href', 'xlink:href']],
11368
+ ['semantics', ['href', 'xlink:href']],
11369
+ ['none', ['href', 'xlink:href']],
11370
+ ]);
11371
+ registerContext(SecurityContext.RESOURCE_URL, /** Namespace */ undefined, [
11372
+ ['base', ['href']],
11373
+ ['embed', ['src']],
11374
+ ['frame', ['src']],
11375
+ ['iframe', ['src']],
11376
+ ['link', ['href']],
11377
+ ['object', ['codebase', 'data']],
11378
+ ]);
11379
+ registerContext(SecurityContext.URL, SVG_NAMESPACE, [['a', ['href', 'xlink:href']]]);
11380
+ // Keep this in sync with SECURITY_SENSITIVE_ELEMENTS in packages/core/src/sanitization/sanitization.ts
11381
+ // Unknown is the internal tag name for unknown elements example used for host-bindings.
11382
+ // These are unsafe as `attributeName` can be `href` or `xlink:href`
11383
+ // See: http://b/463880509#comment7
11384
+ registerContext(SecurityContext.ATTRIBUTE_NO_BINDING, SVG_NAMESPACE, [
11385
+ ['animate', ['attributeName', 'values', 'to', 'from']],
11386
+ ['set', ['to', 'attributeName']],
11387
+ ['animateMotion', ['attributeName']],
11388
+ ['animateTransform', ['attributeName']],
11389
+ ]);
11390
+ registerContext(SecurityContext.ATTRIBUTE_NO_BINDING, /** Namespace */ undefined, [
11391
+ [
11392
+ 'unknown',
11393
+ [
11394
+ 'attributeName',
11395
+ 'values',
11396
+ 'to',
11397
+ 'from',
11398
+ 'sandbox',
11399
+ 'allow',
11400
+ 'allowFullscreen',
11401
+ 'referrerPolicy',
11402
+ 'csp',
11403
+ 'fetchPriority',
11404
+ ],
11405
+ ],
11406
+ ['iframe', ['sandbox', 'allow', 'allowFullscreen', 'referrerPolicy', 'csp', 'fetchPriority']],
11407
+ ]);
11408
+ }
11409
+ return _SECURITY_SCHEMA;
11410
+ }
11411
+ function registerContext(ctx, namespace, specs) {
11412
+ for (const [element, attributeNames] of specs) {
11413
+ let tagName = namespace && element !== '*' && element !== 'unknown' ? `:${namespace}:${element}` : element;
11414
+ tagName = tagName.toLowerCase();
11415
+ for (const attr of attributeNames) {
11416
+ _SECURITY_SCHEMA[`${tagName}|${attr.toLowerCase()}`] = ctx;
11417
+ }
11418
+ }
11419
+ }
11302
11420
 
11303
11421
  /**
11304
11422
  * An `html` sanitizer which converts untrusted `html` **string** into trusted string by removing
@@ -11466,8 +11584,15 @@ function ɵɵtrustConstantResourceUrl(url) {
11466
11584
  return trustedScriptURLFromString(url[0]);
11467
11585
  }
11468
11586
  // Define sets outside the function for O(1) lookups and memory efficiency
11469
- const SRC_RESOURCE_TAGS = new Set(['embed', 'frame', 'iframe', 'media', 'script']);
11470
- const HREF_RESOURCE_TAGS = new Set(['base', 'link', 'script']);
11587
+ const RESOURCE_MAP = {
11588
+ 'embed': { 'src': true },
11589
+ 'frame': { 'src': true },
11590
+ 'iframe': { 'src': true },
11591
+ 'media': { 'src': true },
11592
+ 'base': { 'href': true },
11593
+ 'link': { 'href': true },
11594
+ 'object': { 'data': true, 'codebase': true },
11595
+ };
11471
11596
  /**
11472
11597
  * Detects which sanitizer to use for URL property, based on tag name and prop name.
11473
11598
  *
@@ -11476,9 +11601,7 @@ const HREF_RESOURCE_TAGS = new Set(['base', 'link', 'script']);
11476
11601
  * If tag and prop names don't match Resource URL schema, use URL sanitizer.
11477
11602
  */
11478
11603
  function getUrlSanitizer(tag, prop) {
11479
- const isResource = (prop === 'src' && SRC_RESOURCE_TAGS.has(tag)) ||
11480
- (prop === 'href' && HREF_RESOURCE_TAGS.has(tag)) ||
11481
- (prop === 'xlink:href' && tag === 'script');
11604
+ const isResource = RESOURCE_MAP[tag.toLowerCase()]?.[prop.toLowerCase()] === true;
11482
11605
  return isResource ? ɵɵsanitizeResourceUrl : ɵɵsanitizeUrl;
11483
11606
  }
11484
11607
  /**
@@ -11519,24 +11642,32 @@ function getSanitizer() {
11519
11642
  const lView = getLView();
11520
11643
  return lView && lView[ENVIRONMENT].sanitizer;
11521
11644
  }
11522
- const attributeName = new Set(['attributename']);
11523
11645
  /**
11524
11646
  * @remarks Keep this in sync with DOM Security Schema.
11525
11647
  * @see [SECURITY_SCHEMA](../../../compiler/src/schema/dom_security_schema.ts)
11526
11648
  */
11649
+ /**
11650
+ * Set of attributes that are sensitive and should be sanitized.
11651
+ */
11652
+ const SECURITY_SENSITIVE_ATTRIBUTE_NAMES = new Set(['href', 'xlink:href']);
11527
11653
  const SECURITY_SENSITIVE_ELEMENTS = {
11528
- 'iframe': new Set([
11529
- 'sandbox',
11530
- 'allow',
11531
- 'allowfullscreen',
11532
- 'referrerpolicy',
11533
- 'csp',
11534
- 'fetchpriority',
11535
- ]),
11536
- 'animate': attributeName,
11537
- 'set': attributeName,
11538
- 'animatemotion': attributeName,
11539
- 'animatetransform': attributeName,
11654
+ 'iframe': {
11655
+ 'sandbox': true,
11656
+ 'allow': true,
11657
+ 'allowfullscreen': true,
11658
+ 'referrerpolicy': true,
11659
+ 'csp': true,
11660
+ 'fetchpriority': true,
11661
+ },
11662
+ ':svg:animate': {
11663
+ 'attributename': true,
11664
+ 'to': SECURITY_SENSITIVE_ATTRIBUTE_NAMES,
11665
+ 'values': SECURITY_SENSITIVE_ATTRIBUTE_NAMES,
11666
+ 'from': SECURITY_SENSITIVE_ATTRIBUTE_NAMES,
11667
+ },
11668
+ ':svg:set': { 'attributename': true, 'to': SECURITY_SENSITIVE_ATTRIBUTE_NAMES },
11669
+ ':svg:animatemotion': { 'attributename': true },
11670
+ ':svg:animatetransform': { 'attributename': true },
11540
11671
  };
11541
11672
  /**
11542
11673
  * Validates that the attribute binding is safe to use.
@@ -11548,22 +11679,54 @@ const SECURITY_SENSITIVE_ELEMENTS = {
11548
11679
  function ɵɵvalidateAttribute(value, tagName, attributeName) {
11549
11680
  const lowerCaseTagName = tagName.toLowerCase();
11550
11681
  const lowerCaseAttrName = attributeName.toLowerCase();
11551
- if (!SECURITY_SENSITIVE_ELEMENTS[lowerCaseTagName]?.has(lowerCaseAttrName)) {
11682
+ const index = getSelectedIndex();
11683
+ const tNode = index === -1 ? null : getSelectedTNode();
11684
+ if (tNode && tNode.type !== 2 /* TNodeType.Element */) {
11552
11685
  return value;
11553
11686
  }
11554
- const tNode = getSelectedTNode();
11555
- if (tNode.type !== 2 /* TNodeType.Element */) {
11687
+ // Leverage tNode.namespace if active, otherwise check both namespaced and base variants.
11688
+ const fullTagName = lowerCaseTagName[0] !== ':' && tNode?.namespace
11689
+ ? `:${tNode.namespace}:${lowerCaseTagName}`
11690
+ : lowerCaseTagName;
11691
+ const validationConfig = SECURITY_SENSITIVE_ELEMENTS[fullTagName]?.[lowerCaseAttrName];
11692
+ if (!validationConfig) {
11556
11693
  return value;
11557
11694
  }
11558
11695
  const lView = getLView();
11559
- if (lowerCaseTagName === 'iframe') {
11696
+ if (tNode && lowerCaseTagName === 'iframe') {
11560
11697
  const element = getNativeByTNode(tNode, lView);
11561
11698
  enforceIframeSecurity(element);
11562
11699
  }
11700
+ const displayTagName = tagName[0] === ':' ? tagName.split(':').pop() : tagName;
11701
+ if (typeof validationConfig !== 'boolean') {
11702
+ if (!tNode) {
11703
+ const errorMessage = ngDevMode &&
11704
+ `Angular has detected that the \`${attributeName}\` was applied ` +
11705
+ `as a binding to the <${tagName}> element. ` +
11706
+ `For security reasons, the \`${attributeName}\` can be set on the <${tagName}> element ` +
11707
+ `as a static attribute only. \n` +
11708
+ `To fix this, switch the \`${attributeName}\` binding to a static attribute ` +
11709
+ `in a template or in host bindings section.`;
11710
+ throw new RuntimeError(-910 /* RuntimeErrorCode.UNSAFE_ATTRIBUTE_BINDING */, errorMessage);
11711
+ }
11712
+ const element = getNativeByTNode(tNode, lView);
11713
+ const attributeNameValue = element.getAttribute('attributeName');
11714
+ if (attributeNameValue && validationConfig.has(attributeNameValue.toLowerCase())) {
11715
+ const errorMessage = ngDevMode &&
11716
+ `Angular has detected that the \`${attributeName}\` was applied ` +
11717
+ `as a binding to the <${displayTagName}> element${getTemplateLocationDetails(lView)}. ` +
11718
+ `For security reasons, the \`${attributeName}\` can be set on the <${displayTagName}> element ` +
11719
+ `as a static attribute only when the "attributeName" is set to \'${attributeNameValue}\'. \n` +
11720
+ `To fix this, switch the \`${attributeNameValue}\` binding to a static attribute ` +
11721
+ `in a template or in host bindings section.`;
11722
+ throw new RuntimeError(-910 /* RuntimeErrorCode.UNSAFE_ATTRIBUTE_BINDING */, errorMessage);
11723
+ }
11724
+ return value;
11725
+ }
11563
11726
  const errorMessage = ngDevMode &&
11564
11727
  `Angular has detected that the \`${attributeName}\` was applied ` +
11565
- `as a binding to the <${tagName}> element${getTemplateLocationDetails(lView)}. ` +
11566
- `For security reasons, the \`${attributeName}\` can be set on the <${tagName}> element ` +
11728
+ `as a binding to the <${displayTagName}> element${tNode ? getTemplateLocationDetails(lView) : ''}. ` +
11729
+ `For security reasons, the \`${attributeName}\` can be set on the <${displayTagName}> element ` +
11567
11730
  `as a static attribute only. \n` +
11568
11731
  `To fix this, switch the \`${attributeName}\` binding to a static attribute ` +
11569
11732
  `in a template or in host bindings section.`;
@@ -12558,6 +12721,9 @@ function locateHostElement(renderer, elementOrSelector, encapsulation, injector)
12558
12721
  // projection.
12559
12722
  const preserveContent = preserveHostContent || encapsulation === ViewEncapsulation.ShadowDom;
12560
12723
  const rootElement = renderer.selectRootElement(elementOrSelector, preserveContent);
12724
+ if (rootElement?.tagName?.toLowerCase() === 'script') {
12725
+ throw new RuntimeError(905 /* RuntimeErrorCode.UNSAFE_VALUE_IN_SCRIPT */, ngDevMode && `"<script>" tag is not allowed as a component host element.`);
12726
+ }
12561
12727
  applyRootElementTransform(rootElement);
12562
12728
  return rootElement;
12563
12729
  }
@@ -15590,6 +15756,7 @@ function createTNode(tView, tParent, type, index, value, attrs) {
15590
15756
  flags,
15591
15757
  providerIndexes: 0,
15592
15758
  value: value,
15759
+ namespace: getNamespace(),
15593
15760
  attrs: attrs,
15594
15761
  mergedAttrs: null,
15595
15762
  localNames: null,
@@ -18045,7 +18212,7 @@ function createHostElement(componentDef, render) {
18045
18212
  // dynamically. Default to 'div' if this component did not specify any tag name in its
18046
18213
  // selector.
18047
18214
  const tagName = (componentDef.selectors[0][0] || 'div').toLowerCase();
18048
- const namespace = tagName === 'svg' ? SVG_NAMESPACE : tagName === 'math' ? MATH_ML_NAMESPACE : null;
18215
+ const namespace = tagName === 'svg' ? SVG_NAMESPACE$1 : tagName === 'math' ? MATH_ML_NAMESPACE$1 : null;
18049
18216
  return createElementNode(render, tagName, namespace);
18050
18217
  }
18051
18218
  /**
@@ -18088,7 +18255,7 @@ class ComponentFactory extends ComponentFactory$1 {
18088
18255
  const cmpDef = this.componentDef;
18089
18256
  ngDevMode && verifyNotAnOrphanComponent(cmpDef);
18090
18257
  const tAttributes = rootSelectorOrNode
18091
- ? ['ng-version', '19.2.22']
18258
+ ? ['ng-version', '19.2.23']
18092
18259
  : // Extract attributes and classes from the first selector only to match VE behavior.
18093
18260
  extractAttrsAndClassesFromSelector(this.componentDef.selectors[0]);
18094
18261
  // Create the root view. Uses empty TView and ContentTemplate.
@@ -28898,7 +29065,14 @@ function applyUpdateOpCodes(tView, lView, updateOpCodes, bindingsStartIndex, cha
28898
29065
  setElementAttribute(lView[RENDERER], lView[nodeIndex], null, tNodeOrTagName, propName, value, sanitizeFn);
28899
29066
  }
28900
29067
  else {
28901
- elementPropertyInternal(tView, tNodeOrTagName, lView, propName, value, lView[RENDERER], sanitizeFn, false);
29068
+ const prevSelectedIndex = getSelectedIndex();
29069
+ setSelectedIndex(nodeIndex);
29070
+ try {
29071
+ elementPropertyInternal(tView, tNodeOrTagName, lView, propName, value, lView[RENDERER], sanitizeFn, false);
29072
+ }
29073
+ finally {
29074
+ setSelectedIndex(prevSelectedIndex);
29075
+ }
28902
29076
  }
28903
29077
  break;
28904
29078
  case 0 /* I18nUpdateOpCode.Text */:
@@ -29478,7 +29652,10 @@ function i18nAttributesFirstPass(tView, index, values) {
29478
29652
  // the compiler treats static i18n attributes as regular attribute bindings.
29479
29653
  // Since this may not be the first i18n attribute on this element we need to pass in how
29480
29654
  // many previous bindings there have already been.
29481
- generateBindingUpdateOpCodes(updateOpCodes, message, previousElementIndex, attrName, countBindings(updateOpCodes), i18nSanitizeAttribute(attrName));
29655
+ const tagName = previousElement.namespace
29656
+ ? `:${previousElement.namespace}:${previousElement.value}`
29657
+ : previousElement.value;
29658
+ generateBindingUpdateOpCodes(updateOpCodes, message, previousElementIndex, attrName, countBindings(updateOpCodes), i18nResolveSanitizer(attrName, tagName));
29482
29659
  }
29483
29660
  }
29484
29661
  tView.data[index] = updateOpCodes;
@@ -29804,9 +29981,15 @@ function walkIcuTree(ast, tView, tIcu, lView, sharedUpdateOpCodes, create, remov
29804
29981
  const attr = elAttrs.item(i);
29805
29982
  const lowerAttrName = attr.name.toLowerCase();
29806
29983
  const hasBinding = !!attr.value.match(BINDING_REGEXP);
29984
+ const elementNS = element.namespaceURI;
29985
+ const tagNameWithNamespace = elementNS === 'http://www.w3.org/2000/svg'
29986
+ ? `:svg:${tagName}`
29987
+ : elementNS === 'http://www.w3.org/1998/Math/MathML'
29988
+ ? `:math:${tagName}`
29989
+ : tagName;
29807
29990
  if (hasBinding) {
29808
29991
  if (VALID_ATTRS.hasOwnProperty(lowerAttrName)) {
29809
- generateBindingUpdateOpCodes(update, attr.value, newIndex, attr.name, 0, i18nSanitizeAttribute(lowerAttrName));
29992
+ generateBindingUpdateOpCodes(update, attr.value, newIndex, attr.name, 0, i18nResolveSanitizer(lowerAttrName, tagNameWithNamespace));
29810
29993
  }
29811
29994
  else {
29812
29995
  ngDevMode &&
@@ -29816,9 +29999,9 @@ function walkIcuTree(ast, tView, tIcu, lView, sharedUpdateOpCodes, create, remov
29816
29999
  }
29817
30000
  }
29818
30001
  else if (VALID_ATTRS[lowerAttrName]) {
29819
- if (SENSITIVE_ATTRS[lowerAttrName]) {
29820
- // Don't sanitize, because no value is acceptable in sensitive attributes.
29821
- // Translators are not allowed to create URIs.
30002
+ let val = attr.value;
30003
+ const sanitizer = i18nResolveSanitizer(lowerAttrName, tagNameWithNamespace);
30004
+ if (sanitizer) {
29822
30005
  if (typeof ngDevMode !== 'undefined' && ngDevMode) {
29823
30006
  console.warn(`WARNING: ignoring unsafe attribute ` +
29824
30007
  `${lowerAttrName} on element ${tagName} ` +
@@ -29827,7 +30010,7 @@ function walkIcuTree(ast, tView, tIcu, lView, sharedUpdateOpCodes, create, remov
29827
30010
  addCreateAttribute(create, newIndex, attr.name, 'unsafe:blocked');
29828
30011
  }
29829
30012
  else {
29830
- addCreateAttribute(create, newIndex, attr.name, attr.value);
30013
+ addCreateAttribute(create, newIndex, attr.name, val);
29831
30014
  }
29832
30015
  }
29833
30016
  else {
@@ -29907,26 +30090,49 @@ function addCreateNodeAndAppend(create, marker, text, appendToParentIdx, createA
29907
30090
  function addCreateAttribute(create, newIndex, attrName, attrValue) {
29908
30091
  create.push((newIndex << 1 /* IcuCreateOpCode.SHIFT_REF */) | 1 /* IcuCreateOpCode.Attr */, attrName, attrValue);
29909
30092
  }
29910
- /**
29911
- * Caches all keys of `SECURITY_SENSITIVE_ELEMENTS` in a Set to avoid recomputing
29912
- * or scanning them on every invocation.
29913
- */
29914
- const SECURITY_SENSITIVE_ATTRS = /* @__PURE__ */ (() => new Set(Object.values(SECURITY_SENSITIVE_ELEMENTS).flatMap((attrs) => (attrs ? [...attrs.keys()] : []))))();
29915
- /**
29916
- * Returns a sanitizer for the given attribute name or null if the attribute is not security sensitive.
29917
- *
29918
- * @param attrName The name of the attribute to sanitize.
29919
- * @returns The sanitizer for the given attribute name.
29920
- */
29921
- function i18nSanitizeAttribute(attrName) {
29922
- const lowerAttrName = attrName.toLowerCase();
29923
- if (SENSITIVE_ATTRS[lowerAttrName]) {
29924
- return _sanitizeUrl;
30093
+ function splitNsName(elementName, fatal = true) {
30094
+ if (elementName[0] != ':') {
30095
+ return [null, elementName];
29925
30096
  }
29926
- if (SECURITY_SENSITIVE_ATTRS.has(lowerAttrName)) {
29927
- return ɵɵvalidateAttribute;
30097
+ const colonIndex = elementName.indexOf(':', 1);
30098
+ if (colonIndex === -1) {
30099
+ if (fatal) {
30100
+ throw new Error(`Unsupported format "${elementName}" expecting ":namespace:name"`);
30101
+ }
30102
+ else {
30103
+ return [null, elementName];
30104
+ }
30105
+ }
30106
+ return [elementName.slice(1, colonIndex), elementName.slice(colonIndex + 1)];
30107
+ }
30108
+ function normalizeTagName(tagName) {
30109
+ const tagNameLower = tagName.toLowerCase();
30110
+ const [ns, name] = splitNsName(tagNameLower, false);
30111
+ return ns === SVG_NAMESPACE$1 || ns === MATH_ML_NAMESPACE$1 ? `:${ns}:${name}` : name;
30112
+ }
30113
+ function i18nResolveSanitizer(attrName, tagName) {
30114
+ const lowerAttrName = attrName.toLowerCase();
30115
+ const lowerTagName = tagName ? normalizeTagName(tagName) : '*';
30116
+ const schema = SECURITY_SCHEMA();
30117
+ const schemaContext = schema[`${lowerTagName}|${lowerAttrName}`] ||
30118
+ schema[`*|${lowerAttrName}`] ||
30119
+ SecurityContext.NONE;
30120
+ switch (schemaContext) {
30121
+ case SecurityContext.HTML:
30122
+ return ɵɵsanitizeHtml;
30123
+ case SecurityContext.STYLE:
30124
+ return ɵɵsanitizeStyle;
30125
+ case SecurityContext.SCRIPT:
30126
+ return ɵɵsanitizeScript;
30127
+ case SecurityContext.URL:
30128
+ return _sanitizeUrl;
30129
+ case SecurityContext.RESOURCE_URL:
30130
+ return ɵɵsanitizeResourceUrl;
30131
+ case SecurityContext.ATTRIBUTE_NO_BINDING:
30132
+ return ɵɵvalidateAttribute;
30133
+ default:
30134
+ return null;
29928
30135
  }
29929
- return null;
29930
30136
  }
29931
30137
 
29932
30138
  // i18nPostprocess consts
@@ -34829,7 +35035,7 @@ class Version {
34829
35035
  /**
34830
35036
  * @publicApi
34831
35037
  */
34832
- const VERSION = new Version('19.2.22');
35038
+ const VERSION = new Version('19.2.23');
34833
35039
 
34834
35040
  /**
34835
35041
  * Combination of NgModuleFactory and ComponentFactories.