@angular/core 19.2.21 → 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 +279 -50
  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 +8 -3
  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.21
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.21
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
  /**
@@ -11510,33 +11633,41 @@ function validateAgainstEventProperties(name) {
11510
11633
  }
11511
11634
  function validateAgainstEventAttributes(name) {
11512
11635
  if (name.toLowerCase().startsWith('on')) {
11513
- const errorMessage = `Binding to event attribute '${name}' is disallowed for security reasons, ` +
11514
- `please use (${name.slice(2)})=...`;
11515
- throw new RuntimeError(306 /* RuntimeErrorCode.INVALID_EVENT_BINDING */, errorMessage);
11636
+ throw new RuntimeError(306 /* RuntimeErrorCode.INVALID_EVENT_BINDING */, ngDevMode &&
11637
+ `Binding to event attribute '${name}' is disallowed for security reasons, ` +
11638
+ `please use (${name.slice(2)})=...`);
11516
11639
  }
11517
11640
  }
11518
11641
  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
  }
@@ -12804,10 +12970,12 @@ function findDirectiveDefMatches(tView, tNode) {
12804
12970
  function elementAttributeInternal(tNode, lView, name, value, sanitizer, namespace) {
12805
12971
  if (ngDevMode) {
12806
12972
  assertNotSame(value, NO_CHANGE, 'Incoming value should never be NO_CHANGE.');
12807
- validateAgainstEventAttributes(name);
12808
12973
  assertTNodeType(tNode, 2 /* TNodeType.Element */, `Attempted to set attribute \`${name}\` on a container node. ` +
12809
12974
  `Host bindings are not valid on ng-container or ng-template.`);
12810
12975
  }
12976
+ if (lView[TVIEW].firstUpdatePass) {
12977
+ validateAgainstEventAttributes(name);
12978
+ }
12811
12979
  const element = getNativeByTNode(tNode, lView);
12812
12980
  setElementAttribute(lView[RENDERER], element, namespace, tNode.value, name, value, sanitizer);
12813
12981
  }
@@ -15588,6 +15756,7 @@ function createTNode(tView, tParent, type, index, value, attrs) {
15588
15756
  flags,
15589
15757
  providerIndexes: 0,
15590
15758
  value: value,
15759
+ namespace: getNamespace(),
15591
15760
  attrs: attrs,
15592
15761
  mergedAttrs: null,
15593
15762
  localNames: null,
@@ -18043,7 +18212,7 @@ function createHostElement(componentDef, render) {
18043
18212
  // dynamically. Default to 'div' if this component did not specify any tag name in its
18044
18213
  // selector.
18045
18214
  const tagName = (componentDef.selectors[0][0] || 'div').toLowerCase();
18046
- 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;
18047
18216
  return createElementNode(render, tagName, namespace);
18048
18217
  }
18049
18218
  /**
@@ -18086,7 +18255,7 @@ class ComponentFactory extends ComponentFactory$1 {
18086
18255
  const cmpDef = this.componentDef;
18087
18256
  ngDevMode && verifyNotAnOrphanComponent(cmpDef);
18088
18257
  const tAttributes = rootSelectorOrNode
18089
- ? ['ng-version', '19.2.21']
18258
+ ? ['ng-version', '19.2.23']
18090
18259
  : // Extract attributes and classes from the first selector only to match VE behavior.
18091
18260
  extractAttrsAndClassesFromSelector(this.componentDef.selectors[0]);
18092
18261
  // Create the root view. Uses empty TView and ContentTemplate.
@@ -28896,7 +29065,14 @@ function applyUpdateOpCodes(tView, lView, updateOpCodes, bindingsStartIndex, cha
28896
29065
  setElementAttribute(lView[RENDERER], lView[nodeIndex], null, tNodeOrTagName, propName, value, sanitizeFn);
28897
29066
  }
28898
29067
  else {
28899
- 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
+ }
28900
29076
  }
28901
29077
  break;
28902
29078
  case 0 /* I18nUpdateOpCode.Text */:
@@ -29476,7 +29652,10 @@ function i18nAttributesFirstPass(tView, index, values) {
29476
29652
  // the compiler treats static i18n attributes as regular attribute bindings.
29477
29653
  // Since this may not be the first i18n attribute on this element we need to pass in how
29478
29654
  // many previous bindings there have already been.
29479
- generateBindingUpdateOpCodes(updateOpCodes, message, previousElementIndex, attrName, countBindings(updateOpCodes), SENSITIVE_ATTRS[attrName.toLowerCase()] ? _sanitizeUrl : null);
29655
+ const tagName = previousElement.namespace
29656
+ ? `:${previousElement.namespace}:${previousElement.value}`
29657
+ : previousElement.value;
29658
+ generateBindingUpdateOpCodes(updateOpCodes, message, previousElementIndex, attrName, countBindings(updateOpCodes), i18nResolveSanitizer(attrName, tagName));
29480
29659
  }
29481
29660
  }
29482
29661
  tView.data[index] = updateOpCodes;
@@ -29802,9 +29981,15 @@ function walkIcuTree(ast, tView, tIcu, lView, sharedUpdateOpCodes, create, remov
29802
29981
  const attr = elAttrs.item(i);
29803
29982
  const lowerAttrName = attr.name.toLowerCase();
29804
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;
29805
29990
  if (hasBinding) {
29806
29991
  if (VALID_ATTRS.hasOwnProperty(lowerAttrName)) {
29807
- generateBindingUpdateOpCodes(update, attr.value, newIndex, attr.name, 0, SENSITIVE_ATTRS[lowerAttrName] ? _sanitizeUrl : null);
29992
+ generateBindingUpdateOpCodes(update, attr.value, newIndex, attr.name, 0, i18nResolveSanitizer(lowerAttrName, tagNameWithNamespace));
29808
29993
  }
29809
29994
  else {
29810
29995
  ngDevMode &&
@@ -29814,9 +29999,9 @@ function walkIcuTree(ast, tView, tIcu, lView, sharedUpdateOpCodes, create, remov
29814
29999
  }
29815
30000
  }
29816
30001
  else if (VALID_ATTRS[lowerAttrName]) {
29817
- if (SENSITIVE_ATTRS[lowerAttrName]) {
29818
- // Don't sanitize, because no value is acceptable in sensitive attributes.
29819
- // Translators are not allowed to create URIs.
30002
+ let val = attr.value;
30003
+ const sanitizer = i18nResolveSanitizer(lowerAttrName, tagNameWithNamespace);
30004
+ if (sanitizer) {
29820
30005
  if (typeof ngDevMode !== 'undefined' && ngDevMode) {
29821
30006
  console.warn(`WARNING: ignoring unsafe attribute ` +
29822
30007
  `${lowerAttrName} on element ${tagName} ` +
@@ -29825,7 +30010,7 @@ function walkIcuTree(ast, tView, tIcu, lView, sharedUpdateOpCodes, create, remov
29825
30010
  addCreateAttribute(create, newIndex, attr.name, 'unsafe:blocked');
29826
30011
  }
29827
30012
  else {
29828
- addCreateAttribute(create, newIndex, attr.name, attr.value);
30013
+ addCreateAttribute(create, newIndex, attr.name, val);
29829
30014
  }
29830
30015
  }
29831
30016
  else {
@@ -29905,6 +30090,50 @@ function addCreateNodeAndAppend(create, marker, text, appendToParentIdx, createA
29905
30090
  function addCreateAttribute(create, newIndex, attrName, attrValue) {
29906
30091
  create.push((newIndex << 1 /* IcuCreateOpCode.SHIFT_REF */) | 1 /* IcuCreateOpCode.Attr */, attrName, attrValue);
29907
30092
  }
30093
+ function splitNsName(elementName, fatal = true) {
30094
+ if (elementName[0] != ':') {
30095
+ return [null, elementName];
30096
+ }
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;
30135
+ }
30136
+ }
29908
30137
 
29909
30138
  // i18nPostprocess consts
29910
30139
  const ROOT_TEMPLATE_ID = 0;
@@ -34806,7 +35035,7 @@ class Version {
34806
35035
  /**
34807
35036
  * @publicApi
34808
35037
  */
34809
- const VERSION = new Version('19.2.21');
35038
+ const VERSION = new Version('19.2.23');
34810
35039
 
34811
35040
  /**
34812
35041
  * Combination of NgModuleFactory and ComponentFactories.