@angular/core 20.0.0-rc.2 → 20.0.0

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 (62) hide show
  1. package/api.d-B0vztftH.d.ts +1 -1
  2. package/chrome_dev_tools_performance.d-DvzAxqBc.d.ts +1 -1
  3. package/{discovery.d-Cf_r2Ojk.d.ts → discovery.d-DZNIp-Fw.d.ts} +55 -4
  4. package/event_dispatcher.d-BReQpZfC.d.ts +1 -1
  5. package/fesm2022/attribute-BWp59EjE.mjs +1 -1
  6. package/fesm2022/core.mjs +9 -9
  7. package/fesm2022/core.mjs.map +1 -1
  8. package/fesm2022/{debug_node-Nc-zr65s.mjs → debug_node-Dn-GvQJo.mjs} +1470 -2924
  9. package/fesm2022/debug_node-Dn-GvQJo.mjs.map +1 -0
  10. package/fesm2022/primitives/di.mjs +1 -1
  11. package/fesm2022/primitives/event-dispatch.mjs +1 -1
  12. package/fesm2022/primitives/signals.mjs +1 -1
  13. package/fesm2022/{resource-DOwetGLU.mjs → resource-BPCh38bN.mjs} +3 -3
  14. package/fesm2022/{resource-DOwetGLU.mjs.map → resource-BPCh38bN.mjs.map} +1 -1
  15. package/fesm2022/{root_effect_scheduler-BgGHQ80j.mjs → root_effect_scheduler-0BxwqIgm.mjs} +2 -19
  16. package/fesm2022/{root_effect_scheduler-BgGHQ80j.mjs.map → root_effect_scheduler-0BxwqIgm.mjs.map} +1 -1
  17. package/fesm2022/rxjs-interop.mjs +3 -3
  18. package/fesm2022/signal-ePSl6jXn.mjs +1 -1
  19. package/fesm2022/testing.mjs +33 -7
  20. package/fesm2022/testing.mjs.map +1 -1
  21. package/fesm2022/untracked-2ouAFbCz.mjs +1 -1
  22. package/fesm2022/weak_ref-BaIq-pgY.mjs +1 -1
  23. package/graph.d-BcIOep_B.d.ts +1 -1
  24. package/index.d.ts +619 -1730
  25. package/package.json +5 -2
  26. package/primitives/di/index.d.ts +1 -1
  27. package/primitives/event-dispatch/index.d.ts +1 -1
  28. package/primitives/signals/index.d.ts +1 -1
  29. package/rxjs-interop/index.d.ts +1 -1
  30. package/schematics/bundles/{apply_import_manager-BqwxKJiu.cjs → apply_import_manager-Bqnvtho4.cjs} +3 -3
  31. package/schematics/bundles/{change_tracker-B1qegJFu.cjs → change_tracker-DaCWdziV.cjs} +3 -3
  32. package/schematics/bundles/{checker-DmucNdBi.cjs → checker-BHgMyU8j.cjs} +11 -11
  33. package/schematics/bundles/cleanup-unused-imports.cjs +51 -13
  34. package/schematics/bundles/{compiler-DPq1iS19.cjs → compiler-Dl11rH6-.cjs} +63 -330
  35. package/schematics/bundles/compiler_host-CAfDJO3W.cjs +1 -1
  36. package/schematics/bundles/control-flow-migration.cjs +2 -2
  37. package/schematics/bundles/document-core.cjs +6 -6
  38. package/schematics/bundles/imports-CIX-JgAN.cjs +1 -1
  39. package/schematics/bundles/{index-CFmTQ_wx.cjs → index-CYxAVSJC.cjs} +5 -5
  40. package/schematics/bundles/{index-1H-qYSW6.cjs → index-DPvX-lSh.cjs} +14 -16
  41. package/schematics/bundles/inject-flags.cjs +6 -6
  42. package/schematics/bundles/inject-migration.cjs +4 -4
  43. package/schematics/bundles/leading_space-D9nQ8UQC.cjs +1 -1
  44. package/schematics/bundles/{migrate_ts_type_references-B2aJNuIK.cjs → migrate_ts_type_references-DWUePVh6.cjs} +6 -6
  45. package/schematics/bundles/ng_decorators-B5HCqr20.cjs +1 -1
  46. package/schematics/bundles/nodes-B16H9JUd.cjs +1 -1
  47. package/schematics/bundles/output-migration.cjs +7 -7
  48. package/schematics/bundles/{project_paths-DmvzlTQL.cjs → project_paths-BPBAn_A2.cjs} +4 -4
  49. package/schematics/bundles/project_tsconfig_paths-CDVxT6Ov.cjs +1 -1
  50. package/schematics/bundles/property_name-BBwFuqMe.cjs +1 -1
  51. package/schematics/bundles/route-lazy-loading.cjs +4 -4
  52. package/schematics/bundles/self-closing-tags-migration.cjs +5 -5
  53. package/schematics/bundles/signal-input-migration.cjs +8 -8
  54. package/schematics/bundles/signal-queries-migration.cjs +8 -8
  55. package/schematics/bundles/signals.cjs +8 -8
  56. package/schematics/bundles/standalone-migration.cjs +5 -5
  57. package/schematics/bundles/symbol-VPWguRxr.cjs +1 -1
  58. package/schematics/bundles/test-bed-get.cjs +5 -5
  59. package/signal.d-D6VJ67xi.d.ts +1 -1
  60. package/testing/index.d.ts +16 -3
  61. package/weak_ref.d-eGOEP9S1.d.ts +1 -1
  62. package/fesm2022/debug_node-Nc-zr65s.mjs.map +0 -1
@@ -1,10 +1,10 @@
1
1
  /**
2
- * @license Angular v20.0.0-rc.2
2
+ * @license Angular v20.0.0
3
3
  * (c) 2010-2025 Google LLC. https://angular.io/
4
4
  * License: MIT
5
5
  */
6
6
 
7
- import { attachInjectFlag, _global, resolveForwardRef, ɵɵinvalidFactoryDep as __invalidFactoryDep, ɵɵinject as __inject, ɵɵdefineInjector as __defineInjector, ɵɵdefineInjectable as __defineInjectable, newArray, assertString, EMPTY_OBJ, assertFirstCreatePass, assertDefined, assertNotEqual, FLAGS, assertEqual, isInCheckNoChangesMode, PREORDER_HOOK_FLAGS, throwError, assertNumber, assertGreaterThan, HEADER_OFFSET, DECLARATION_VIEW, throwCyclicDependencyError, stringifyForError, setInjectorProfilerContext, setInjectImplementation, enterDI, emitInjectorToCreateInstanceEvent, emitInstanceCreatedByInjectorEvent, assertDirectiveDef, leaveDI, isRootView, assertTNodeForLView, runInInjectorProfilerContext, getCurrentTNode, getLView, throwProviderNotFoundError, assertNodeInjector, injectRootLimpMode, assertIndexInRange, TVIEW, EMBEDDED_VIEW_INJECTOR, T_HOST, NG_ELEMENT_ID, INJECTOR$1 as INJECTOR, isComponentDef, isComponentHost, convertToBitFlags, NG_FACTORY_DEF, isForwardRef, getFactoryDef, DECLARATION_COMPONENT_VIEW, RuntimeError, NG_PROV_DEF, getClosureSafeProperty, getNativeByTNode, flatten, arrayEquals, ID, isLView, assertDomNode, getComponentLViewByIndex, CONTEXT, EMPTY_ARRAY, unwrapRNode, assertLView, HOST, getLViewParent, CHILD_HEAD, NEXT, isLContainer, Injector, CLEANUP, getComponentDef, getDirectiveDef, InjectionToken, inject, isContentQueryHost, setCurrentQueryIndex, XSS_SECURITY_URL, renderStringify, ENVIRONMENT, makeEnvironmentProviders, formatRuntimeError, resetPreOrderHookFlags, PARENT, RENDERER, HYDRATION, CHILD_TAIL, assertSame, assertFirstUpdatePass, getSelectedIndex, getTView, assertIndexInDeclRange, setSelectedIndex, INTERNAL_APPLICATION_ERROR_HANDLER, assertNotSame, setCurrentDirectiveIndex, stringify, getCurrentDirectiveIndex, unwrapLView, assertNotReactive, enterView, QUERIES, leaveView, isCreationMode, assertLContainer, DECLARATION_LCONTAINER, isDestroyed, MOVED_VIEWS, NATIVE, assertProjectionSlots, CONTAINER_HEADER_OFFSET, assertParentView, REACTIVE_TEMPLATE_CONSUMER, ON_DESTROY_HOOKS, assertFunction, EFFECTS, AFTER_RENDER_SEQUENCES_TO_ADD, markViewForRefresh, markAncestorsForTraversal, setIsInCheckNoChangesMode, setIsRefreshingViews, isExhaustiveCheckNoChanges, requiresRefreshOrTraversal, setBindingIndex, EFFECTS_TO_SCHEDULE, setBindingRootForHostBindings, viewAttachedToChangeDetector, isRefreshingViews, CheckNoChangesMode, removeFromArray, addToArray, updateAncestorTraversalFlagsOnAttach, storeLViewOnDestroy, VIEW_REFS, assertGreaterThanOrEqual, isInI18nBlock, getCurrentParentTNode, assertTNodeForTView, setCurrentTNode, getCurrentTNodePlaceholderOk, isCurrentTNodeParent, isInSkipHydrationBlock as isInSkipHydrationBlock$1, assertTNode, assertTIcu, assertNumberInRange, DEHYDRATED_VIEWS, getNgModuleDef, getPipeDef as getPipeDef$1, getNgModuleDefOrThrow, isStandalone, concatStringsWithSpace, assertInjectImplementationNotEqual, emitInjectEvent, getConstant, assertLessThan, getOrCreateTViewCleanup, getOrCreateLViewCleanup, isDirectiveHost, assertNotDefined, getSelectedTNode, nextBindingIndex, getTNode, debugStringifyTypeForError, getDirectiveDefOrThrow, ChangeDetectionScheduler, assertComponentType, EnvironmentInjector, SVG_NAMESPACE, MATH_ML_NAMESPACE, viewAttachedToContainer, storeCleanupWithContext, signal, createInjectorWithoutInjectorInstances, R3Injector, getNullInjector, internalImportProvidersFrom, initNgDevMode, fillProperties, wasLastNodeCreated, getBindingsEnabled, lastNodeWasCreated, isInInjectionContext, DestroyRef, PendingTasksInternal, noop, ErrorHandler, assertNotInReactiveContext, assertInInjectionContext, ViewContext, removeLViewOnDestroy, walkUpViews, getNativeByIndex, assertElement, arrayInsert2, arraySplice, setInjectorProfiler, NullInjector, ENVIRONMENT_INITIALIZER, INJECTOR_DEF_TYPES, walkProviderTree, getInjectorDef, deepForEach, isTypeProvider, isSignal, runInInjectionContext, ZONELESS_ENABLED, EffectScheduler, PendingTasks, incrementBindingIndex, getBindingIndex, keyValueArrayIndexOf, keyValueArrayGet, getCurrentDirectiveDef, keyValueArraySet, assertHasParent, getElementDepthCount, getNamespace, enterSkipHydrationBlock, increaseElementDepthCount, setCurrentTNodeAsNotParent, isSkipHydrationRootTNode, leaveSkipHydrationBlock, decreaseElementDepthCount, assertIndexInExpandoRange, assertOneOf, setInI18nBlock, nextContextImpl, getCurrentQueryIndex, getContextLView, load, isWritableSignal, store, providerToFactory, emitProviderConfiguredEvent, isClassProvider, getBindingRoot, NG_COMP_DEF, forwardRef, ɵɵrestoreView as __restoreView, ɵɵdisableBindings as __disableBindings, ɵɵenableBindings as __enableBindings, ɵɵnamespaceSVG as __namespaceSVG, ɵɵnamespaceMathML as __namespaceMathML, ɵɵnamespaceHTML as __namespaceHTML, ɵɵresetView as __resetView, NG_MOD_DEF, NG_INJ_DEF, NG_DIR_DEF, NG_PIPE_DEF, ZONELESS_SCHEDULER_DISABLED, SCHEDULE_IN_ROOT_ZONE, PROVIDED_ZONELESS, getNativeByTNodeOrNull } from './root_effect_scheduler-BgGHQ80j.mjs';
7
+ import { attachInjectFlag, _global, resolveForwardRef, ɵɵinvalidFactoryDep as __invalidFactoryDep, ɵɵinject as __inject, ɵɵdefineInjector as __defineInjector, ɵɵdefineInjectable as __defineInjectable, newArray, assertString, EMPTY_OBJ, assertFirstCreatePass, assertDefined, assertNotEqual, FLAGS, assertEqual, isInCheckNoChangesMode, PREORDER_HOOK_FLAGS, throwError, assertNumber, assertGreaterThan, HEADER_OFFSET, DECLARATION_VIEW, throwCyclicDependencyError, stringifyForError, setInjectorProfilerContext, setInjectImplementation, enterDI, emitInjectorToCreateInstanceEvent, emitInstanceCreatedByInjectorEvent, assertDirectiveDef, leaveDI, isRootView, assertTNodeForLView, runInInjectorProfilerContext, getCurrentTNode, getLView, throwProviderNotFoundError, assertNodeInjector, injectRootLimpMode, assertIndexInRange, TVIEW, EMBEDDED_VIEW_INJECTOR, T_HOST, NG_ELEMENT_ID, INJECTOR$1 as INJECTOR, isComponentDef, isComponentHost, convertToBitFlags, NG_FACTORY_DEF, isForwardRef, getFactoryDef, DECLARATION_COMPONENT_VIEW, RuntimeError, NG_PROV_DEF, getClosureSafeProperty, getNativeByTNode, flatten, arrayEquals, ID, isLView, assertDomNode, getComponentLViewByIndex, CONTEXT, EMPTY_ARRAY, unwrapRNode, assertLView, HOST, getLViewParent, CHILD_HEAD, NEXT, isLContainer, Injector, CLEANUP, getComponentDef, getDirectiveDef, InjectionToken, inject, isContentQueryHost, setCurrentQueryIndex, XSS_SECURITY_URL, renderStringify, ENVIRONMENT, makeEnvironmentProviders, formatRuntimeError, resetPreOrderHookFlags, PARENT, RENDERER, HYDRATION, CHILD_TAIL, assertSame, assertFirstUpdatePass, getSelectedIndex, getTView, assertIndexInDeclRange, setSelectedIndex, INTERNAL_APPLICATION_ERROR_HANDLER, assertNotSame, setCurrentDirectiveIndex, stringify, getCurrentDirectiveIndex, unwrapLView, assertNotReactive, enterView, QUERIES, leaveView, isCreationMode, assertLContainer, DECLARATION_LCONTAINER, isDestroyed, MOVED_VIEWS, NATIVE, assertProjectionSlots, CONTAINER_HEADER_OFFSET, assertParentView, REACTIVE_TEMPLATE_CONSUMER, ON_DESTROY_HOOKS, assertFunction, EFFECTS, AFTER_RENDER_SEQUENCES_TO_ADD, markViewForRefresh, markAncestorsForTraversal, setIsInCheckNoChangesMode, setIsRefreshingViews, isExhaustiveCheckNoChanges, requiresRefreshOrTraversal, setBindingIndex, EFFECTS_TO_SCHEDULE, setBindingRootForHostBindings, viewAttachedToChangeDetector, isRefreshingViews, CheckNoChangesMode, removeFromArray, addToArray, updateAncestorTraversalFlagsOnAttach, storeLViewOnDestroy, VIEW_REFS, assertGreaterThanOrEqual, isInI18nBlock, getCurrentParentTNode, assertTNodeForTView, setCurrentTNode, getCurrentTNodePlaceholderOk, isCurrentTNodeParent, isInSkipHydrationBlock as isInSkipHydrationBlock$1, assertTNode, assertTIcu, assertNumberInRange, DEHYDRATED_VIEWS, getNgModuleDef, getPipeDef as getPipeDef$1, getNgModuleDefOrThrow, isStandalone, concatStringsWithSpace, assertInjectImplementationNotEqual, emitInjectEvent, getConstant, assertLessThan, getOrCreateTViewCleanup, getOrCreateLViewCleanup, isDirectiveHost, assertNotDefined, getSelectedTNode, nextBindingIndex, getTNode, debugStringifyTypeForError, getDirectiveDefOrThrow, ChangeDetectionScheduler, assertComponentType, EnvironmentInjector, SVG_NAMESPACE, MATH_ML_NAMESPACE, viewAttachedToContainer, storeCleanupWithContext, signal, createInjectorWithoutInjectorInstances, R3Injector, getNullInjector, internalImportProvidersFrom, initNgDevMode, fillProperties, wasLastNodeCreated, getBindingsEnabled, lastNodeWasCreated, isInInjectionContext, DestroyRef, PendingTasksInternal, noop, ErrorHandler, assertNotInReactiveContext, assertInInjectionContext, ViewContext, removeLViewOnDestroy, walkUpViews, getNativeByIndex, assertElement, arrayInsert2, arraySplice, setInjectorProfiler, NullInjector, ENVIRONMENT_INITIALIZER, INJECTOR_DEF_TYPES, walkProviderTree, getInjectorDef, deepForEach, isTypeProvider, isSignal, runInInjectionContext, ZONELESS_ENABLED, EffectScheduler, PendingTasks, assertHasParent, getElementDepthCount, getNamespace, enterSkipHydrationBlock, getBindingIndex, increaseElementDepthCount, setCurrentTNodeAsNotParent, isSkipHydrationRootTNode, leaveSkipHydrationBlock, decreaseElementDepthCount, getCurrentDirectiveDef, assertIndexInExpandoRange, assertOneOf, setInI18nBlock, nextContextImpl, getCurrentQueryIndex, getContextLView, load, keyValueArrayIndexOf, incrementBindingIndex, keyValueArrayGet, keyValueArraySet, isWritableSignal, store, providerToFactory, emitProviderConfiguredEvent, isClassProvider, getBindingRoot, NG_COMP_DEF, forwardRef, ɵɵrestoreView as __restoreView, ɵɵdisableBindings as __disableBindings, ɵɵenableBindings as __enableBindings, ɵɵnamespaceSVG as __namespaceSVG, ɵɵnamespaceMathML as __namespaceMathML, ɵɵnamespaceHTML as __namespaceHTML, ɵɵresetView as __resetView, NG_MOD_DEF, NG_INJ_DEF, NG_DIR_DEF, NG_PIPE_DEF, ZONELESS_SCHEDULER_DISABLED, SCHEDULE_IN_ROOT_ZONE, PROVIDED_ZONELESS, getNativeByTNodeOrNull } from './root_effect_scheduler-0BxwqIgm.mjs';
8
8
  import { setActiveConsumer, SIGNAL, consumerDestroy, REACTIVE_NODE, consumerPollProducersForChange, consumerBeforeComputation, getActiveConsumer, consumerAfterComputation, createComputed, setThrowInvalidWriteToSignalError } from './signal-ePSl6jXn.mjs';
9
9
  import { Subject, Subscription } from 'rxjs';
10
10
  import { setActiveConsumer as setActiveConsumer$1 } from '@angular/core/primitives/signals';
@@ -13386,7 +13386,7 @@ class ComponentFactory extends ComponentFactory$1 {
13386
13386
  }
13387
13387
  function createRootTView(rootSelectorOrNode, componentDef, componentBindings, directives) {
13388
13388
  const tAttributes = rootSelectorOrNode
13389
- ? ['ng-version', '20.0.0-rc.2']
13389
+ ? ['ng-version', '20.0.0']
13390
13390
  : // Extract attributes and classes from the first selector only to match VE behavior.
13391
13391
  extractAttrsAndClassesFromSelector(componentDef.selectors[0]);
13392
13392
  let creationBindings = null;
@@ -21402,1872 +21402,6 @@ function ɵɵattribute(name, value, sanitizer, namespace) {
21402
21402
  return ɵɵattribute;
21403
21403
  }
21404
21404
 
21405
- /**
21406
- * Create interpolation bindings with a variable number of expressions.
21407
- *
21408
- * If there are 1 to 8 expressions `interpolation1()` to `interpolation8()` should be used instead.
21409
- * Those are faster because there is no need to create an array of expressions and iterate over it.
21410
- *
21411
- * `values`:
21412
- * - has static text at even indexes,
21413
- * - has evaluated expressions at odd indexes.
21414
- *
21415
- * Returns the concatenated string when any of the arguments changes, `NO_CHANGE` otherwise.
21416
- */
21417
- function interpolationV(lView, values) {
21418
- ngDevMode && assertLessThan(2, values.length, 'should have at least 3 values');
21419
- let isBindingUpdated = false;
21420
- let bindingIndex = getBindingIndex();
21421
- for (let i = 1; i < values.length; i += 2) {
21422
- // Check if bindings (odd indexes) have changed
21423
- isBindingUpdated = bindingUpdated(lView, bindingIndex++, values[i]) || isBindingUpdated;
21424
- }
21425
- setBindingIndex(bindingIndex);
21426
- if (!isBindingUpdated) {
21427
- return NO_CHANGE;
21428
- }
21429
- // Build the updated content
21430
- let content = values[0];
21431
- for (let i = 1; i < values.length; i += 2) {
21432
- // The condition is to prevent an out-of-bound read
21433
- content += renderStringify(values[i]) + (i + 1 !== values.length ? values[i + 1] : '');
21434
- }
21435
- return content;
21436
- }
21437
- /**
21438
- * Creates an interpolation binding with 1 expression.
21439
- *
21440
- * @param prefix static value used for concatenation only.
21441
- * @param v0 value checked for change.
21442
- * @param suffix static value used for concatenation only.
21443
- */
21444
- function interpolation1(lView, prefix, v0, suffix = '') {
21445
- const different = bindingUpdated(lView, nextBindingIndex(), v0);
21446
- return different ? prefix + renderStringify(v0) + suffix : NO_CHANGE;
21447
- }
21448
- /**
21449
- * Creates an interpolation binding with 2 expressions.
21450
- */
21451
- function interpolation2(lView, prefix, v0, i0, v1, suffix = '') {
21452
- const bindingIndex = getBindingIndex();
21453
- const different = bindingUpdated2(lView, bindingIndex, v0, v1);
21454
- incrementBindingIndex(2);
21455
- return different ? prefix + renderStringify(v0) + i0 + renderStringify(v1) + suffix : NO_CHANGE;
21456
- }
21457
- /**
21458
- * Creates an interpolation binding with 3 expressions.
21459
- */
21460
- function interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix = '') {
21461
- const bindingIndex = getBindingIndex();
21462
- const different = bindingUpdated3(lView, bindingIndex, v0, v1, v2);
21463
- incrementBindingIndex(3);
21464
- return different
21465
- ? prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 + renderStringify(v2) + suffix
21466
- : NO_CHANGE;
21467
- }
21468
- /**
21469
- * Create an interpolation binding with 4 expressions.
21470
- */
21471
- function interpolation4(lView, prefix, v0, i0, v1, i1, v2, i2, v3, suffix = '') {
21472
- const bindingIndex = getBindingIndex();
21473
- const different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);
21474
- incrementBindingIndex(4);
21475
- return different
21476
- ? prefix +
21477
- renderStringify(v0) +
21478
- i0 +
21479
- renderStringify(v1) +
21480
- i1 +
21481
- renderStringify(v2) +
21482
- i2 +
21483
- renderStringify(v3) +
21484
- suffix
21485
- : NO_CHANGE;
21486
- }
21487
- /**
21488
- * Creates an interpolation binding with 5 expressions.
21489
- */
21490
- function interpolation5(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix = '') {
21491
- const bindingIndex = getBindingIndex();
21492
- let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);
21493
- different = bindingUpdated(lView, bindingIndex + 4, v4) || different;
21494
- incrementBindingIndex(5);
21495
- return different
21496
- ? prefix +
21497
- renderStringify(v0) +
21498
- i0 +
21499
- renderStringify(v1) +
21500
- i1 +
21501
- renderStringify(v2) +
21502
- i2 +
21503
- renderStringify(v3) +
21504
- i3 +
21505
- renderStringify(v4) +
21506
- suffix
21507
- : NO_CHANGE;
21508
- }
21509
- /**
21510
- * Creates an interpolation binding with 6 expressions.
21511
- */
21512
- function interpolation6(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix = '') {
21513
- const bindingIndex = getBindingIndex();
21514
- let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);
21515
- different = bindingUpdated2(lView, bindingIndex + 4, v4, v5) || different;
21516
- incrementBindingIndex(6);
21517
- return different
21518
- ? prefix +
21519
- renderStringify(v0) +
21520
- i0 +
21521
- renderStringify(v1) +
21522
- i1 +
21523
- renderStringify(v2) +
21524
- i2 +
21525
- renderStringify(v3) +
21526
- i3 +
21527
- renderStringify(v4) +
21528
- i4 +
21529
- renderStringify(v5) +
21530
- suffix
21531
- : NO_CHANGE;
21532
- }
21533
- /**
21534
- * Creates an interpolation binding with 7 expressions.
21535
- */
21536
- function interpolation7(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix = '') {
21537
- const bindingIndex = getBindingIndex();
21538
- let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);
21539
- different = bindingUpdated3(lView, bindingIndex + 4, v4, v5, v6) || different;
21540
- incrementBindingIndex(7);
21541
- return different
21542
- ? prefix +
21543
- renderStringify(v0) +
21544
- i0 +
21545
- renderStringify(v1) +
21546
- i1 +
21547
- renderStringify(v2) +
21548
- i2 +
21549
- renderStringify(v3) +
21550
- i3 +
21551
- renderStringify(v4) +
21552
- i4 +
21553
- renderStringify(v5) +
21554
- i5 +
21555
- renderStringify(v6) +
21556
- suffix
21557
- : NO_CHANGE;
21558
- }
21559
- /**
21560
- * Creates an interpolation binding with 8 expressions.
21561
- */
21562
- function interpolation8(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix = '') {
21563
- const bindingIndex = getBindingIndex();
21564
- let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);
21565
- different = bindingUpdated4(lView, bindingIndex + 4, v4, v5, v6, v7) || different;
21566
- incrementBindingIndex(8);
21567
- return different
21568
- ? prefix +
21569
- renderStringify(v0) +
21570
- i0 +
21571
- renderStringify(v1) +
21572
- i1 +
21573
- renderStringify(v2) +
21574
- i2 +
21575
- renderStringify(v3) +
21576
- i3 +
21577
- renderStringify(v4) +
21578
- i4 +
21579
- renderStringify(v5) +
21580
- i5 +
21581
- renderStringify(v6) +
21582
- i6 +
21583
- renderStringify(v7) +
21584
- suffix
21585
- : NO_CHANGE;
21586
- }
21587
-
21588
- function toTStylingRange(prev, next) {
21589
- ngDevMode && assertNumberInRange(prev, 0, 32767 /* StylingRange.UNSIGNED_MASK */);
21590
- ngDevMode && assertNumberInRange(next, 0, 32767 /* StylingRange.UNSIGNED_MASK */);
21591
- return ((prev << 17 /* StylingRange.PREV_SHIFT */) | (next << 2 /* StylingRange.NEXT_SHIFT */));
21592
- }
21593
- function getTStylingRangePrev(tStylingRange) {
21594
- ngDevMode && assertNumber(tStylingRange, 'expected number');
21595
- return (tStylingRange >> 17 /* StylingRange.PREV_SHIFT */) & 32767 /* StylingRange.UNSIGNED_MASK */;
21596
- }
21597
- function getTStylingRangePrevDuplicate(tStylingRange) {
21598
- ngDevMode && assertNumber(tStylingRange, 'expected number');
21599
- return (tStylingRange & 2 /* StylingRange.PREV_DUPLICATE */) == 2 /* StylingRange.PREV_DUPLICATE */;
21600
- }
21601
- function setTStylingRangePrev(tStylingRange, previous) {
21602
- ngDevMode && assertNumber(tStylingRange, 'expected number');
21603
- ngDevMode && assertNumberInRange(previous, 0, 32767 /* StylingRange.UNSIGNED_MASK */);
21604
- return ((tStylingRange & 131071 /* StylingRange.PREV_MASK */) |
21605
- (previous << 17 /* StylingRange.PREV_SHIFT */));
21606
- }
21607
- function setTStylingRangePrevDuplicate(tStylingRange) {
21608
- ngDevMode && assertNumber(tStylingRange, 'expected number');
21609
- return (tStylingRange | 2 /* StylingRange.PREV_DUPLICATE */);
21610
- }
21611
- function getTStylingRangeNext(tStylingRange) {
21612
- ngDevMode && assertNumber(tStylingRange, 'expected number');
21613
- return (tStylingRange & 131068 /* StylingRange.NEXT_MASK */) >> 2 /* StylingRange.NEXT_SHIFT */;
21614
- }
21615
- function setTStylingRangeNext(tStylingRange, next) {
21616
- ngDevMode && assertNumber(tStylingRange, 'expected number');
21617
- ngDevMode && assertNumberInRange(next, 0, 32767 /* StylingRange.UNSIGNED_MASK */);
21618
- return ((tStylingRange & -131069 /* StylingRange.NEXT_MASK */) | //
21619
- (next << 2 /* StylingRange.NEXT_SHIFT */));
21620
- }
21621
- function getTStylingRangeNextDuplicate(tStylingRange) {
21622
- ngDevMode && assertNumber(tStylingRange, 'expected number');
21623
- return (tStylingRange & 1 /* StylingRange.NEXT_DUPLICATE */) === 1 /* StylingRange.NEXT_DUPLICATE */;
21624
- }
21625
- function setTStylingRangeNextDuplicate(tStylingRange) {
21626
- ngDevMode && assertNumber(tStylingRange, 'expected number');
21627
- return (tStylingRange | 1 /* StylingRange.NEXT_DUPLICATE */);
21628
- }
21629
-
21630
- /**
21631
- * Insert new `tStyleValue` at `TData` and link existing style bindings such that we maintain linked
21632
- * list of styles and compute the duplicate flag.
21633
- *
21634
- * Note: this function is executed during `firstUpdatePass` only to populate the `TView.data`.
21635
- *
21636
- * The function works by keeping track of `tStylingRange` which contains two pointers pointing to
21637
- * the head/tail of the template portion of the styles.
21638
- * - if `isHost === false` (we are template) then insertion is at tail of `TStylingRange`
21639
- * - if `isHost === true` (we are host binding) then insertion is at head of `TStylingRange`
21640
- *
21641
- * @param tData The `TData` to insert into.
21642
- * @param tNode `TNode` associated with the styling element.
21643
- * @param tStylingKey See `TStylingKey`.
21644
- * @param index location of where `tStyleValue` should be stored (and linked into list.)
21645
- * @param isHostBinding `true` if the insertion is for a `hostBinding`. (insertion is in front of
21646
- * template.)
21647
- * @param isClassBinding True if the associated `tStylingKey` as a `class` styling.
21648
- * `tNode.classBindings` should be used (or `tNode.styleBindings` otherwise.)
21649
- */
21650
- function insertTStylingBinding(tData, tNode, tStylingKeyWithStatic, index, isHostBinding, isClassBinding) {
21651
- ngDevMode && assertFirstUpdatePass(getTView());
21652
- let tBindings = isClassBinding ? tNode.classBindings : tNode.styleBindings;
21653
- let tmplHead = getTStylingRangePrev(tBindings);
21654
- let tmplTail = getTStylingRangeNext(tBindings);
21655
- tData[index] = tStylingKeyWithStatic;
21656
- let isKeyDuplicateOfStatic = false;
21657
- let tStylingKey;
21658
- if (Array.isArray(tStylingKeyWithStatic)) {
21659
- // We are case when the `TStylingKey` contains static fields as well.
21660
- const staticKeyValueArray = tStylingKeyWithStatic;
21661
- tStylingKey = staticKeyValueArray[1]; // unwrap.
21662
- // We need to check if our key is present in the static so that we can mark it as duplicate.
21663
- if (tStylingKey === null ||
21664
- keyValueArrayIndexOf(staticKeyValueArray, tStylingKey) > 0) {
21665
- // tStylingKey is present in the statics, need to mark it as duplicate.
21666
- isKeyDuplicateOfStatic = true;
21667
- }
21668
- }
21669
- else {
21670
- tStylingKey = tStylingKeyWithStatic;
21671
- }
21672
- if (isHostBinding) {
21673
- // We are inserting host bindings
21674
- // If we don't have template bindings then `tail` is 0.
21675
- const hasTemplateBindings = tmplTail !== 0;
21676
- // This is important to know because that means that the `head` can't point to the first
21677
- // template bindings (there are none.) Instead the head points to the tail of the template.
21678
- if (hasTemplateBindings) {
21679
- // template head's "prev" will point to last host binding or to 0 if no host bindings yet
21680
- const previousNode = getTStylingRangePrev(tData[tmplHead + 1]);
21681
- tData[index + 1] = toTStylingRange(previousNode, tmplHead);
21682
- // if a host binding has already been registered, we need to update the next of that host
21683
- // binding to point to this one
21684
- if (previousNode !== 0) {
21685
- // We need to update the template-tail value to point to us.
21686
- tData[previousNode + 1] = setTStylingRangeNext(tData[previousNode + 1], index);
21687
- }
21688
- // The "previous" of the template binding head should point to this host binding
21689
- tData[tmplHead + 1] = setTStylingRangePrev(tData[tmplHead + 1], index);
21690
- }
21691
- else {
21692
- tData[index + 1] = toTStylingRange(tmplHead, 0);
21693
- // if a host binding has already been registered, we need to update the next of that host
21694
- // binding to point to this one
21695
- if (tmplHead !== 0) {
21696
- // We need to update the template-tail value to point to us.
21697
- tData[tmplHead + 1] = setTStylingRangeNext(tData[tmplHead + 1], index);
21698
- }
21699
- // if we don't have template, the head points to template-tail, and needs to be advanced.
21700
- tmplHead = index;
21701
- }
21702
- }
21703
- else {
21704
- // We are inserting in template section.
21705
- // We need to set this binding's "previous" to the current template tail
21706
- tData[index + 1] = toTStylingRange(tmplTail, 0);
21707
- ngDevMode &&
21708
- assertEqual(tmplHead !== 0 && tmplTail === 0, false, 'Adding template bindings after hostBindings is not allowed.');
21709
- if (tmplHead === 0) {
21710
- tmplHead = index;
21711
- }
21712
- else {
21713
- // We need to update the previous value "next" to point to this binding
21714
- tData[tmplTail + 1] = setTStylingRangeNext(tData[tmplTail + 1], index);
21715
- }
21716
- tmplTail = index;
21717
- }
21718
- // Now we need to update / compute the duplicates.
21719
- // Starting with our location search towards head (least priority)
21720
- if (isKeyDuplicateOfStatic) {
21721
- tData[index + 1] = setTStylingRangePrevDuplicate(tData[index + 1]);
21722
- }
21723
- markDuplicates(tData, tStylingKey, index, true);
21724
- markDuplicates(tData, tStylingKey, index, false);
21725
- markDuplicateOfResidualStyling(tNode, tStylingKey, tData, index, isClassBinding);
21726
- tBindings = toTStylingRange(tmplHead, tmplTail);
21727
- if (isClassBinding) {
21728
- tNode.classBindings = tBindings;
21729
- }
21730
- else {
21731
- tNode.styleBindings = tBindings;
21732
- }
21733
- }
21734
- /**
21735
- * Look into the residual styling to see if the current `tStylingKey` is duplicate of residual.
21736
- *
21737
- * @param tNode `TNode` where the residual is stored.
21738
- * @param tStylingKey `TStylingKey` to store.
21739
- * @param tData `TData` associated with the current `LView`.
21740
- * @param index location of where `tStyleValue` should be stored (and linked into list.)
21741
- * @param isClassBinding True if the associated `tStylingKey` as a `class` styling.
21742
- * `tNode.classBindings` should be used (or `tNode.styleBindings` otherwise.)
21743
- */
21744
- function markDuplicateOfResidualStyling(tNode, tStylingKey, tData, index, isClassBinding) {
21745
- const residual = isClassBinding ? tNode.residualClasses : tNode.residualStyles;
21746
- if (residual != null /* or undefined */ &&
21747
- typeof tStylingKey == 'string' &&
21748
- keyValueArrayIndexOf(residual, tStylingKey) >= 0) {
21749
- // We have duplicate in the residual so mark ourselves as duplicate.
21750
- tData[index + 1] = setTStylingRangeNextDuplicate(tData[index + 1]);
21751
- }
21752
- }
21753
- /**
21754
- * Marks `TStyleValue`s as duplicates if another style binding in the list has the same
21755
- * `TStyleValue`.
21756
- *
21757
- * NOTE: this function is intended to be called twice once with `isPrevDir` set to `true` and once
21758
- * with it set to `false` to search both the previous as well as next items in the list.
21759
- *
21760
- * No duplicate case
21761
- * ```
21762
- * [style.color]
21763
- * [style.width.px] <<- index
21764
- * [style.height.px]
21765
- * ```
21766
- *
21767
- * In the above case adding `[style.width.px]` to the existing `[style.color]` produces no
21768
- * duplicates because `width` is not found in any other part of the linked list.
21769
- *
21770
- * Duplicate case
21771
- * ```
21772
- * [style.color]
21773
- * [style.width.em]
21774
- * [style.width.px] <<- index
21775
- * ```
21776
- * In the above case adding `[style.width.px]` will produce a duplicate with `[style.width.em]`
21777
- * because `width` is found in the chain.
21778
- *
21779
- * Map case 1
21780
- * ```
21781
- * [style.width.px]
21782
- * [style.color]
21783
- * [style] <<- index
21784
- * ```
21785
- * In the above case adding `[style]` will produce a duplicate with any other bindings because
21786
- * `[style]` is a Map and as such is fully dynamic and could produce `color` or `width`.
21787
- *
21788
- * Map case 2
21789
- * ```
21790
- * [style]
21791
- * [style.width.px]
21792
- * [style.color] <<- index
21793
- * ```
21794
- * In the above case adding `[style.color]` will produce a duplicate because there is already a
21795
- * `[style]` binding which is a Map and as such is fully dynamic and could produce `color` or
21796
- * `width`.
21797
- *
21798
- * NOTE: Once `[style]` (Map) is added into the system all things are mapped as duplicates.
21799
- * NOTE: We use `style` as example, but same logic is applied to `class`es as well.
21800
- *
21801
- * @param tData `TData` where the linked list is stored.
21802
- * @param tStylingKey `TStylingKeyPrimitive` which contains the value to compare to other keys in
21803
- * the linked list.
21804
- * @param index Starting location in the linked list to search from
21805
- * @param isPrevDir Direction.
21806
- * - `true` for previous (lower priority);
21807
- * - `false` for next (higher priority).
21808
- */
21809
- function markDuplicates(tData, tStylingKey, index, isPrevDir) {
21810
- const tStylingAtIndex = tData[index + 1];
21811
- const isMap = tStylingKey === null;
21812
- let cursor = isPrevDir
21813
- ? getTStylingRangePrev(tStylingAtIndex)
21814
- : getTStylingRangeNext(tStylingAtIndex);
21815
- let foundDuplicate = false;
21816
- // We keep iterating as long as we have a cursor
21817
- // AND either:
21818
- // - we found what we are looking for, OR
21819
- // - we are a map in which case we have to continue searching even after we find what we were
21820
- // looking for since we are a wild card and everything needs to be flipped to duplicate.
21821
- while (cursor !== 0 && (foundDuplicate === false || isMap)) {
21822
- ngDevMode && assertIndexInRange(tData, cursor);
21823
- const tStylingValueAtCursor = tData[cursor];
21824
- const tStyleRangeAtCursor = tData[cursor + 1];
21825
- if (isStylingMatch(tStylingValueAtCursor, tStylingKey)) {
21826
- foundDuplicate = true;
21827
- tData[cursor + 1] = isPrevDir
21828
- ? setTStylingRangeNextDuplicate(tStyleRangeAtCursor)
21829
- : setTStylingRangePrevDuplicate(tStyleRangeAtCursor);
21830
- }
21831
- cursor = isPrevDir
21832
- ? getTStylingRangePrev(tStyleRangeAtCursor)
21833
- : getTStylingRangeNext(tStyleRangeAtCursor);
21834
- }
21835
- if (foundDuplicate) {
21836
- // if we found a duplicate, than mark ourselves.
21837
- tData[index + 1] = isPrevDir
21838
- ? setTStylingRangePrevDuplicate(tStylingAtIndex)
21839
- : setTStylingRangeNextDuplicate(tStylingAtIndex);
21840
- }
21841
- }
21842
- /**
21843
- * Determines if two `TStylingKey`s are a match.
21844
- *
21845
- * When computing whether a binding contains a duplicate, we need to compare if the instruction
21846
- * `TStylingKey` has a match.
21847
- *
21848
- * Here are examples of `TStylingKey`s which match given `tStylingKeyCursor` is:
21849
- * - `color`
21850
- * - `color` // Match another color
21851
- * - `null` // That means that `tStylingKey` is a `classMap`/`styleMap` instruction
21852
- * - `['', 'color', 'other', true]` // wrapped `color` so match
21853
- * - `['', null, 'other', true]` // wrapped `null` so match
21854
- * - `['', 'width', 'color', 'value']` // wrapped static value contains a match on `'color'`
21855
- * - `null` // `tStylingKeyCursor` always match as it is `classMap`/`styleMap` instruction
21856
- *
21857
- * @param tStylingKeyCursor
21858
- * @param tStylingKey
21859
- */
21860
- function isStylingMatch(tStylingKeyCursor, tStylingKey) {
21861
- ngDevMode &&
21862
- assertNotEqual(Array.isArray(tStylingKey), true, "Expected that 'tStylingKey' has been unwrapped");
21863
- if (tStylingKeyCursor === null || // If the cursor is `null` it means that we have map at that
21864
- // location so we must assume that we have a match.
21865
- tStylingKey == null || // If `tStylingKey` is `null` then it is a map therefor assume that it
21866
- // contains a match.
21867
- (Array.isArray(tStylingKeyCursor) ? tStylingKeyCursor[1] : tStylingKeyCursor) === tStylingKey // If the keys match explicitly than we are a match.
21868
- ) {
21869
- return true;
21870
- }
21871
- else if (Array.isArray(tStylingKeyCursor) && typeof tStylingKey === 'string') {
21872
- // if we did not find a match, but `tStylingKeyCursor` is `KeyValueArray` that means cursor has
21873
- // statics and we need to check those as well.
21874
- return keyValueArrayIndexOf(tStylingKeyCursor, tStylingKey) >= 0; // see if we are matching the key
21875
- }
21876
- return false;
21877
- }
21878
-
21879
- // Global state of the parser. (This makes parser non-reentrant, but that is not an issue)
21880
- const parserState = {
21881
- textEnd: 0,
21882
- key: 0,
21883
- keyEnd: 0,
21884
- value: 0,
21885
- valueEnd: 0,
21886
- };
21887
- /**
21888
- * Retrieves the last parsed `key` of style.
21889
- * @param text the text to substring the key from.
21890
- */
21891
- function getLastParsedKey(text) {
21892
- return text.substring(parserState.key, parserState.keyEnd);
21893
- }
21894
- /**
21895
- * Retrieves the last parsed `value` of style.
21896
- * @param text the text to substring the key from.
21897
- */
21898
- function getLastParsedValue(text) {
21899
- return text.substring(parserState.value, parserState.valueEnd);
21900
- }
21901
- /**
21902
- * Initializes `className` string for parsing and parses the first token.
21903
- *
21904
- * This function is intended to be used in this format:
21905
- * ```ts
21906
- * for (let i = parseClassName(text); i >= 0; i = parseClassNameNext(text, i)) {
21907
- * const key = getLastParsedKey();
21908
- * ...
21909
- * }
21910
- * ```
21911
- * @param text `className` to parse
21912
- * @returns index where the next invocation of `parseClassNameNext` should resume.
21913
- */
21914
- function parseClassName(text) {
21915
- resetParserState(text);
21916
- return parseClassNameNext(text, consumeWhitespace(text, 0, parserState.textEnd));
21917
- }
21918
- /**
21919
- * Parses next `className` token.
21920
- *
21921
- * This function is intended to be used in this format:
21922
- * ```ts
21923
- * for (let i = parseClassName(text); i >= 0; i = parseClassNameNext(text, i)) {
21924
- * const key = getLastParsedKey();
21925
- * ...
21926
- * }
21927
- * ```
21928
- *
21929
- * @param text `className` to parse
21930
- * @param index where the parsing should resume.
21931
- * @returns index where the next invocation of `parseClassNameNext` should resume.
21932
- */
21933
- function parseClassNameNext(text, index) {
21934
- const end = parserState.textEnd;
21935
- if (end === index) {
21936
- return -1;
21937
- }
21938
- index = parserState.keyEnd = consumeClassToken(text, (parserState.key = index), end);
21939
- return consumeWhitespace(text, index, end);
21940
- }
21941
- /**
21942
- * Initializes `cssText` string for parsing and parses the first key/values.
21943
- *
21944
- * This function is intended to be used in this format:
21945
- * ```ts
21946
- * for (let i = parseStyle(text); i >= 0; i = parseStyleNext(text, i))) {
21947
- * const key = getLastParsedKey();
21948
- * const value = getLastParsedValue();
21949
- * ...
21950
- * }
21951
- * ```
21952
- * @param text `cssText` to parse
21953
- * @returns index where the next invocation of `parseStyleNext` should resume.
21954
- */
21955
- function parseStyle(text) {
21956
- resetParserState(text);
21957
- return parseStyleNext(text, consumeWhitespace(text, 0, parserState.textEnd));
21958
- }
21959
- /**
21960
- * Parses the next `cssText` key/values.
21961
- *
21962
- * This function is intended to be used in this format:
21963
- * ```ts
21964
- * for (let i = parseStyle(text); i >= 0; i = parseStyleNext(text, i))) {
21965
- * const key = getLastParsedKey();
21966
- * const value = getLastParsedValue();
21967
- * ...
21968
- * }
21969
- *
21970
- * @param text `cssText` to parse
21971
- * @param index where the parsing should resume.
21972
- * @returns index where the next invocation of `parseStyleNext` should resume.
21973
- */
21974
- function parseStyleNext(text, startIndex) {
21975
- const end = parserState.textEnd;
21976
- let index = (parserState.key = consumeWhitespace(text, startIndex, end));
21977
- if (end === index) {
21978
- // we reached an end so just quit
21979
- return -1;
21980
- }
21981
- index = parserState.keyEnd = consumeStyleKey(text, index, end);
21982
- index = consumeSeparator(text, index, end, 58 /* CharCode.COLON */);
21983
- index = parserState.value = consumeWhitespace(text, index, end);
21984
- index = parserState.valueEnd = consumeStyleValue(text, index, end);
21985
- return consumeSeparator(text, index, end, 59 /* CharCode.SEMI_COLON */);
21986
- }
21987
- /**
21988
- * Reset the global state of the styling parser.
21989
- * @param text The styling text to parse.
21990
- */
21991
- function resetParserState(text) {
21992
- parserState.key = 0;
21993
- parserState.keyEnd = 0;
21994
- parserState.value = 0;
21995
- parserState.valueEnd = 0;
21996
- parserState.textEnd = text.length;
21997
- }
21998
- /**
21999
- * Returns index of next non-whitespace character.
22000
- *
22001
- * @param text Text to scan
22002
- * @param startIndex Starting index of character where the scan should start.
22003
- * @param endIndex Ending index of character where the scan should end.
22004
- * @returns Index of next non-whitespace character (May be the same as `start` if no whitespace at
22005
- * that location.)
22006
- */
22007
- function consumeWhitespace(text, startIndex, endIndex) {
22008
- while (startIndex < endIndex && text.charCodeAt(startIndex) <= 32 /* CharCode.SPACE */) {
22009
- startIndex++;
22010
- }
22011
- return startIndex;
22012
- }
22013
- /**
22014
- * Returns index of last char in class token.
22015
- *
22016
- * @param text Text to scan
22017
- * @param startIndex Starting index of character where the scan should start.
22018
- * @param endIndex Ending index of character where the scan should end.
22019
- * @returns Index after last char in class token.
22020
- */
22021
- function consumeClassToken(text, startIndex, endIndex) {
22022
- while (startIndex < endIndex && text.charCodeAt(startIndex) > 32 /* CharCode.SPACE */) {
22023
- startIndex++;
22024
- }
22025
- return startIndex;
22026
- }
22027
- /**
22028
- * Consumes all of the characters belonging to style key and token.
22029
- *
22030
- * @param text Text to scan
22031
- * @param startIndex Starting index of character where the scan should start.
22032
- * @param endIndex Ending index of character where the scan should end.
22033
- * @returns Index after last style key character.
22034
- */
22035
- function consumeStyleKey(text, startIndex, endIndex) {
22036
- let ch;
22037
- while (startIndex < endIndex &&
22038
- ((ch = text.charCodeAt(startIndex)) === 45 /* CharCode.DASH */ ||
22039
- ch === 95 /* CharCode.UNDERSCORE */ ||
22040
- ((ch & -33 /* CharCode.UPPER_CASE */) >= 65 /* CharCode.A */ && (ch & -33 /* CharCode.UPPER_CASE */) <= 90 /* CharCode.Z */) ||
22041
- (ch >= 48 /* CharCode.ZERO */ && ch <= 57 /* CharCode.NINE */))) {
22042
- startIndex++;
22043
- }
22044
- return startIndex;
22045
- }
22046
- /**
22047
- * Consumes all whitespace and the separator `:` after the style key.
22048
- *
22049
- * @param text Text to scan
22050
- * @param startIndex Starting index of character where the scan should start.
22051
- * @param endIndex Ending index of character where the scan should end.
22052
- * @returns Index after separator and surrounding whitespace.
22053
- */
22054
- function consumeSeparator(text, startIndex, endIndex, separator) {
22055
- startIndex = consumeWhitespace(text, startIndex, endIndex);
22056
- if (startIndex < endIndex) {
22057
- if (ngDevMode && text.charCodeAt(startIndex) !== separator) {
22058
- malformedStyleError(text, String.fromCharCode(separator), startIndex);
22059
- }
22060
- startIndex++;
22061
- }
22062
- return startIndex;
22063
- }
22064
- /**
22065
- * Consumes style value honoring `url()` and `""` text.
22066
- *
22067
- * @param text Text to scan
22068
- * @param startIndex Starting index of character where the scan should start.
22069
- * @param endIndex Ending index of character where the scan should end.
22070
- * @returns Index after last style value character.
22071
- */
22072
- function consumeStyleValue(text, startIndex, endIndex) {
22073
- let ch1 = -1; // 1st previous character
22074
- let ch2 = -1; // 2nd previous character
22075
- let ch3 = -1; // 3rd previous character
22076
- let i = startIndex;
22077
- let lastChIndex = i;
22078
- while (i < endIndex) {
22079
- const ch = text.charCodeAt(i++);
22080
- if (ch === 59 /* CharCode.SEMI_COLON */) {
22081
- return lastChIndex;
22082
- }
22083
- else if (ch === 34 /* CharCode.DOUBLE_QUOTE */ || ch === 39 /* CharCode.SINGLE_QUOTE */) {
22084
- lastChIndex = i = consumeQuotedText(text, ch, i, endIndex);
22085
- }
22086
- else if (startIndex === i - 4 && // We have seen only 4 characters so far "URL(" (Ignore "foo_URL()")
22087
- ch3 === 85 /* CharCode.U */ &&
22088
- ch2 === 82 /* CharCode.R */ &&
22089
- ch1 === 76 /* CharCode.L */ &&
22090
- ch === 40 /* CharCode.OPEN_PAREN */) {
22091
- lastChIndex = i = consumeQuotedText(text, 41 /* CharCode.CLOSE_PAREN */, i, endIndex);
22092
- }
22093
- else if (ch > 32 /* CharCode.SPACE */) {
22094
- // if we have a non-whitespace character then capture its location
22095
- lastChIndex = i;
22096
- }
22097
- ch3 = ch2;
22098
- ch2 = ch1;
22099
- ch1 = ch & -33 /* CharCode.UPPER_CASE */;
22100
- }
22101
- return lastChIndex;
22102
- }
22103
- /**
22104
- * Consumes all of the quoted characters.
22105
- *
22106
- * @param text Text to scan
22107
- * @param quoteCharCode CharCode of either `"` or `'` quote or `)` for `url(...)`.
22108
- * @param startIndex Starting index of character where the scan should start.
22109
- * @param endIndex Ending index of character where the scan should end.
22110
- * @returns Index after quoted characters.
22111
- */
22112
- function consumeQuotedText(text, quoteCharCode, startIndex, endIndex) {
22113
- let ch1 = -1; // 1st previous character
22114
- let index = startIndex;
22115
- while (index < endIndex) {
22116
- const ch = text.charCodeAt(index++);
22117
- if (ch == quoteCharCode && ch1 !== 92 /* CharCode.BACK_SLASH */) {
22118
- return index;
22119
- }
22120
- if (ch == 92 /* CharCode.BACK_SLASH */ && ch1 === 92 /* CharCode.BACK_SLASH */) {
22121
- // two back slashes cancel each other out. For example `"\\"` should properly end the
22122
- // quotation. (It should not assume that the last `"` is escaped.)
22123
- ch1 = 0;
22124
- }
22125
- else {
22126
- ch1 = ch;
22127
- }
22128
- }
22129
- throw ngDevMode
22130
- ? malformedStyleError(text, String.fromCharCode(quoteCharCode), endIndex)
22131
- : new Error();
22132
- }
22133
- function malformedStyleError(text, expecting, index) {
22134
- ngDevMode && assertEqual(typeof text === 'string', true, 'String expected here');
22135
- throw throwError(`Malformed style at location ${index} in string '` +
22136
- text.substring(0, index) +
22137
- '[>>' +
22138
- text.substring(index, index + 1) +
22139
- '<<]' +
22140
- text.slice(index + 1) +
22141
- `'. Expecting '${expecting}'.`);
22142
- }
22143
-
22144
- /**
22145
- * Update a property on a selected element.
22146
- *
22147
- * Operates on the element selected by index via the {@link select} instruction.
22148
- *
22149
- * If the property name also exists as an input property on one of the element's directives,
22150
- * the component property will be set instead of the element property. This check must
22151
- * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled
22152
- *
22153
- * @param propName Name of property. Because it is going to DOM, this is not subject to
22154
- * renaming as part of minification.
22155
- * @param value New value to write.
22156
- * @param sanitizer An optional function used to sanitize the value.
22157
- * @returns This function returns itself so that it may be chained
22158
- * (e.g. `property('name', ctx.name)('title', ctx.title)`)
22159
- *
22160
- * @codeGenApi
22161
- */
22162
- function ɵɵproperty(propName, value, sanitizer) {
22163
- const lView = getLView();
22164
- const bindingIndex = nextBindingIndex();
22165
- if (bindingUpdated(lView, bindingIndex, value)) {
22166
- const tView = getTView();
22167
- const tNode = getSelectedTNode();
22168
- setPropertyAndInputs(tNode, lView, propName, value, lView[RENDERER], sanitizer);
22169
- ngDevMode && storePropertyBindingMetadata(tView.data, tNode, propName, bindingIndex);
22170
- }
22171
- return ɵɵproperty;
22172
- }
22173
- /**
22174
- * Given `<div style="..." my-dir>` and `MyDir` with `@Input('style')` we need to write to
22175
- * directive input.
22176
- */
22177
- function setDirectiveInputsWhichShadowsStyling(tView, tNode, lView, value, isClassBased) {
22178
- // We support both 'class' and `className` hence the fallback.
22179
- setAllInputsForProperty(tNode, tView, lView, isClassBased ? 'class' : 'style', value);
22180
- }
22181
-
22182
- /**
22183
- * Update a style binding on an element with the provided value.
22184
- *
22185
- * If the style value is falsy then it will be removed from the element
22186
- * (or assigned a different value depending if there are any styles placed
22187
- * on the element with `styleMap` or any static styles that are
22188
- * present from when the element was created with `styling`).
22189
- *
22190
- * Note that the styling element is updated as part of `stylingApply`.
22191
- *
22192
- * @param prop A valid CSS property.
22193
- * @param value New value to write (`null` or an empty string to remove).
22194
- * @param suffix Optional suffix. Used with scalar values to add unit such as `px`.
22195
- *
22196
- * Note that this will apply the provided style value to the host element if this function is called
22197
- * within a host binding function.
22198
- *
22199
- * @codeGenApi
22200
- */
22201
- function ɵɵstyleProp(prop, value, suffix) {
22202
- checkStylingProperty(prop, value, suffix, false);
22203
- return ɵɵstyleProp;
22204
- }
22205
- /**
22206
- * Update a class binding on an element with the provided value.
22207
- *
22208
- * This instruction is meant to handle the `[class.foo]="exp"` case and,
22209
- * therefore, the class binding itself must already be allocated using
22210
- * `styling` within the creation block.
22211
- *
22212
- * @param prop A valid CSS class (only one).
22213
- * @param value A true/false value which will turn the class on or off.
22214
- *
22215
- * Note that this will apply the provided class value to the host element if this function
22216
- * is called within a host binding function.
22217
- *
22218
- * @codeGenApi
22219
- */
22220
- function ɵɵclassProp(className, value) {
22221
- checkStylingProperty(className, value, null, true);
22222
- return ɵɵclassProp;
22223
- }
22224
- /**
22225
- * Update style bindings using an object literal on an element.
22226
- *
22227
- * This instruction is meant to apply styling via the `[style]="exp"` template bindings.
22228
- * When styles are applied to the element they will then be updated with respect to
22229
- * any styles/classes set via `styleProp`. If any styles are set to falsy
22230
- * then they will be removed from the element.
22231
- *
22232
- * Note that the styling instruction will not be applied until `stylingApply` is called.
22233
- *
22234
- * @param styles A key/value style map of the styles that will be applied to the given element.
22235
- * Any missing styles (that have already been applied to the element beforehand) will be
22236
- * removed (unset) from the element's styling.
22237
- *
22238
- * Note that this will apply the provided styleMap value to the host element if this function
22239
- * is called within a host binding.
22240
- *
22241
- * @codeGenApi
22242
- */
22243
- function ɵɵstyleMap(styles) {
22244
- checkStylingMap(styleKeyValueArraySet, styleStringParser, styles, false);
22245
- }
22246
- /**
22247
- * Parse text as style and add values to KeyValueArray.
22248
- *
22249
- * This code is pulled out to a separate function so that it can be tree shaken away if it is not
22250
- * needed. It is only referenced from `ɵɵstyleMap`.
22251
- *
22252
- * @param keyValueArray KeyValueArray to add parsed values to.
22253
- * @param text text to parse.
22254
- */
22255
- function styleStringParser(keyValueArray, text) {
22256
- for (let i = parseStyle(text); i >= 0; i = parseStyleNext(text, i)) {
22257
- styleKeyValueArraySet(keyValueArray, getLastParsedKey(text), getLastParsedValue(text));
22258
- }
22259
- }
22260
- /**
22261
- * Update class bindings using an object literal or class-string on an element.
22262
- *
22263
- * This instruction is meant to apply styling via the `[class]="exp"` template bindings.
22264
- * When classes are applied to the element they will then be updated with
22265
- * respect to any styles/classes set via `classProp`. If any
22266
- * classes are set to falsy then they will be removed from the element.
22267
- *
22268
- * Note that the styling instruction will not be applied until `stylingApply` is called.
22269
- * Note that this will the provided classMap value to the host element if this function is called
22270
- * within a host binding.
22271
- *
22272
- * @param classes A key/value map or string of CSS classes that will be added to the
22273
- * given element. Any missing classes (that have already been applied to the element
22274
- * beforehand) will be removed (unset) from the element's list of CSS classes.
22275
- *
22276
- * @codeGenApi
22277
- */
22278
- function ɵɵclassMap(classes) {
22279
- checkStylingMap(classKeyValueArraySet, classStringParser, classes, true);
22280
- }
22281
- /**
22282
- * Parse text as class and add values to KeyValueArray.
22283
- *
22284
- * This code is pulled out to a separate function so that it can be tree shaken away if it is not
22285
- * needed. It is only referenced from `ɵɵclassMap`.
22286
- *
22287
- * @param keyValueArray KeyValueArray to add parsed values to.
22288
- * @param text text to parse.
22289
- */
22290
- function classStringParser(keyValueArray, text) {
22291
- for (let i = parseClassName(text); i >= 0; i = parseClassNameNext(text, i)) {
22292
- keyValueArraySet(keyValueArray, getLastParsedKey(text), true);
22293
- }
22294
- }
22295
- /**
22296
- * Common code between `ɵɵclassProp` and `ɵɵstyleProp`.
22297
- *
22298
- * @param prop property name.
22299
- * @param value binding value.
22300
- * @param suffix suffix for the property (e.g. `em` or `px`)
22301
- * @param isClassBased `true` if `class` change (`false` if `style`)
22302
- */
22303
- function checkStylingProperty(prop, value, suffix, isClassBased) {
22304
- const lView = getLView();
22305
- const tView = getTView();
22306
- // Styling instructions use 2 slots per binding.
22307
- // 1. one for the value / TStylingKey
22308
- // 2. one for the intermittent-value / TStylingRange
22309
- const bindingIndex = incrementBindingIndex(2);
22310
- if (tView.firstUpdatePass) {
22311
- stylingFirstUpdatePass(tView, prop, bindingIndex, isClassBased);
22312
- }
22313
- if (value !== NO_CHANGE && bindingUpdated(lView, bindingIndex, value)) {
22314
- const tNode = tView.data[getSelectedIndex()];
22315
- updateStyling(tView, tNode, lView, lView[RENDERER], prop, (lView[bindingIndex + 1] = normalizeSuffix(value, suffix)), isClassBased, bindingIndex);
22316
- }
22317
- }
22318
- /**
22319
- * Common code between `ɵɵclassMap` and `ɵɵstyleMap`.
22320
- *
22321
- * @param keyValueArraySet (See `keyValueArraySet` in "util/array_utils") Gets passed in as a
22322
- * function so that `style` can be processed. This is done for tree shaking purposes.
22323
- * @param stringParser Parser used to parse `value` if `string`. (Passed in as `style` and `class`
22324
- * have different parsers.)
22325
- * @param value bound value from application
22326
- * @param isClassBased `true` if `class` change (`false` if `style`)
22327
- */
22328
- function checkStylingMap(keyValueArraySet, stringParser, value, isClassBased) {
22329
- const tView = getTView();
22330
- const bindingIndex = incrementBindingIndex(2);
22331
- if (tView.firstUpdatePass) {
22332
- stylingFirstUpdatePass(tView, null, bindingIndex, isClassBased);
22333
- }
22334
- const lView = getLView();
22335
- if (value !== NO_CHANGE && bindingUpdated(lView, bindingIndex, value)) {
22336
- // `getSelectedIndex()` should be here (rather than in instruction) so that it is guarded by the
22337
- // if so as not to read unnecessarily.
22338
- const tNode = tView.data[getSelectedIndex()];
22339
- if (hasStylingInputShadow(tNode, isClassBased) && !isInHostBindings(tView, bindingIndex)) {
22340
- if (ngDevMode) {
22341
- // verify that if we are shadowing then `TData` is appropriately marked so that we skip
22342
- // processing this binding in styling resolution.
22343
- const tStylingKey = tView.data[bindingIndex];
22344
- assertEqual(Array.isArray(tStylingKey) ? tStylingKey[1] : tStylingKey, false, "Styling linked list shadow input should be marked as 'false'");
22345
- }
22346
- // VE does not concatenate the static portion like we are doing here.
22347
- // Instead VE just ignores the static completely if dynamic binding is present.
22348
- // Because of locality we have already set the static portion because we don't know if there
22349
- // is a dynamic portion until later. If we would ignore the static portion it would look like
22350
- // the binding has removed it. This would confuse `[ngStyle]`/`[ngClass]` to do the wrong
22351
- // thing as it would think that the static portion was removed. For this reason we
22352
- // concatenate it so that `[ngStyle]`/`[ngClass]` can continue to work on changed.
22353
- let staticPrefix = isClassBased ? tNode.classesWithoutHost : tNode.stylesWithoutHost;
22354
- ngDevMode &&
22355
- isClassBased === false &&
22356
- staticPrefix !== null &&
22357
- assertEqual(staticPrefix.endsWith(';'), true, "Expecting static portion to end with ';'");
22358
- if (staticPrefix !== null) {
22359
- // We want to make sure that falsy values of `value` become empty strings.
22360
- value = concatStringsWithSpace(staticPrefix, value ? value : '');
22361
- }
22362
- // Given `<div [style] my-dir>` such that `my-dir` has `@Input('style')`.
22363
- // This takes over the `[style]` binding. (Same for `[class]`)
22364
- setDirectiveInputsWhichShadowsStyling(tView, tNode, lView, value, isClassBased);
22365
- }
22366
- else {
22367
- updateStylingMap(tView, tNode, lView, lView[RENDERER], lView[bindingIndex + 1], (lView[bindingIndex + 1] = toStylingKeyValueArray(keyValueArraySet, stringParser, value)), isClassBased, bindingIndex);
22368
- }
22369
- }
22370
- }
22371
- /**
22372
- * Determines when the binding is in `hostBindings` section
22373
- *
22374
- * @param tView Current `TView`
22375
- * @param bindingIndex index of binding which we would like if it is in `hostBindings`
22376
- */
22377
- function isInHostBindings(tView, bindingIndex) {
22378
- // All host bindings are placed after the expando section.
22379
- return bindingIndex >= tView.expandoStartIndex;
22380
- }
22381
- /**
22382
- * Collects the necessary information to insert the binding into a linked list of style bindings
22383
- * using `insertTStylingBinding`.
22384
- *
22385
- * @param tView `TView` where the binding linked list will be stored.
22386
- * @param tStylingKey Property/key of the binding.
22387
- * @param bindingIndex Index of binding associated with the `prop`
22388
- * @param isClassBased `true` if `class` change (`false` if `style`)
22389
- */
22390
- function stylingFirstUpdatePass(tView, tStylingKey, bindingIndex, isClassBased) {
22391
- ngDevMode && assertFirstUpdatePass(tView);
22392
- const tData = tView.data;
22393
- if (tData[bindingIndex + 1] === null) {
22394
- // The above check is necessary because we don't clear first update pass until first successful
22395
- // (no exception) template execution. This prevents the styling instruction from double adding
22396
- // itself to the list.
22397
- // `getSelectedIndex()` should be here (rather than in instruction) so that it is guarded by the
22398
- // if so as not to read unnecessarily.
22399
- const tNode = tData[getSelectedIndex()];
22400
- ngDevMode && assertDefined(tNode, 'TNode expected');
22401
- const isHostBindings = isInHostBindings(tView, bindingIndex);
22402
- if (hasStylingInputShadow(tNode, isClassBased) && tStylingKey === null && !isHostBindings) {
22403
- // `tStylingKey === null` implies that we are either `[style]` or `[class]` binding.
22404
- // If there is a directive which uses `@Input('style')` or `@Input('class')` than
22405
- // we need to neutralize this binding since that directive is shadowing it.
22406
- // We turn this into a noop by setting the key to `false`
22407
- tStylingKey = false;
22408
- }
22409
- tStylingKey = wrapInStaticStylingKey(tData, tNode, tStylingKey, isClassBased);
22410
- insertTStylingBinding(tData, tNode, tStylingKey, bindingIndex, isHostBindings, isClassBased);
22411
- }
22412
- }
22413
- /**
22414
- * Adds static styling information to the binding if applicable.
22415
- *
22416
- * The linked list of styles not only stores the list and keys, but also stores static styling
22417
- * information on some of the keys. This function determines if the key should contain the styling
22418
- * information and computes it.
22419
- *
22420
- * See `TStylingStatic` for more details.
22421
- *
22422
- * @param tData `TData` where the linked list is stored.
22423
- * @param tNode `TNode` for which the styling is being computed.
22424
- * @param stylingKey `TStylingKeyPrimitive` which may need to be wrapped into `TStylingKey`
22425
- * @param isClassBased `true` if `class` (`false` if `style`)
22426
- */
22427
- function wrapInStaticStylingKey(tData, tNode, stylingKey, isClassBased) {
22428
- const hostDirectiveDef = getCurrentDirectiveDef(tData);
22429
- let residual = isClassBased ? tNode.residualClasses : tNode.residualStyles;
22430
- if (hostDirectiveDef === null) {
22431
- // We are in template node.
22432
- // If template node already had styling instruction then it has already collected the static
22433
- // styling and there is no need to collect them again. We know that we are the first styling
22434
- // instruction because the `TNode.*Bindings` points to 0 (nothing has been inserted yet).
22435
- const isFirstStylingInstructionInTemplate = (isClassBased ? tNode.classBindings : tNode.styleBindings) === 0;
22436
- if (isFirstStylingInstructionInTemplate) {
22437
- // It would be nice to be able to get the statics from `mergeAttrs`, however, at this point
22438
- // they are already merged and it would not be possible to figure which property belongs where
22439
- // in the priority.
22440
- stylingKey = collectStylingFromDirectives(null, tData, tNode, stylingKey, isClassBased);
22441
- stylingKey = collectStylingFromTAttrs(stylingKey, tNode.attrs, isClassBased);
22442
- // We know that if we have styling binding in template we can't have residual.
22443
- residual = null;
22444
- }
22445
- }
22446
- else {
22447
- // We are in host binding node and there was no binding instruction in template node.
22448
- // This means that we need to compute the residual.
22449
- const directiveStylingLast = tNode.directiveStylingLast;
22450
- const isFirstStylingInstructionInHostBinding = directiveStylingLast === -1 || tData[directiveStylingLast] !== hostDirectiveDef;
22451
- if (isFirstStylingInstructionInHostBinding) {
22452
- stylingKey = collectStylingFromDirectives(hostDirectiveDef, tData, tNode, stylingKey, isClassBased);
22453
- if (residual === null) {
22454
- // - If `null` than either:
22455
- // - Template styling instruction already ran and it has consumed the static
22456
- // styling into its `TStylingKey` and so there is no need to update residual. Instead
22457
- // we need to update the `TStylingKey` associated with the first template node
22458
- // instruction. OR
22459
- // - Some other styling instruction ran and determined that there are no residuals
22460
- let templateStylingKey = getTemplateHeadTStylingKey(tData, tNode, isClassBased);
22461
- if (templateStylingKey !== undefined && Array.isArray(templateStylingKey)) {
22462
- // Only recompute if `templateStylingKey` had static values. (If no static value found
22463
- // then there is nothing to do since this operation can only produce less static keys, not
22464
- // more.)
22465
- templateStylingKey = collectStylingFromDirectives(null, tData, tNode, templateStylingKey[1] /* unwrap previous statics */, isClassBased);
22466
- templateStylingKey = collectStylingFromTAttrs(templateStylingKey, tNode.attrs, isClassBased);
22467
- setTemplateHeadTStylingKey(tData, tNode, isClassBased, templateStylingKey);
22468
- }
22469
- }
22470
- else {
22471
- // We only need to recompute residual if it is not `null`.
22472
- // - If existing residual (implies there was no template styling). This means that some of
22473
- // the statics may have moved from the residual to the `stylingKey` and so we have to
22474
- // recompute.
22475
- // - If `undefined` this is the first time we are running.
22476
- residual = collectResidual(tData, tNode, isClassBased);
22477
- }
22478
- }
22479
- }
22480
- if (residual !== undefined) {
22481
- isClassBased ? (tNode.residualClasses = residual) : (tNode.residualStyles = residual);
22482
- }
22483
- return stylingKey;
22484
- }
22485
- /**
22486
- * Retrieve the `TStylingKey` for the template styling instruction.
22487
- *
22488
- * This is needed since `hostBinding` styling instructions are inserted after the template
22489
- * instruction. While the template instruction needs to update the residual in `TNode` the
22490
- * `hostBinding` instructions need to update the `TStylingKey` of the template instruction because
22491
- * the template instruction is downstream from the `hostBindings` instructions.
22492
- *
22493
- * @param tData `TData` where the linked list is stored.
22494
- * @param tNode `TNode` for which the styling is being computed.
22495
- * @param isClassBased `true` if `class` (`false` if `style`)
22496
- * @return `TStylingKey` if found or `undefined` if not found.
22497
- */
22498
- function getTemplateHeadTStylingKey(tData, tNode, isClassBased) {
22499
- const bindings = isClassBased ? tNode.classBindings : tNode.styleBindings;
22500
- if (getTStylingRangeNext(bindings) === 0) {
22501
- // There does not seem to be a styling instruction in the `template`.
22502
- return undefined;
22503
- }
22504
- return tData[getTStylingRangePrev(bindings)];
22505
- }
22506
- /**
22507
- * Update the `TStylingKey` of the first template instruction in `TNode`.
22508
- *
22509
- * Logically `hostBindings` styling instructions are of lower priority than that of the template.
22510
- * However, they execute after the template styling instructions. This means that they get inserted
22511
- * in front of the template styling instructions.
22512
- *
22513
- * If we have a template styling instruction and a new `hostBindings` styling instruction is
22514
- * executed it means that it may need to steal static fields from the template instruction. This
22515
- * method allows us to update the first template instruction `TStylingKey` with a new value.
22516
- *
22517
- * Assume:
22518
- * ```angular-ts
22519
- * <div my-dir style="color: red" [style.color]="tmplExp"></div>
22520
- *
22521
- * @Directive({
22522
- * host: {
22523
- * 'style': 'width: 100px',
22524
- * '[style.color]': 'dirExp',
22525
- * }
22526
- * })
22527
- * class MyDir {}
22528
- * ```
22529
- *
22530
- * when `[style.color]="tmplExp"` executes it creates this data structure.
22531
- * ```ts
22532
- * ['', 'color', 'color', 'red', 'width', '100px'],
22533
- * ```
22534
- *
22535
- * The reason for this is that the template instruction does not know if there are styling
22536
- * instructions and must assume that there are none and must collect all of the static styling.
22537
- * (both
22538
- * `color' and 'width`)
22539
- *
22540
- * When `'[style.color]': 'dirExp',` executes we need to insert a new data into the linked list.
22541
- * ```ts
22542
- * ['', 'color', 'width', '100px'], // newly inserted
22543
- * ['', 'color', 'color', 'red', 'width', '100px'], // this is wrong
22544
- * ```
22545
- *
22546
- * Notice that the template statics is now wrong as it incorrectly contains `width` so we need to
22547
- * update it like so:
22548
- * ```ts
22549
- * ['', 'color', 'width', '100px'],
22550
- * ['', 'color', 'color', 'red'], // UPDATE
22551
- * ```
22552
- *
22553
- * @param tData `TData` where the linked list is stored.
22554
- * @param tNode `TNode` for which the styling is being computed.
22555
- * @param isClassBased `true` if `class` (`false` if `style`)
22556
- * @param tStylingKey New `TStylingKey` which is replacing the old one.
22557
- */
22558
- function setTemplateHeadTStylingKey(tData, tNode, isClassBased, tStylingKey) {
22559
- const bindings = isClassBased ? tNode.classBindings : tNode.styleBindings;
22560
- ngDevMode &&
22561
- assertNotEqual(getTStylingRangeNext(bindings), 0, 'Expecting to have at least one template styling binding.');
22562
- tData[getTStylingRangePrev(bindings)] = tStylingKey;
22563
- }
22564
- /**
22565
- * Collect all static values after the current `TNode.directiveStylingLast` index.
22566
- *
22567
- * Collect the remaining styling information which has not yet been collected by an existing
22568
- * styling instruction.
22569
- *
22570
- * @param tData `TData` where the `DirectiveDefs` are stored.
22571
- * @param tNode `TNode` which contains the directive range.
22572
- * @param isClassBased `true` if `class` (`false` if `style`)
22573
- */
22574
- function collectResidual(tData, tNode, isClassBased) {
22575
- let residual = undefined;
22576
- const directiveEnd = tNode.directiveEnd;
22577
- ngDevMode &&
22578
- assertNotEqual(tNode.directiveStylingLast, -1, 'By the time this function gets called at least one hostBindings-node styling instruction must have executed.');
22579
- // We add `1 + tNode.directiveStart` because we need to skip the current directive (as we are
22580
- // collecting things after the last `hostBindings` directive which had a styling instruction.)
22581
- for (let i = 1 + tNode.directiveStylingLast; i < directiveEnd; i++) {
22582
- const attrs = tData[i].hostAttrs;
22583
- residual = collectStylingFromTAttrs(residual, attrs, isClassBased);
22584
- }
22585
- return collectStylingFromTAttrs(residual, tNode.attrs, isClassBased);
22586
- }
22587
- /**
22588
- * Collect the static styling information with lower priority than `hostDirectiveDef`.
22589
- *
22590
- * (This is opposite of residual styling.)
22591
- *
22592
- * @param hostDirectiveDef `DirectiveDef` for which we want to collect lower priority static
22593
- * styling. (Or `null` if template styling)
22594
- * @param tData `TData` where the linked list is stored.
22595
- * @param tNode `TNode` for which the styling is being computed.
22596
- * @param stylingKey Existing `TStylingKey` to update or wrap.
22597
- * @param isClassBased `true` if `class` (`false` if `style`)
22598
- */
22599
- function collectStylingFromDirectives(hostDirectiveDef, tData, tNode, stylingKey, isClassBased) {
22600
- // We need to loop because there can be directives which have `hostAttrs` but don't have
22601
- // `hostBindings` so this loop catches up to the current directive..
22602
- let currentDirective = null;
22603
- const directiveEnd = tNode.directiveEnd;
22604
- let directiveStylingLast = tNode.directiveStylingLast;
22605
- if (directiveStylingLast === -1) {
22606
- directiveStylingLast = tNode.directiveStart;
22607
- }
22608
- else {
22609
- directiveStylingLast++;
22610
- }
22611
- while (directiveStylingLast < directiveEnd) {
22612
- currentDirective = tData[directiveStylingLast];
22613
- ngDevMode && assertDefined(currentDirective, 'expected to be defined');
22614
- stylingKey = collectStylingFromTAttrs(stylingKey, currentDirective.hostAttrs, isClassBased);
22615
- if (currentDirective === hostDirectiveDef)
22616
- break;
22617
- directiveStylingLast++;
22618
- }
22619
- if (hostDirectiveDef !== null) {
22620
- // we only advance the styling cursor if we are collecting data from host bindings.
22621
- // Template executes before host bindings and so if we would update the index,
22622
- // host bindings would not get their statics.
22623
- tNode.directiveStylingLast = directiveStylingLast;
22624
- }
22625
- return stylingKey;
22626
- }
22627
- /**
22628
- * Convert `TAttrs` into `TStylingStatic`.
22629
- *
22630
- * @param stylingKey existing `TStylingKey` to update or wrap.
22631
- * @param attrs `TAttributes` to process.
22632
- * @param isClassBased `true` if `class` (`false` if `style`)
22633
- */
22634
- function collectStylingFromTAttrs(stylingKey, attrs, isClassBased) {
22635
- const desiredMarker = isClassBased ? 1 /* AttributeMarker.Classes */ : 2 /* AttributeMarker.Styles */;
22636
- let currentMarker = -1 /* AttributeMarker.ImplicitAttributes */;
22637
- if (attrs !== null) {
22638
- for (let i = 0; i < attrs.length; i++) {
22639
- const item = attrs[i];
22640
- if (typeof item === 'number') {
22641
- currentMarker = item;
22642
- }
22643
- else {
22644
- if (currentMarker === desiredMarker) {
22645
- if (!Array.isArray(stylingKey)) {
22646
- stylingKey = stylingKey === undefined ? [] : ['', stylingKey];
22647
- }
22648
- keyValueArraySet(stylingKey, item, isClassBased ? true : attrs[++i]);
22649
- }
22650
- }
22651
- }
22652
- }
22653
- return stylingKey === undefined ? null : stylingKey;
22654
- }
22655
- /**
22656
- * Convert user input to `KeyValueArray`.
22657
- *
22658
- * This function takes user input which could be `string`, Object literal, or iterable and converts
22659
- * it into a consistent representation. The output of this is `KeyValueArray` (which is an array
22660
- * where
22661
- * even indexes contain keys and odd indexes contain values for those keys).
22662
- *
22663
- * The advantage of converting to `KeyValueArray` is that we can perform diff in an input
22664
- * independent
22665
- * way.
22666
- * (ie we can compare `foo bar` to `['bar', 'baz'] and determine a set of changes which need to be
22667
- * applied)
22668
- *
22669
- * The fact that `KeyValueArray` is sorted is very important because it allows us to compute the
22670
- * difference in linear fashion without the need to allocate any additional data.
22671
- *
22672
- * For example if we kept this as a `Map` we would have to iterate over previous `Map` to determine
22673
- * which values need to be deleted, over the new `Map` to determine additions, and we would have to
22674
- * keep additional `Map` to keep track of duplicates or items which have not yet been visited.
22675
- *
22676
- * @param keyValueArraySet (See `keyValueArraySet` in "util/array_utils") Gets passed in as a
22677
- * function so that `style` can be processed. This is done
22678
- * for tree shaking purposes.
22679
- * @param stringParser The parser is passed in so that it will be tree shakable. See
22680
- * `styleStringParser` and `classStringParser`
22681
- * @param value The value to parse/convert to `KeyValueArray`
22682
- */
22683
- function toStylingKeyValueArray(keyValueArraySet, stringParser, value) {
22684
- if (value == null /*|| value === undefined */ || value === '')
22685
- return EMPTY_ARRAY;
22686
- const styleKeyValueArray = [];
22687
- const unwrappedValue = unwrapSafeValue(value);
22688
- if (Array.isArray(unwrappedValue)) {
22689
- for (let i = 0; i < unwrappedValue.length; i++) {
22690
- keyValueArraySet(styleKeyValueArray, unwrappedValue[i], true);
22691
- }
22692
- }
22693
- else if (typeof unwrappedValue === 'object') {
22694
- for (const key in unwrappedValue) {
22695
- if (unwrappedValue.hasOwnProperty(key)) {
22696
- keyValueArraySet(styleKeyValueArray, key, unwrappedValue[key]);
22697
- }
22698
- }
22699
- }
22700
- else if (typeof unwrappedValue === 'string') {
22701
- stringParser(styleKeyValueArray, unwrappedValue);
22702
- }
22703
- else {
22704
- ngDevMode &&
22705
- throwError('Unsupported styling type: ' + typeof unwrappedValue + ' (' + unwrappedValue + ')');
22706
- }
22707
- return styleKeyValueArray;
22708
- }
22709
- /**
22710
- * Set a `value` for a `key`.
22711
- *
22712
- * See: `keyValueArraySet` for details
22713
- *
22714
- * @param keyValueArray KeyValueArray to add to.
22715
- * @param key Style key to add.
22716
- * @param value The value to set.
22717
- */
22718
- function styleKeyValueArraySet(keyValueArray, key, value) {
22719
- keyValueArraySet(keyValueArray, key, unwrapSafeValue(value));
22720
- }
22721
- /**
22722
- * Class-binding-specific function for setting the `value` for a `key`.
22723
- *
22724
- * See: `keyValueArraySet` for details
22725
- *
22726
- * @param keyValueArray KeyValueArray to add to.
22727
- * @param key Style key to add.
22728
- * @param value The value to set.
22729
- */
22730
- function classKeyValueArraySet(keyValueArray, key, value) {
22731
- // We use `classList.add` to eventually add the CSS classes to the DOM node. Any value passed into
22732
- // `add` is stringified and added to the `class` attribute, e.g. even null, undefined or numbers
22733
- // will be added. Stringify the key here so that our internal data structure matches the value in
22734
- // the DOM. The only exceptions are empty strings and strings that contain spaces for which
22735
- // the browser throws an error. We ignore such values, because the error is somewhat cryptic.
22736
- const stringKey = String(key);
22737
- if (stringKey !== '' && !stringKey.includes(' ')) {
22738
- keyValueArraySet(keyValueArray, stringKey, value);
22739
- }
22740
- }
22741
- /**
22742
- * Update map based styling.
22743
- *
22744
- * Map based styling could be anything which contains more than one binding. For example `string`,
22745
- * or object literal. Dealing with all of these types would complicate the logic so
22746
- * instead this function expects that the complex input is first converted into normalized
22747
- * `KeyValueArray`. The advantage of normalization is that we get the values sorted, which makes it
22748
- * very cheap to compute deltas between the previous and current value.
22749
- *
22750
- * @param tView Associated `TView.data` contains the linked list of binding priorities.
22751
- * @param tNode `TNode` where the binding is located.
22752
- * @param lView `LView` contains the values associated with other styling binding at this `TNode`.
22753
- * @param renderer Renderer to use if any updates.
22754
- * @param oldKeyValueArray Previous value represented as `KeyValueArray`
22755
- * @param newKeyValueArray Current value represented as `KeyValueArray`
22756
- * @param isClassBased `true` if `class` (`false` if `style`)
22757
- * @param bindingIndex Binding index of the binding.
22758
- */
22759
- function updateStylingMap(tView, tNode, lView, renderer, oldKeyValueArray, newKeyValueArray, isClassBased, bindingIndex) {
22760
- if (oldKeyValueArray === NO_CHANGE) {
22761
- // On first execution the oldKeyValueArray is NO_CHANGE => treat it as empty KeyValueArray.
22762
- oldKeyValueArray = EMPTY_ARRAY;
22763
- }
22764
- let oldIndex = 0;
22765
- let newIndex = 0;
22766
- let oldKey = 0 < oldKeyValueArray.length ? oldKeyValueArray[0] : null;
22767
- let newKey = 0 < newKeyValueArray.length ? newKeyValueArray[0] : null;
22768
- while (oldKey !== null || newKey !== null) {
22769
- ngDevMode && assertLessThan(oldIndex, 999, 'Are we stuck in infinite loop?');
22770
- ngDevMode && assertLessThan(newIndex, 999, 'Are we stuck in infinite loop?');
22771
- const oldValue = oldIndex < oldKeyValueArray.length ? oldKeyValueArray[oldIndex + 1] : undefined;
22772
- const newValue = newIndex < newKeyValueArray.length ? newKeyValueArray[newIndex + 1] : undefined;
22773
- let setKey = null;
22774
- let setValue = undefined;
22775
- if (oldKey === newKey) {
22776
- // UPDATE: Keys are equal => new value is overwriting old value.
22777
- oldIndex += 2;
22778
- newIndex += 2;
22779
- if (oldValue !== newValue) {
22780
- setKey = newKey;
22781
- setValue = newValue;
22782
- }
22783
- }
22784
- else if (newKey === null || (oldKey !== null && oldKey < newKey)) {
22785
- // DELETE: oldKey key is missing or we did not find the oldKey in the newValue
22786
- // (because the keyValueArray is sorted and `newKey` is found later alphabetically).
22787
- // `"background" < "color"` so we need to delete `"background"` because it is not found in the
22788
- // new array.
22789
- oldIndex += 2;
22790
- setKey = oldKey;
22791
- }
22792
- else {
22793
- // CREATE: newKey's is earlier alphabetically than oldKey's (or no oldKey) => we have new key.
22794
- // `"color" > "background"` so we need to add `color` because it is in new array but not in
22795
- // old array.
22796
- ngDevMode && assertDefined(newKey, 'Expecting to have a valid key');
22797
- newIndex += 2;
22798
- setKey = newKey;
22799
- setValue = newValue;
22800
- }
22801
- if (setKey !== null) {
22802
- updateStyling(tView, tNode, lView, renderer, setKey, setValue, isClassBased, bindingIndex);
22803
- }
22804
- oldKey = oldIndex < oldKeyValueArray.length ? oldKeyValueArray[oldIndex] : null;
22805
- newKey = newIndex < newKeyValueArray.length ? newKeyValueArray[newIndex] : null;
22806
- }
22807
- }
22808
- /**
22809
- * Update a simple (property name) styling.
22810
- *
22811
- * This function takes `prop` and updates the DOM to that value. The function takes the binding
22812
- * value as well as binding priority into consideration to determine which value should be written
22813
- * to DOM. (For example it may be determined that there is a higher priority overwrite which blocks
22814
- * the DOM write, or if the value goes to `undefined` a lower priority overwrite may be consulted.)
22815
- *
22816
- * @param tView Associated `TView.data` contains the linked list of binding priorities.
22817
- * @param tNode `TNode` where the binding is located.
22818
- * @param lView `LView` contains the values associated with other styling binding at this `TNode`.
22819
- * @param renderer Renderer to use if any updates.
22820
- * @param prop Either style property name or a class name.
22821
- * @param value Either style value for `prop` or `true`/`false` if `prop` is class.
22822
- * @param isClassBased `true` if `class` (`false` if `style`)
22823
- * @param bindingIndex Binding index of the binding.
22824
- */
22825
- function updateStyling(tView, tNode, lView, renderer, prop, value, isClassBased, bindingIndex) {
22826
- if (!(tNode.type & 3 /* TNodeType.AnyRNode */)) {
22827
- // It is possible to have styling on non-elements (such as ng-container).
22828
- // This is rare, but it does happen. In such a case, just ignore the binding.
22829
- return;
22830
- }
22831
- const tData = tView.data;
22832
- const tRange = tData[bindingIndex + 1];
22833
- const higherPriorityValue = getTStylingRangeNextDuplicate(tRange)
22834
- ? findStylingValue(tData, tNode, lView, prop, getTStylingRangeNext(tRange), isClassBased)
22835
- : undefined;
22836
- if (!isStylingValuePresent(higherPriorityValue)) {
22837
- // We don't have a next duplicate, or we did not find a duplicate value.
22838
- if (!isStylingValuePresent(value)) {
22839
- // We should delete current value or restore to lower priority value.
22840
- if (getTStylingRangePrevDuplicate(tRange)) {
22841
- // We have a possible prev duplicate, let's retrieve it.
22842
- value = findStylingValue(tData, null, lView, prop, bindingIndex, isClassBased);
22843
- }
22844
- }
22845
- const rNode = getNativeByIndex(getSelectedIndex(), lView);
22846
- applyStyling(renderer, isClassBased, rNode, prop, value);
22847
- }
22848
- }
22849
- /**
22850
- * Search for styling value with higher priority which is overwriting current value, or a
22851
- * value of lower priority to which we should fall back if the value is `undefined`.
22852
- *
22853
- * When value is being applied at a location, related values need to be consulted.
22854
- * - If there is a higher priority binding, we should be using that one instead.
22855
- * For example `<div [style]="{color:exp1}" [style.color]="exp2">` change to `exp1`
22856
- * requires that we check `exp2` to see if it is set to value other than `undefined`.
22857
- * - If there is a lower priority binding and we are changing to `undefined`
22858
- * For example `<div [style]="{color:exp1}" [style.color]="exp2">` change to `exp2` to
22859
- * `undefined` requires that we check `exp1` (and static values) and use that as new value.
22860
- *
22861
- * NOTE: The styling stores two values.
22862
- * 1. The raw value which came from the application is stored at `index + 0` location. (This value
22863
- * is used for dirty checking).
22864
- * 2. The normalized value is stored at `index + 1`.
22865
- *
22866
- * @param tData `TData` used for traversing the priority.
22867
- * @param tNode `TNode` to use for resolving static styling. Also controls search direction.
22868
- * - `TNode` search next and quit as soon as `isStylingValuePresent(value)` is true.
22869
- * If no value found consult `tNode.residualStyle`/`tNode.residualClass` for default value.
22870
- * - `null` search prev and go all the way to end. Return last value where
22871
- * `isStylingValuePresent(value)` is true.
22872
- * @param lView `LView` used for retrieving the actual values.
22873
- * @param prop Property which we are interested in.
22874
- * @param index Starting index in the linked list of styling bindings where the search should start.
22875
- * @param isClassBased `true` if `class` (`false` if `style`)
22876
- */
22877
- function findStylingValue(tData, tNode, lView, prop, index, isClassBased) {
22878
- // `TNode` to use for resolving static styling. Also controls search direction.
22879
- // - `TNode` search next and quit as soon as `isStylingValuePresent(value)` is true.
22880
- // If no value found consult `tNode.residualStyle`/`tNode.residualClass` for default value.
22881
- // - `null` search prev and go all the way to end. Return last value where
22882
- // `isStylingValuePresent(value)` is true.
22883
- const isPrevDirection = tNode === null;
22884
- let value = undefined;
22885
- while (index > 0) {
22886
- const rawKey = tData[index];
22887
- const containsStatics = Array.isArray(rawKey);
22888
- // Unwrap the key if we contain static values.
22889
- const key = containsStatics ? rawKey[1] : rawKey;
22890
- const isStylingMap = key === null;
22891
- let valueAtLViewIndex = lView[index + 1];
22892
- if (valueAtLViewIndex === NO_CHANGE) {
22893
- // In firstUpdatePass the styling instructions create a linked list of styling.
22894
- // On subsequent passes it is possible for a styling instruction to try to read a binding
22895
- // which
22896
- // has not yet executed. In that case we will find `NO_CHANGE` and we should assume that
22897
- // we have `undefined` (or empty array in case of styling-map instruction) instead. This
22898
- // allows the resolution to apply the value (which may later be overwritten when the
22899
- // binding actually executes.)
22900
- valueAtLViewIndex = isStylingMap ? EMPTY_ARRAY : undefined;
22901
- }
22902
- let currentValue = isStylingMap
22903
- ? keyValueArrayGet(valueAtLViewIndex, prop)
22904
- : key === prop
22905
- ? valueAtLViewIndex
22906
- : undefined;
22907
- if (containsStatics && !isStylingValuePresent(currentValue)) {
22908
- currentValue = keyValueArrayGet(rawKey, prop);
22909
- }
22910
- if (isStylingValuePresent(currentValue)) {
22911
- value = currentValue;
22912
- if (isPrevDirection) {
22913
- return value;
22914
- }
22915
- }
22916
- const tRange = tData[index + 1];
22917
- index = isPrevDirection ? getTStylingRangePrev(tRange) : getTStylingRangeNext(tRange);
22918
- }
22919
- if (tNode !== null) {
22920
- // in case where we are going in next direction AND we did not find anything, we need to
22921
- // consult residual styling
22922
- let residual = isClassBased ? tNode.residualClasses : tNode.residualStyles;
22923
- if (residual != null /** OR residual !=== undefined */) {
22924
- value = keyValueArrayGet(residual, prop);
22925
- }
22926
- }
22927
- return value;
22928
- }
22929
- /**
22930
- * Determines if the binding value should be used (or if the value is 'undefined' and hence priority
22931
- * resolution should be used.)
22932
- *
22933
- * @param value Binding style value.
22934
- */
22935
- function isStylingValuePresent(value) {
22936
- // Currently only `undefined` value is considered non-binding. That is `undefined` says I don't
22937
- // have an opinion as to what this binding should be and you should consult other bindings by
22938
- // priority to determine the valid value.
22939
- // This is extracted into a single function so that we have a single place to control this.
22940
- return value !== undefined;
22941
- }
22942
- /**
22943
- * Normalizes and/or adds a suffix to the value.
22944
- *
22945
- * If value is `null`/`undefined` no suffix is added
22946
- * @param value
22947
- * @param suffix
22948
- */
22949
- function normalizeSuffix(value, suffix) {
22950
- if (value == null || value === '') ;
22951
- else if (typeof suffix === 'string') {
22952
- value = value + suffix;
22953
- }
22954
- else if (typeof value === 'object') {
22955
- value = stringify(unwrapSafeValue(value));
22956
- }
22957
- return value;
22958
- }
22959
- /**
22960
- * Tests if the `TNode` has input shadow.
22961
- *
22962
- * An input shadow is when a directive steals (shadows) the input by using `@Input('style')` or
22963
- * `@Input('class')` as input.
22964
- *
22965
- * @param tNode `TNode` which we would like to see if it has shadow.
22966
- * @param isClassBased `true` if `class` (`false` if `style`)
22967
- */
22968
- function hasStylingInputShadow(tNode, isClassBased) {
22969
- return (tNode.flags & (isClassBased ? 8 /* TNodeFlags.hasClassInput */ : 16 /* TNodeFlags.hasStyleInput */)) !== 0;
22970
- }
22971
-
22972
- /**
22973
- *
22974
- * Update an interpolated class on an element with single bound value surrounded by text.
22975
- *
22976
- * Used when the value passed to a property has 1 interpolated value in it:
22977
- *
22978
- * ```html
22979
- * <div class="prefix{{v0}}suffix"></div>
22980
- * ```
22981
- *
22982
- * Its compiled representation is:
22983
- *
22984
- * ```ts
22985
- * ɵɵclassMapInterpolate1('prefix', v0, 'suffix');
22986
- * ```
22987
- *
22988
- * @param prefix Static value used for concatenation only.
22989
- * @param v0 Value checked for change.
22990
- * @param suffix Static value used for concatenation only.
22991
- * @codeGenApi
22992
- */
22993
- function ɵɵclassMapInterpolate1(prefix, v0, suffix) {
22994
- const lView = getLView();
22995
- const interpolatedValue = interpolation1(lView, prefix, v0, suffix);
22996
- checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true);
22997
- }
22998
- /**
22999
- *
23000
- * Update an interpolated class on an element with 2 bound values surrounded by text.
23001
- *
23002
- * Used when the value passed to a property has 2 interpolated values in it:
23003
- *
23004
- * ```html
23005
- * <div class="prefix{{v0}}-{{v1}}suffix"></div>
23006
- * ```
23007
- *
23008
- * Its compiled representation is:
23009
- *
23010
- * ```ts
23011
- * ɵɵclassMapInterpolate2('prefix', v0, '-', v1, 'suffix');
23012
- * ```
23013
- *
23014
- * @param prefix Static value used for concatenation only.
23015
- * @param v0 Value checked for change.
23016
- * @param i0 Static value used for concatenation only.
23017
- * @param v1 Value checked for change.
23018
- * @param suffix Static value used for concatenation only.
23019
- * @codeGenApi
23020
- */
23021
- function ɵɵclassMapInterpolate2(prefix, v0, i0, v1, suffix) {
23022
- const lView = getLView();
23023
- const interpolatedValue = interpolation2(lView, prefix, v0, i0, v1, suffix);
23024
- checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true);
23025
- }
23026
- /**
23027
- *
23028
- * Update an interpolated class on an element with 3 bound values surrounded by text.
23029
- *
23030
- * Used when the value passed to a property has 3 interpolated values in it:
23031
- *
23032
- * ```html
23033
- * <div class="prefix{{v0}}-{{v1}}-{{v2}}suffix"></div>
23034
- * ```
23035
- *
23036
- * Its compiled representation is:
23037
- *
23038
- * ```ts
23039
- * ɵɵclassMapInterpolate3(
23040
- * 'prefix', v0, '-', v1, '-', v2, 'suffix');
23041
- * ```
23042
- *
23043
- * @param prefix Static value used for concatenation only.
23044
- * @param v0 Value checked for change.
23045
- * @param i0 Static value used for concatenation only.
23046
- * @param v1 Value checked for change.
23047
- * @param i1 Static value used for concatenation only.
23048
- * @param v2 Value checked for change.
23049
- * @param suffix Static value used for concatenation only.
23050
- * @codeGenApi
23051
- */
23052
- function ɵɵclassMapInterpolate3(prefix, v0, i0, v1, i1, v2, suffix) {
23053
- const lView = getLView();
23054
- const interpolatedValue = interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix);
23055
- checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true);
23056
- }
23057
- /**
23058
- *
23059
- * Update an interpolated class on an element with 4 bound values surrounded by text.
23060
- *
23061
- * Used when the value passed to a property has 4 interpolated values in it:
23062
- *
23063
- * ```html
23064
- * <div class="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}suffix"></div>
23065
- * ```
23066
- *
23067
- * Its compiled representation is:
23068
- *
23069
- * ```ts
23070
- * ɵɵclassMapInterpolate4(
23071
- * 'prefix', v0, '-', v1, '-', v2, '-', v3, 'suffix');
23072
- * ```
23073
- *
23074
- * @param prefix Static value used for concatenation only.
23075
- * @param v0 Value checked for change.
23076
- * @param i0 Static value used for concatenation only.
23077
- * @param v1 Value checked for change.
23078
- * @param i1 Static value used for concatenation only.
23079
- * @param v2 Value checked for change.
23080
- * @param i2 Static value used for concatenation only.
23081
- * @param v3 Value checked for change.
23082
- * @param suffix Static value used for concatenation only.
23083
- * @codeGenApi
23084
- */
23085
- function ɵɵclassMapInterpolate4(prefix, v0, i0, v1, i1, v2, i2, v3, suffix) {
23086
- const lView = getLView();
23087
- const interpolatedValue = interpolation4(lView, prefix, v0, i0, v1, i1, v2, i2, v3, suffix);
23088
- checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true);
23089
- }
23090
- /**
23091
- *
23092
- * Update an interpolated class on an element with 5 bound values surrounded by text.
23093
- *
23094
- * Used when the value passed to a property has 5 interpolated values in it:
23095
- *
23096
- * ```html
23097
- * <div class="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}suffix"></div>
23098
- * ```
23099
- *
23100
- * Its compiled representation is:
23101
- *
23102
- * ```ts
23103
- * ɵɵclassMapInterpolate5(
23104
- * 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, 'suffix');
23105
- * ```
23106
- *
23107
- * @param prefix Static value used for concatenation only.
23108
- * @param v0 Value checked for change.
23109
- * @param i0 Static value used for concatenation only.
23110
- * @param v1 Value checked for change.
23111
- * @param i1 Static value used for concatenation only.
23112
- * @param v2 Value checked for change.
23113
- * @param i2 Static value used for concatenation only.
23114
- * @param v3 Value checked for change.
23115
- * @param i3 Static value used for concatenation only.
23116
- * @param v4 Value checked for change.
23117
- * @param suffix Static value used for concatenation only.
23118
- * @codeGenApi
23119
- */
23120
- function ɵɵclassMapInterpolate5(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix) {
23121
- const lView = getLView();
23122
- const interpolatedValue = interpolation5(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix);
23123
- checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true);
23124
- }
23125
- /**
23126
- *
23127
- * Update an interpolated class on an element with 6 bound values surrounded by text.
23128
- *
23129
- * Used when the value passed to a property has 6 interpolated values in it:
23130
- *
23131
- * ```html
23132
- * <div class="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}suffix"></div>
23133
- * ```
23134
- *
23135
- * Its compiled representation is:
23136
- *
23137
- * ```ts
23138
- * ɵɵclassMapInterpolate6(
23139
- * 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, 'suffix');
23140
- * ```
23141
- *
23142
- * @param prefix Static value used for concatenation only.
23143
- * @param v0 Value checked for change.
23144
- * @param i0 Static value used for concatenation only.
23145
- * @param v1 Value checked for change.
23146
- * @param i1 Static value used for concatenation only.
23147
- * @param v2 Value checked for change.
23148
- * @param i2 Static value used for concatenation only.
23149
- * @param v3 Value checked for change.
23150
- * @param i3 Static value used for concatenation only.
23151
- * @param v4 Value checked for change.
23152
- * @param i4 Static value used for concatenation only.
23153
- * @param v5 Value checked for change.
23154
- * @param suffix Static value used for concatenation only.
23155
- * @codeGenApi
23156
- */
23157
- function ɵɵclassMapInterpolate6(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix) {
23158
- const lView = getLView();
23159
- const interpolatedValue = interpolation6(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix);
23160
- checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true);
23161
- }
23162
- /**
23163
- *
23164
- * Update an interpolated class on an element with 7 bound values surrounded by text.
23165
- *
23166
- * Used when the value passed to a property has 7 interpolated values in it:
23167
- *
23168
- * ```html
23169
- * <div class="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}suffix"></div>
23170
- * ```
23171
- *
23172
- * Its compiled representation is:
23173
- *
23174
- * ```ts
23175
- * ɵɵclassMapInterpolate7(
23176
- * 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, 'suffix');
23177
- * ```
23178
- *
23179
- * @param prefix Static value used for concatenation only.
23180
- * @param v0 Value checked for change.
23181
- * @param i0 Static value used for concatenation only.
23182
- * @param v1 Value checked for change.
23183
- * @param i1 Static value used for concatenation only.
23184
- * @param v2 Value checked for change.
23185
- * @param i2 Static value used for concatenation only.
23186
- * @param v3 Value checked for change.
23187
- * @param i3 Static value used for concatenation only.
23188
- * @param v4 Value checked for change.
23189
- * @param i4 Static value used for concatenation only.
23190
- * @param v5 Value checked for change.
23191
- * @param i5 Static value used for concatenation only.
23192
- * @param v6 Value checked for change.
23193
- * @param suffix Static value used for concatenation only.
23194
- * @codeGenApi
23195
- */
23196
- function ɵɵclassMapInterpolate7(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix) {
23197
- const lView = getLView();
23198
- const interpolatedValue = interpolation7(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix);
23199
- checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true);
23200
- }
23201
- /**
23202
- *
23203
- * Update an interpolated class on an element with 8 bound values surrounded by text.
23204
- *
23205
- * Used when the value passed to a property has 8 interpolated values in it:
23206
- *
23207
- * ```html
23208
- * <div class="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}suffix"></div>
23209
- * ```
23210
- *
23211
- * Its compiled representation is:
23212
- *
23213
- * ```ts
23214
- * ɵɵclassMapInterpolate8(
23215
- * 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, 'suffix');
23216
- * ```
23217
- *
23218
- * @param prefix Static value used for concatenation only.
23219
- * @param v0 Value checked for change.
23220
- * @param i0 Static value used for concatenation only.
23221
- * @param v1 Value checked for change.
23222
- * @param i1 Static value used for concatenation only.
23223
- * @param v2 Value checked for change.
23224
- * @param i2 Static value used for concatenation only.
23225
- * @param v3 Value checked for change.
23226
- * @param i3 Static value used for concatenation only.
23227
- * @param v4 Value checked for change.
23228
- * @param i4 Static value used for concatenation only.
23229
- * @param v5 Value checked for change.
23230
- * @param i5 Static value used for concatenation only.
23231
- * @param v6 Value checked for change.
23232
- * @param i6 Static value used for concatenation only.
23233
- * @param v7 Value checked for change.
23234
- * @param suffix Static value used for concatenation only.
23235
- * @codeGenApi
23236
- */
23237
- function ɵɵclassMapInterpolate8(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix) {
23238
- const lView = getLView();
23239
- const interpolatedValue = interpolation8(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix);
23240
- checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true);
23241
- }
23242
- /**
23243
- * Update an interpolated class on an element with 9 or more bound values surrounded by text.
23244
- *
23245
- * Used when the number of interpolated values exceeds 8.
23246
- *
23247
- * ```html
23248
- * <div
23249
- * class="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}-{{v8}}-{{v9}}suffix"></div>
23250
- * ```
23251
- *
23252
- * Its compiled representation is:
23253
- *
23254
- * ```ts
23255
- * ɵɵclassMapInterpolateV(
23256
- * ['prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, '-', v9,
23257
- * 'suffix']);
23258
- * ```
23259
- *.
23260
- * @param values The collection of values and the strings in-between those values, beginning with
23261
- * a string prefix and ending with a string suffix.
23262
- * (e.g. `['prefix', value0, '-', value1, '-', value2, ..., value99, 'suffix']`)
23263
- * @codeGenApi
23264
- */
23265
- function ɵɵclassMapInterpolateV(values) {
23266
- const lView = getLView();
23267
- const interpolatedValue = interpolationV(lView, values);
23268
- checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true);
23269
- }
23270
-
23271
21405
  /*!
23272
21406
  * @license
23273
21407
  * Copyright Google LLC All Rights Reserved.
@@ -24012,6 +22146,44 @@ function getExistingTNode(tView, index) {
24012
22146
  return tNode;
24013
22147
  }
24014
22148
 
22149
+ /**
22150
+ * Update a property on a selected element.
22151
+ *
22152
+ * Operates on the element selected by index via the {@link select} instruction.
22153
+ *
22154
+ * If the property name also exists as an input property on one of the element's directives,
22155
+ * the component property will be set instead of the element property. This check must
22156
+ * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled
22157
+ *
22158
+ * @param propName Name of property. Because it is going to DOM, this is not subject to
22159
+ * renaming as part of minification.
22160
+ * @param value New value to write.
22161
+ * @param sanitizer An optional function used to sanitize the value.
22162
+ * @returns This function returns itself so that it may be chained
22163
+ * (e.g. `property('name', ctx.name)('title', ctx.title)`)
22164
+ *
22165
+ * @codeGenApi
22166
+ */
22167
+ function ɵɵproperty(propName, value, sanitizer) {
22168
+ const lView = getLView();
22169
+ const bindingIndex = nextBindingIndex();
22170
+ if (bindingUpdated(lView, bindingIndex, value)) {
22171
+ const tView = getTView();
22172
+ const tNode = getSelectedTNode();
22173
+ setPropertyAndInputs(tNode, lView, propName, value, lView[RENDERER], sanitizer);
22174
+ ngDevMode && storePropertyBindingMetadata(tView.data, tNode, propName, bindingIndex);
22175
+ }
22176
+ return ɵɵproperty;
22177
+ }
22178
+ /**
22179
+ * Given `<div style="..." my-dir>` and `MyDir` with `@Input('style')` we need to write to
22180
+ * directive input.
22181
+ */
22182
+ function setDirectiveInputsWhichShadowsStyling(tView, tNode, lView, value, isClassBased) {
22183
+ // We support both 'class' and `className` hence the fallback.
22184
+ setAllInputsForProperty(tNode, tView, lView, isClassBased ? 'class' : 'style', value);
22185
+ }
22186
+
24015
22187
  /**
24016
22188
  * Create DOM element. The instruction must later be followed by `elementEnd()` call.
24017
22189
  *
@@ -26416,1248 +24588,1474 @@ function insertFallbackContent(lView, tView, fallbackIndex) {
26416
24588
  }
26417
24589
 
26418
24590
  /**
24591
+ * Registers a QueryList, associated with a content query, for later refresh (part of a view
24592
+ * refresh).
24593
+ *
24594
+ * @param directiveIndex Current directive index
24595
+ * @param predicate The type for which the query will search
24596
+ * @param flags Flags associated with the query
24597
+ * @param read What to save in the query
24598
+ * @returns QueryList<T>
24599
+ *
24600
+ * @codeGenApi
24601
+ */
24602
+ function ɵɵcontentQuery(directiveIndex, predicate, flags, read) {
24603
+ createContentQuery(directiveIndex, predicate, flags, read);
24604
+ }
24605
+ /**
24606
+ * Creates a new view query by initializing internal data structures.
24607
+ *
24608
+ * @param predicate The type for which the query will search
24609
+ * @param flags Flags associated with the query
24610
+ * @param read What to save in the query
24611
+ *
24612
+ * @codeGenApi
24613
+ */
24614
+ function ɵɵviewQuery(predicate, flags, read) {
24615
+ createViewQuery(predicate, flags, read);
24616
+ }
24617
+ /**
24618
+ * Refreshes a query by combining matches from all active views and removing matches from deleted
24619
+ * views.
24620
+ *
24621
+ * @returns `true` if a query got dirty during change detection or if this is a static query
24622
+ * resolving in creation mode, `false` otherwise.
24623
+ *
24624
+ * @codeGenApi
24625
+ */
24626
+ function ɵɵqueryRefresh(queryList) {
24627
+ const lView = getLView();
24628
+ const tView = getTView();
24629
+ const queryIndex = getCurrentQueryIndex();
24630
+ setCurrentQueryIndex(queryIndex + 1);
24631
+ const tQuery = getTQuery(tView, queryIndex);
24632
+ if (queryList.dirty &&
24633
+ isCreationMode(lView) ===
24634
+ ((tQuery.metadata.flags & 2 /* QueryFlags.isStatic */) === 2 /* QueryFlags.isStatic */)) {
24635
+ if (tQuery.matches === null) {
24636
+ queryList.reset([]);
24637
+ }
24638
+ else {
24639
+ const result = getQueryResults(lView, queryIndex);
24640
+ queryList.reset(result, unwrapElementRef);
24641
+ queryList.notifyOnChanges();
24642
+ }
24643
+ return true;
24644
+ }
24645
+ return false;
24646
+ }
24647
+ /**
24648
+ * Loads a QueryList corresponding to the current view or content query.
24649
+ *
24650
+ * @codeGenApi
24651
+ */
24652
+ function ɵɵloadQuery() {
24653
+ return loadQueryInternal(getLView(), getCurrentQueryIndex());
24654
+ }
24655
+
24656
+ /**
24657
+ * Creates a new content query and binds it to a signal created by an authoring function.
26419
24658
  *
26420
- * Update an interpolated property on an element with a lone bound value
24659
+ * @param directiveIndex Current directive index
24660
+ * @param target The target signal to which the query should be bound
24661
+ * @param predicate The type for which the query will search
24662
+ * @param flags Flags associated with the query
24663
+ * @param read What to save in the query
26421
24664
  *
26422
- * Used when the value passed to a property has 1 interpolated value in it, an no additional text
26423
- * surrounds that interpolated value:
24665
+ * @codeGenApi
24666
+ */
24667
+ function ɵɵcontentQuerySignal(directiveIndex, target, predicate, flags, read) {
24668
+ bindQueryToSignal(target, createContentQuery(directiveIndex, predicate, flags, read));
24669
+ }
24670
+ /**
24671
+ * Creates a new view query by initializing internal data structures and binding a new query to the
24672
+ * target signal.
26424
24673
  *
26425
- * ```html
26426
- * <div title="{{v0}}"></div>
26427
- * ```
24674
+ * @param target The target signal to assign the query results to.
24675
+ * @param predicate The type or label that should match a given query
24676
+ * @param flags Flags associated with the query
24677
+ * @param read What to save in the query
26428
24678
  *
26429
- * Its compiled representation is::
24679
+ * @codeGenApi
24680
+ */
24681
+ function ɵɵviewQuerySignal(target, predicate, flags, read) {
24682
+ bindQueryToSignal(target, createViewQuery(predicate, flags, read));
24683
+ }
24684
+ /**
24685
+ * Advances the current query index by a specified offset.
26430
24686
  *
26431
- * ```ts
26432
- * ɵɵpropertyInterpolate('title', v0);
26433
- * ```
24687
+ * Adjusting the current query index is necessary in cases where a given directive has a mix of
24688
+ * zone-based and signal-based queries. The signal-based queries don't require tracking of the
24689
+ * current index (those are refreshed on demand and not during change detection) so this instruction
24690
+ * is only necessary for backward-compatibility.
26434
24691
  *
26435
- * If the property name also exists as an input property on one of the element's directives,
26436
- * the component property will be set instead of the element property. This check must
26437
- * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.
24692
+ * @param index offset to apply to the current query index (defaults to 1)
26438
24693
  *
26439
- * @param propName The name of the property to update
26440
- * @param prefix Static value used for concatenation only.
26441
- * @param v0 Value checked for change.
26442
- * @param suffix Static value used for concatenation only.
26443
- * @param sanitizer An optional sanitizer function
26444
- * @returns itself, so that it may be chained.
26445
24694
  * @codeGenApi
26446
24695
  */
26447
- function ɵɵpropertyInterpolate(propName, v0, sanitizer) {
26448
- ɵɵpropertyInterpolate1(propName, '', v0, '', sanitizer);
26449
- return ɵɵpropertyInterpolate;
24696
+ function ɵɵqueryAdvance(indexOffset = 1) {
24697
+ setCurrentQueryIndex(getCurrentQueryIndex() + indexOffset);
26450
24698
  }
24699
+
26451
24700
  /**
24701
+ * Retrieves a local reference from the current contextViewData.
26452
24702
  *
26453
- * Update an interpolated property on an element with single bound value surrounded by text.
26454
- *
26455
- * Used when the value passed to a property has 1 interpolated value in it:
24703
+ * If the reference to retrieve is in a parent view, this instruction is used in conjunction
24704
+ * with a nextContext() call, which walks up the tree and updates the contextViewData instance.
26456
24705
  *
26457
- * ```html
26458
- * <div title="prefix{{v0}}suffix"></div>
26459
- * ```
24706
+ * @param index The index of the local ref in contextViewData.
26460
24707
  *
26461
- * Its compiled representation is::
24708
+ * @codeGenApi
24709
+ */
24710
+ function ɵɵreference(index) {
24711
+ const contextLView = getContextLView();
24712
+ return load(contextLView, HEADER_OFFSET + index);
24713
+ }
24714
+
24715
+ function toTStylingRange(prev, next) {
24716
+ ngDevMode && assertNumberInRange(prev, 0, 32767 /* StylingRange.UNSIGNED_MASK */);
24717
+ ngDevMode && assertNumberInRange(next, 0, 32767 /* StylingRange.UNSIGNED_MASK */);
24718
+ return ((prev << 17 /* StylingRange.PREV_SHIFT */) | (next << 2 /* StylingRange.NEXT_SHIFT */));
24719
+ }
24720
+ function getTStylingRangePrev(tStylingRange) {
24721
+ ngDevMode && assertNumber(tStylingRange, 'expected number');
24722
+ return (tStylingRange >> 17 /* StylingRange.PREV_SHIFT */) & 32767 /* StylingRange.UNSIGNED_MASK */;
24723
+ }
24724
+ function getTStylingRangePrevDuplicate(tStylingRange) {
24725
+ ngDevMode && assertNumber(tStylingRange, 'expected number');
24726
+ return (tStylingRange & 2 /* StylingRange.PREV_DUPLICATE */) == 2 /* StylingRange.PREV_DUPLICATE */;
24727
+ }
24728
+ function setTStylingRangePrev(tStylingRange, previous) {
24729
+ ngDevMode && assertNumber(tStylingRange, 'expected number');
24730
+ ngDevMode && assertNumberInRange(previous, 0, 32767 /* StylingRange.UNSIGNED_MASK */);
24731
+ return ((tStylingRange & 131071 /* StylingRange.PREV_MASK */) |
24732
+ (previous << 17 /* StylingRange.PREV_SHIFT */));
24733
+ }
24734
+ function setTStylingRangePrevDuplicate(tStylingRange) {
24735
+ ngDevMode && assertNumber(tStylingRange, 'expected number');
24736
+ return (tStylingRange | 2 /* StylingRange.PREV_DUPLICATE */);
24737
+ }
24738
+ function getTStylingRangeNext(tStylingRange) {
24739
+ ngDevMode && assertNumber(tStylingRange, 'expected number');
24740
+ return (tStylingRange & 131068 /* StylingRange.NEXT_MASK */) >> 2 /* StylingRange.NEXT_SHIFT */;
24741
+ }
24742
+ function setTStylingRangeNext(tStylingRange, next) {
24743
+ ngDevMode && assertNumber(tStylingRange, 'expected number');
24744
+ ngDevMode && assertNumberInRange(next, 0, 32767 /* StylingRange.UNSIGNED_MASK */);
24745
+ return ((tStylingRange & -131069 /* StylingRange.NEXT_MASK */) | //
24746
+ (next << 2 /* StylingRange.NEXT_SHIFT */));
24747
+ }
24748
+ function getTStylingRangeNextDuplicate(tStylingRange) {
24749
+ ngDevMode && assertNumber(tStylingRange, 'expected number');
24750
+ return (tStylingRange & 1 /* StylingRange.NEXT_DUPLICATE */) === 1 /* StylingRange.NEXT_DUPLICATE */;
24751
+ }
24752
+ function setTStylingRangeNextDuplicate(tStylingRange) {
24753
+ ngDevMode && assertNumber(tStylingRange, 'expected number');
24754
+ return (tStylingRange | 1 /* StylingRange.NEXT_DUPLICATE */);
24755
+ }
24756
+
24757
+ /**
24758
+ * Insert new `tStyleValue` at `TData` and link existing style bindings such that we maintain linked
24759
+ * list of styles and compute the duplicate flag.
26462
24760
  *
26463
- * ```ts
26464
- * ɵɵpropertyInterpolate1('title', 'prefix', v0, 'suffix');
26465
- * ```
24761
+ * Note: this function is executed during `firstUpdatePass` only to populate the `TView.data`.
26466
24762
  *
26467
- * If the property name also exists as an input property on one of the element's directives,
26468
- * the component property will be set instead of the element property. This check must
26469
- * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.
24763
+ * The function works by keeping track of `tStylingRange` which contains two pointers pointing to
24764
+ * the head/tail of the template portion of the styles.
24765
+ * - if `isHost === false` (we are template) then insertion is at tail of `TStylingRange`
24766
+ * - if `isHost === true` (we are host binding) then insertion is at head of `TStylingRange`
26470
24767
  *
26471
- * @param propName The name of the property to update
26472
- * @param prefix Static value used for concatenation only.
26473
- * @param v0 Value checked for change.
26474
- * @param suffix Static value used for concatenation only.
26475
- * @param sanitizer An optional sanitizer function
26476
- * @returns itself, so that it may be chained.
26477
- * @codeGenApi
24768
+ * @param tData The `TData` to insert into.
24769
+ * @param tNode `TNode` associated with the styling element.
24770
+ * @param tStylingKey See `TStylingKey`.
24771
+ * @param index location of where `tStyleValue` should be stored (and linked into list.)
24772
+ * @param isHostBinding `true` if the insertion is for a `hostBinding`. (insertion is in front of
24773
+ * template.)
24774
+ * @param isClassBinding True if the associated `tStylingKey` as a `class` styling.
24775
+ * `tNode.classBindings` should be used (or `tNode.styleBindings` otherwise.)
26478
24776
  */
26479
- function ɵɵpropertyInterpolate1(propName, prefix, v0, suffix, sanitizer) {
26480
- const lView = getLView();
26481
- const interpolatedValue = interpolation1(lView, prefix, v0, suffix);
26482
- if (interpolatedValue !== NO_CHANGE) {
26483
- const tView = getTView();
26484
- const tNode = getSelectedTNode();
26485
- setPropertyAndInputs(tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer);
24777
+ function insertTStylingBinding(tData, tNode, tStylingKeyWithStatic, index, isHostBinding, isClassBinding) {
24778
+ ngDevMode && assertFirstUpdatePass(getTView());
24779
+ let tBindings = isClassBinding ? tNode.classBindings : tNode.styleBindings;
24780
+ let tmplHead = getTStylingRangePrev(tBindings);
24781
+ let tmplTail = getTStylingRangeNext(tBindings);
24782
+ tData[index] = tStylingKeyWithStatic;
24783
+ let isKeyDuplicateOfStatic = false;
24784
+ let tStylingKey;
24785
+ if (Array.isArray(tStylingKeyWithStatic)) {
24786
+ // We are case when the `TStylingKey` contains static fields as well.
24787
+ const staticKeyValueArray = tStylingKeyWithStatic;
24788
+ tStylingKey = staticKeyValueArray[1]; // unwrap.
24789
+ // We need to check if our key is present in the static so that we can mark it as duplicate.
24790
+ if (tStylingKey === null ||
24791
+ keyValueArrayIndexOf(staticKeyValueArray, tStylingKey) > 0) {
24792
+ // tStylingKey is present in the statics, need to mark it as duplicate.
24793
+ isKeyDuplicateOfStatic = true;
24794
+ }
24795
+ }
24796
+ else {
24797
+ tStylingKey = tStylingKeyWithStatic;
24798
+ }
24799
+ if (isHostBinding) {
24800
+ // We are inserting host bindings
24801
+ // If we don't have template bindings then `tail` is 0.
24802
+ const hasTemplateBindings = tmplTail !== 0;
24803
+ // This is important to know because that means that the `head` can't point to the first
24804
+ // template bindings (there are none.) Instead the head points to the tail of the template.
24805
+ if (hasTemplateBindings) {
24806
+ // template head's "prev" will point to last host binding or to 0 if no host bindings yet
24807
+ const previousNode = getTStylingRangePrev(tData[tmplHead + 1]);
24808
+ tData[index + 1] = toTStylingRange(previousNode, tmplHead);
24809
+ // if a host binding has already been registered, we need to update the next of that host
24810
+ // binding to point to this one
24811
+ if (previousNode !== 0) {
24812
+ // We need to update the template-tail value to point to us.
24813
+ tData[previousNode + 1] = setTStylingRangeNext(tData[previousNode + 1], index);
24814
+ }
24815
+ // The "previous" of the template binding head should point to this host binding
24816
+ tData[tmplHead + 1] = setTStylingRangePrev(tData[tmplHead + 1], index);
24817
+ }
24818
+ else {
24819
+ tData[index + 1] = toTStylingRange(tmplHead, 0);
24820
+ // if a host binding has already been registered, we need to update the next of that host
24821
+ // binding to point to this one
24822
+ if (tmplHead !== 0) {
24823
+ // We need to update the template-tail value to point to us.
24824
+ tData[tmplHead + 1] = setTStylingRangeNext(tData[tmplHead + 1], index);
24825
+ }
24826
+ // if we don't have template, the head points to template-tail, and needs to be advanced.
24827
+ tmplHead = index;
24828
+ }
24829
+ }
24830
+ else {
24831
+ // We are inserting in template section.
24832
+ // We need to set this binding's "previous" to the current template tail
24833
+ tData[index + 1] = toTStylingRange(tmplTail, 0);
26486
24834
  ngDevMode &&
26487
- storePropertyBindingMetadata(tView.data, tNode, propName, getBindingIndex() - 1, prefix, suffix ?? '');
24835
+ assertEqual(tmplHead !== 0 && tmplTail === 0, false, 'Adding template bindings after hostBindings is not allowed.');
24836
+ if (tmplHead === 0) {
24837
+ tmplHead = index;
24838
+ }
24839
+ else {
24840
+ // We need to update the previous value "next" to point to this binding
24841
+ tData[tmplTail + 1] = setTStylingRangeNext(tData[tmplTail + 1], index);
24842
+ }
24843
+ tmplTail = index;
24844
+ }
24845
+ // Now we need to update / compute the duplicates.
24846
+ // Starting with our location search towards head (least priority)
24847
+ if (isKeyDuplicateOfStatic) {
24848
+ tData[index + 1] = setTStylingRangePrevDuplicate(tData[index + 1]);
24849
+ }
24850
+ markDuplicates(tData, tStylingKey, index, true);
24851
+ markDuplicates(tData, tStylingKey, index, false);
24852
+ markDuplicateOfResidualStyling(tNode, tStylingKey, tData, index, isClassBinding);
24853
+ tBindings = toTStylingRange(tmplHead, tmplTail);
24854
+ if (isClassBinding) {
24855
+ tNode.classBindings = tBindings;
24856
+ }
24857
+ else {
24858
+ tNode.styleBindings = tBindings;
26488
24859
  }
26489
- return ɵɵpropertyInterpolate1;
26490
24860
  }
26491
24861
  /**
24862
+ * Look into the residual styling to see if the current `tStylingKey` is duplicate of residual.
26492
24863
  *
26493
- * Update an interpolated property on an element with 2 bound values surrounded by text.
26494
- *
26495
- * Used when the value passed to a property has 2 interpolated values in it:
26496
- *
26497
- * ```html
26498
- * <div title="prefix{{v0}}-{{v1}}suffix"></div>
26499
- * ```
26500
- *
26501
- * Its compiled representation is::
26502
- *
26503
- * ```ts
26504
- * ɵɵpropertyInterpolate2('title', 'prefix', v0, '-', v1, 'suffix');
26505
- * ```
26506
- *
26507
- * If the property name also exists as an input property on one of the element's directives,
26508
- * the component property will be set instead of the element property. This check must
26509
- * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.
26510
- *
26511
- * @param propName The name of the property to update
26512
- * @param prefix Static value used for concatenation only.
26513
- * @param v0 Value checked for change.
26514
- * @param i0 Static value used for concatenation only.
26515
- * @param v1 Value checked for change.
26516
- * @param suffix Static value used for concatenation only.
26517
- * @param sanitizer An optional sanitizer function
26518
- * @returns itself, so that it may be chained.
26519
- * @codeGenApi
24864
+ * @param tNode `TNode` where the residual is stored.
24865
+ * @param tStylingKey `TStylingKey` to store.
24866
+ * @param tData `TData` associated with the current `LView`.
24867
+ * @param index location of where `tStyleValue` should be stored (and linked into list.)
24868
+ * @param isClassBinding True if the associated `tStylingKey` as a `class` styling.
24869
+ * `tNode.classBindings` should be used (or `tNode.styleBindings` otherwise.)
26520
24870
  */
26521
- function ɵɵpropertyInterpolate2(propName, prefix, v0, i0, v1, suffix, sanitizer) {
26522
- const lView = getLView();
26523
- const interpolatedValue = interpolation2(lView, prefix, v0, i0, v1, suffix);
26524
- if (interpolatedValue !== NO_CHANGE) {
26525
- const tView = getTView();
26526
- const tNode = getSelectedTNode();
26527
- setPropertyAndInputs(tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer);
26528
- ngDevMode &&
26529
- storePropertyBindingMetadata(tView.data, tNode, propName, getBindingIndex() - 2, prefix, i0, suffix ?? '');
24871
+ function markDuplicateOfResidualStyling(tNode, tStylingKey, tData, index, isClassBinding) {
24872
+ const residual = isClassBinding ? tNode.residualClasses : tNode.residualStyles;
24873
+ if (residual != null /* or undefined */ &&
24874
+ typeof tStylingKey == 'string' &&
24875
+ keyValueArrayIndexOf(residual, tStylingKey) >= 0) {
24876
+ // We have duplicate in the residual so mark ourselves as duplicate.
24877
+ tData[index + 1] = setTStylingRangeNextDuplicate(tData[index + 1]);
26530
24878
  }
26531
- return ɵɵpropertyInterpolate2;
26532
24879
  }
26533
24880
  /**
24881
+ * Marks `TStyleValue`s as duplicates if another style binding in the list has the same
24882
+ * `TStyleValue`.
26534
24883
  *
26535
- * Update an interpolated property on an element with 3 bound values surrounded by text.
26536
- *
26537
- * Used when the value passed to a property has 3 interpolated values in it:
24884
+ * NOTE: this function is intended to be called twice once with `isPrevDir` set to `true` and once
24885
+ * with it set to `false` to search both the previous as well as next items in the list.
26538
24886
  *
26539
- * ```html
26540
- * <div title="prefix{{v0}}-{{v1}}-{{v2}}suffix"></div>
24887
+ * No duplicate case
26541
24888
  * ```
26542
- *
26543
- * Its compiled representation is::
26544
- *
26545
- * ```ts
26546
- * ɵɵpropertyInterpolate3(
26547
- * 'title', 'prefix', v0, '-', v1, '-', v2, 'suffix');
24889
+ * [style.color]
24890
+ * [style.width.px] <<- index
24891
+ * [style.height.px]
26548
24892
  * ```
26549
24893
  *
26550
- * If the property name also exists as an input property on one of the element's directives,
26551
- * the component property will be set instead of the element property. This check must
26552
- * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.
26553
- *
26554
- * @param propName The name of the property to update
26555
- * @param prefix Static value used for concatenation only.
26556
- * @param v0 Value checked for change.
26557
- * @param i0 Static value used for concatenation only.
26558
- * @param v1 Value checked for change.
26559
- * @param i1 Static value used for concatenation only.
26560
- * @param v2 Value checked for change.
26561
- * @param suffix Static value used for concatenation only.
26562
- * @param sanitizer An optional sanitizer function
26563
- * @returns itself, so that it may be chained.
26564
- * @codeGenApi
26565
- */
26566
- function ɵɵpropertyInterpolate3(propName, prefix, v0, i0, v1, i1, v2, suffix, sanitizer) {
26567
- const lView = getLView();
26568
- const interpolatedValue = interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix);
26569
- if (interpolatedValue !== NO_CHANGE) {
26570
- const tView = getTView();
26571
- const tNode = getSelectedTNode();
26572
- setPropertyAndInputs(tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer);
26573
- ngDevMode &&
26574
- storePropertyBindingMetadata(tView.data, tNode, propName, getBindingIndex() - 3, prefix, i0, i1, suffix ?? '');
26575
- }
26576
- return ɵɵpropertyInterpolate3;
26577
- }
26578
- /**
26579
- *
26580
- * Update an interpolated property on an element with 4 bound values surrounded by text.
26581
- *
26582
- * Used when the value passed to a property has 4 interpolated values in it:
24894
+ * In the above case adding `[style.width.px]` to the existing `[style.color]` produces no
24895
+ * duplicates because `width` is not found in any other part of the linked list.
26583
24896
  *
26584
- * ```html
26585
- * <div title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}suffix"></div>
24897
+ * Duplicate case
24898
+ * ```
24899
+ * [style.color]
24900
+ * [style.width.em]
24901
+ * [style.width.px] <<- index
26586
24902
  * ```
24903
+ * In the above case adding `[style.width.px]` will produce a duplicate with `[style.width.em]`
24904
+ * because `width` is found in the chain.
26587
24905
  *
26588
- * Its compiled representation is::
24906
+ * Map case 1
24907
+ * ```
24908
+ * [style.width.px]
24909
+ * [style.color]
24910
+ * [style] <<- index
24911
+ * ```
24912
+ * In the above case adding `[style]` will produce a duplicate with any other bindings because
24913
+ * `[style]` is a Map and as such is fully dynamic and could produce `color` or `width`.
26589
24914
  *
26590
- * ```ts
26591
- * ɵɵpropertyInterpolate4(
26592
- * 'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, 'suffix');
24915
+ * Map case 2
24916
+ * ```
24917
+ * [style]
24918
+ * [style.width.px]
24919
+ * [style.color] <<- index
26593
24920
  * ```
24921
+ * In the above case adding `[style.color]` will produce a duplicate because there is already a
24922
+ * `[style]` binding which is a Map and as such is fully dynamic and could produce `color` or
24923
+ * `width`.
26594
24924
  *
26595
- * If the property name also exists as an input property on one of the element's directives,
26596
- * the component property will be set instead of the element property. This check must
26597
- * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.
24925
+ * NOTE: Once `[style]` (Map) is added into the system all things are mapped as duplicates.
24926
+ * NOTE: We use `style` as example, but same logic is applied to `class`es as well.
26598
24927
  *
26599
- * @param propName The name of the property to update
26600
- * @param prefix Static value used for concatenation only.
26601
- * @param v0 Value checked for change.
26602
- * @param i0 Static value used for concatenation only.
26603
- * @param v1 Value checked for change.
26604
- * @param i1 Static value used for concatenation only.
26605
- * @param v2 Value checked for change.
26606
- * @param i2 Static value used for concatenation only.
26607
- * @param v3 Value checked for change.
26608
- * @param suffix Static value used for concatenation only.
26609
- * @param sanitizer An optional sanitizer function
26610
- * @returns itself, so that it may be chained.
26611
- * @codeGenApi
24928
+ * @param tData `TData` where the linked list is stored.
24929
+ * @param tStylingKey `TStylingKeyPrimitive` which contains the value to compare to other keys in
24930
+ * the linked list.
24931
+ * @param index Starting location in the linked list to search from
24932
+ * @param isPrevDir Direction.
24933
+ * - `true` for previous (lower priority);
24934
+ * - `false` for next (higher priority).
26612
24935
  */
26613
- function ɵɵpropertyInterpolate4(propName, prefix, v0, i0, v1, i1, v2, i2, v3, suffix, sanitizer) {
26614
- const lView = getLView();
26615
- const interpolatedValue = interpolation4(lView, prefix, v0, i0, v1, i1, v2, i2, v3, suffix);
26616
- if (interpolatedValue !== NO_CHANGE) {
26617
- const tView = getTView();
26618
- const tNode = getSelectedTNode();
26619
- setPropertyAndInputs(tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer);
26620
- ngDevMode &&
26621
- storePropertyBindingMetadata(tView.data, tNode, propName, getBindingIndex() - 4, prefix, i0, i1, i2, suffix ?? '');
24936
+ function markDuplicates(tData, tStylingKey, index, isPrevDir) {
24937
+ const tStylingAtIndex = tData[index + 1];
24938
+ const isMap = tStylingKey === null;
24939
+ let cursor = isPrevDir
24940
+ ? getTStylingRangePrev(tStylingAtIndex)
24941
+ : getTStylingRangeNext(tStylingAtIndex);
24942
+ let foundDuplicate = false;
24943
+ // We keep iterating as long as we have a cursor
24944
+ // AND either:
24945
+ // - we found what we are looking for, OR
24946
+ // - we are a map in which case we have to continue searching even after we find what we were
24947
+ // looking for since we are a wild card and everything needs to be flipped to duplicate.
24948
+ while (cursor !== 0 && (foundDuplicate === false || isMap)) {
24949
+ ngDevMode && assertIndexInRange(tData, cursor);
24950
+ const tStylingValueAtCursor = tData[cursor];
24951
+ const tStyleRangeAtCursor = tData[cursor + 1];
24952
+ if (isStylingMatch(tStylingValueAtCursor, tStylingKey)) {
24953
+ foundDuplicate = true;
24954
+ tData[cursor + 1] = isPrevDir
24955
+ ? setTStylingRangeNextDuplicate(tStyleRangeAtCursor)
24956
+ : setTStylingRangePrevDuplicate(tStyleRangeAtCursor);
24957
+ }
24958
+ cursor = isPrevDir
24959
+ ? getTStylingRangePrev(tStyleRangeAtCursor)
24960
+ : getTStylingRangeNext(tStyleRangeAtCursor);
24961
+ }
24962
+ if (foundDuplicate) {
24963
+ // if we found a duplicate, than mark ourselves.
24964
+ tData[index + 1] = isPrevDir
24965
+ ? setTStylingRangePrevDuplicate(tStylingAtIndex)
24966
+ : setTStylingRangeNextDuplicate(tStylingAtIndex);
26622
24967
  }
26623
- return ɵɵpropertyInterpolate4;
26624
24968
  }
26625
24969
  /**
24970
+ * Determines if two `TStylingKey`s are a match.
26626
24971
  *
26627
- * Update an interpolated property on an element with 5 bound values surrounded by text.
26628
- *
26629
- * Used when the value passed to a property has 5 interpolated values in it:
26630
- *
26631
- * ```html
26632
- * <div title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}suffix"></div>
26633
- * ```
26634
- *
26635
- * Its compiled representation is::
26636
- *
26637
- * ```ts
26638
- * ɵɵpropertyInterpolate5(
26639
- * 'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, 'suffix');
26640
- * ```
24972
+ * When computing whether a binding contains a duplicate, we need to compare if the instruction
24973
+ * `TStylingKey` has a match.
26641
24974
  *
26642
- * If the property name also exists as an input property on one of the element's directives,
26643
- * the component property will be set instead of the element property. This check must
26644
- * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.
24975
+ * Here are examples of `TStylingKey`s which match given `tStylingKeyCursor` is:
24976
+ * - `color`
24977
+ * - `color` // Match another color
24978
+ * - `null` // That means that `tStylingKey` is a `classMap`/`styleMap` instruction
24979
+ * - `['', 'color', 'other', true]` // wrapped `color` so match
24980
+ * - `['', null, 'other', true]` // wrapped `null` so match
24981
+ * - `['', 'width', 'color', 'value']` // wrapped static value contains a match on `'color'`
24982
+ * - `null` // `tStylingKeyCursor` always match as it is `classMap`/`styleMap` instruction
26645
24983
  *
26646
- * @param propName The name of the property to update
26647
- * @param prefix Static value used for concatenation only.
26648
- * @param v0 Value checked for change.
26649
- * @param i0 Static value used for concatenation only.
26650
- * @param v1 Value checked for change.
26651
- * @param i1 Static value used for concatenation only.
26652
- * @param v2 Value checked for change.
26653
- * @param i2 Static value used for concatenation only.
26654
- * @param v3 Value checked for change.
26655
- * @param i3 Static value used for concatenation only.
26656
- * @param v4 Value checked for change.
26657
- * @param suffix Static value used for concatenation only.
26658
- * @param sanitizer An optional sanitizer function
26659
- * @returns itself, so that it may be chained.
26660
- * @codeGenApi
24984
+ * @param tStylingKeyCursor
24985
+ * @param tStylingKey
26661
24986
  */
26662
- function ɵɵpropertyInterpolate5(propName, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix, sanitizer) {
26663
- const lView = getLView();
26664
- const interpolatedValue = interpolation5(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix);
26665
- if (interpolatedValue !== NO_CHANGE) {
26666
- const tView = getTView();
26667
- const tNode = getSelectedTNode();
26668
- setPropertyAndInputs(tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer);
26669
- ngDevMode &&
26670
- storePropertyBindingMetadata(tView.data, tNode, propName, getBindingIndex() - 5, prefix, i0, i1, i2, i3, suffix ?? '');
24987
+ function isStylingMatch(tStylingKeyCursor, tStylingKey) {
24988
+ ngDevMode &&
24989
+ assertNotEqual(Array.isArray(tStylingKey), true, "Expected that 'tStylingKey' has been unwrapped");
24990
+ if (tStylingKeyCursor === null || // If the cursor is `null` it means that we have map at that
24991
+ // location so we must assume that we have a match.
24992
+ tStylingKey == null || // If `tStylingKey` is `null` then it is a map therefor assume that it
24993
+ // contains a match.
24994
+ (Array.isArray(tStylingKeyCursor) ? tStylingKeyCursor[1] : tStylingKeyCursor) === tStylingKey // If the keys match explicitly than we are a match.
24995
+ ) {
24996
+ return true;
24997
+ }
24998
+ else if (Array.isArray(tStylingKeyCursor) && typeof tStylingKey === 'string') {
24999
+ // if we did not find a match, but `tStylingKeyCursor` is `KeyValueArray` that means cursor has
25000
+ // statics and we need to check those as well.
25001
+ return keyValueArrayIndexOf(tStylingKeyCursor, tStylingKey) >= 0; // see if we are matching the key
26671
25002
  }
26672
- return ɵɵpropertyInterpolate5;
25003
+ return false;
26673
25004
  }
25005
+
25006
+ // Global state of the parser. (This makes parser non-reentrant, but that is not an issue)
25007
+ const parserState = {
25008
+ textEnd: 0,
25009
+ key: 0,
25010
+ keyEnd: 0,
25011
+ value: 0,
25012
+ valueEnd: 0,
25013
+ };
26674
25014
  /**
26675
- *
26676
- * Update an interpolated property on an element with 6 bound values surrounded by text.
26677
- *
26678
- * Used when the value passed to a property has 6 interpolated values in it:
26679
- *
26680
- * ```html
26681
- * <div title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}suffix"></div>
26682
- * ```
26683
- *
26684
- * Its compiled representation is::
26685
- *
26686
- * ```ts
26687
- * ɵɵpropertyInterpolate6(
26688
- * 'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, 'suffix');
26689
- * ```
26690
- *
26691
- * If the property name also exists as an input property on one of the element's directives,
26692
- * the component property will be set instead of the element property. This check must
26693
- * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.
26694
- *
26695
- * @param propName The name of the property to update
26696
- * @param prefix Static value used for concatenation only.
26697
- * @param v0 Value checked for change.
26698
- * @param i0 Static value used for concatenation only.
26699
- * @param v1 Value checked for change.
26700
- * @param i1 Static value used for concatenation only.
26701
- * @param v2 Value checked for change.
26702
- * @param i2 Static value used for concatenation only.
26703
- * @param v3 Value checked for change.
26704
- * @param i3 Static value used for concatenation only.
26705
- * @param v4 Value checked for change.
26706
- * @param i4 Static value used for concatenation only.
26707
- * @param v5 Value checked for change.
26708
- * @param suffix Static value used for concatenation only.
26709
- * @param sanitizer An optional sanitizer function
26710
- * @returns itself, so that it may be chained.
26711
- * @codeGenApi
25015
+ * Retrieves the last parsed `key` of style.
25016
+ * @param text the text to substring the key from.
26712
25017
  */
26713
- function ɵɵpropertyInterpolate6(propName, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix, sanitizer) {
26714
- const lView = getLView();
26715
- const interpolatedValue = interpolation6(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix);
26716
- if (interpolatedValue !== NO_CHANGE) {
26717
- const tView = getTView();
26718
- const tNode = getSelectedTNode();
26719
- setPropertyAndInputs(tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer);
26720
- ngDevMode &&
26721
- storePropertyBindingMetadata(tView.data, tNode, propName, getBindingIndex() - 6, prefix, i0, i1, i2, i3, i4, suffix ?? '');
26722
- }
26723
- return ɵɵpropertyInterpolate6;
25018
+ function getLastParsedKey(text) {
25019
+ return text.substring(parserState.key, parserState.keyEnd);
26724
25020
  }
26725
25021
  /**
26726
- *
26727
- * Update an interpolated property on an element with 7 bound values surrounded by text.
26728
- *
26729
- * Used when the value passed to a property has 7 interpolated values in it:
26730
- *
26731
- * ```html
26732
- * <div title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}suffix"></div>
26733
- * ```
26734
- *
26735
- * Its compiled representation is::
26736
- *
26737
- * ```ts
26738
- * ɵɵpropertyInterpolate7(
26739
- * 'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, 'suffix');
26740
- * ```
26741
- *
26742
- * If the property name also exists as an input property on one of the element's directives,
26743
- * the component property will be set instead of the element property. This check must
26744
- * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.
26745
- *
26746
- * @param propName The name of the property to update
26747
- * @param prefix Static value used for concatenation only.
26748
- * @param v0 Value checked for change.
26749
- * @param i0 Static value used for concatenation only.
26750
- * @param v1 Value checked for change.
26751
- * @param i1 Static value used for concatenation only.
26752
- * @param v2 Value checked for change.
26753
- * @param i2 Static value used for concatenation only.
26754
- * @param v3 Value checked for change.
26755
- * @param i3 Static value used for concatenation only.
26756
- * @param v4 Value checked for change.
26757
- * @param i4 Static value used for concatenation only.
26758
- * @param v5 Value checked for change.
26759
- * @param i5 Static value used for concatenation only.
26760
- * @param v6 Value checked for change.
26761
- * @param suffix Static value used for concatenation only.
26762
- * @param sanitizer An optional sanitizer function
26763
- * @returns itself, so that it may be chained.
26764
- * @codeGenApi
25022
+ * Retrieves the last parsed `value` of style.
25023
+ * @param text the text to substring the key from.
26765
25024
  */
26766
- function ɵɵpropertyInterpolate7(propName, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix, sanitizer) {
26767
- const lView = getLView();
26768
- const interpolatedValue = interpolation7(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix);
26769
- if (interpolatedValue !== NO_CHANGE) {
26770
- const tView = getTView();
26771
- const tNode = getSelectedTNode();
26772
- setPropertyAndInputs(tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer);
26773
- ngDevMode &&
26774
- storePropertyBindingMetadata(tView.data, tNode, propName, getBindingIndex() - 7, prefix, i0, i1, i2, i3, i4, i5, suffix ?? '');
26775
- }
26776
- return ɵɵpropertyInterpolate7;
25025
+ function getLastParsedValue(text) {
25026
+ return text.substring(parserState.value, parserState.valueEnd);
26777
25027
  }
26778
25028
  /**
25029
+ * Initializes `className` string for parsing and parses the first token.
26779
25030
  *
26780
- * Update an interpolated property on an element with 8 bound values surrounded by text.
26781
- *
26782
- * Used when the value passed to a property has 8 interpolated values in it:
26783
- *
26784
- * ```html
26785
- * <div title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}suffix"></div>
25031
+ * This function is intended to be used in this format:
25032
+ * ```ts
25033
+ * for (let i = parseClassName(text); i >= 0; i = parseClassNameNext(text, i)) {
25034
+ * const key = getLastParsedKey();
25035
+ * ...
25036
+ * }
26786
25037
  * ```
25038
+ * @param text `className` to parse
25039
+ * @returns index where the next invocation of `parseClassNameNext` should resume.
25040
+ */
25041
+ function parseClassName(text) {
25042
+ resetParserState(text);
25043
+ return parseClassNameNext(text, consumeWhitespace(text, 0, parserState.textEnd));
25044
+ }
25045
+ /**
25046
+ * Parses next `className` token.
26787
25047
  *
26788
- * Its compiled representation is::
26789
- *
25048
+ * This function is intended to be used in this format:
26790
25049
  * ```ts
26791
- * ɵɵpropertyInterpolate8(
26792
- * 'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, 'suffix');
25050
+ * for (let i = parseClassName(text); i >= 0; i = parseClassNameNext(text, i)) {
25051
+ * const key = getLastParsedKey();
25052
+ * ...
25053
+ * }
26793
25054
  * ```
26794
25055
  *
26795
- * If the property name also exists as an input property on one of the element's directives,
26796
- * the component property will be set instead of the element property. This check must
26797
- * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.
26798
- *
26799
- * @param propName The name of the property to update
26800
- * @param prefix Static value used for concatenation only.
26801
- * @param v0 Value checked for change.
26802
- * @param i0 Static value used for concatenation only.
26803
- * @param v1 Value checked for change.
26804
- * @param i1 Static value used for concatenation only.
26805
- * @param v2 Value checked for change.
26806
- * @param i2 Static value used for concatenation only.
26807
- * @param v3 Value checked for change.
26808
- * @param i3 Static value used for concatenation only.
26809
- * @param v4 Value checked for change.
26810
- * @param i4 Static value used for concatenation only.
26811
- * @param v5 Value checked for change.
26812
- * @param i5 Static value used for concatenation only.
26813
- * @param v6 Value checked for change.
26814
- * @param i6 Static value used for concatenation only.
26815
- * @param v7 Value checked for change.
26816
- * @param suffix Static value used for concatenation only.
26817
- * @param sanitizer An optional sanitizer function
26818
- * @returns itself, so that it may be chained.
26819
- * @codeGenApi
25056
+ * @param text `className` to parse
25057
+ * @param index where the parsing should resume.
25058
+ * @returns index where the next invocation of `parseClassNameNext` should resume.
26820
25059
  */
26821
- function ɵɵpropertyInterpolate8(propName, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix, sanitizer) {
26822
- const lView = getLView();
26823
- const interpolatedValue = interpolation8(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix);
26824
- if (interpolatedValue !== NO_CHANGE) {
26825
- const tView = getTView();
26826
- const tNode = getSelectedTNode();
26827
- setPropertyAndInputs(tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer);
26828
- ngDevMode &&
26829
- storePropertyBindingMetadata(tView.data, tNode, propName, getBindingIndex() - 8, prefix, i0, i1, i2, i3, i4, i5, i6, suffix ?? '');
25060
+ function parseClassNameNext(text, index) {
25061
+ const end = parserState.textEnd;
25062
+ if (end === index) {
25063
+ return -1;
26830
25064
  }
26831
- return ɵɵpropertyInterpolate8;
25065
+ index = parserState.keyEnd = consumeClassToken(text, (parserState.key = index), end);
25066
+ return consumeWhitespace(text, index, end);
26832
25067
  }
26833
25068
  /**
26834
- * Update an interpolated property on an element with 9 or more bound values surrounded by text.
26835
- *
26836
- * Used when the number of interpolated values exceeds 8.
26837
- *
26838
- * ```html
26839
- * <div
26840
- * title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}-{{v8}}-{{v9}}suffix"></div>
26841
- * ```
26842
- *
26843
- * Its compiled representation is::
25069
+ * Initializes `cssText` string for parsing and parses the first key/values.
26844
25070
  *
25071
+ * This function is intended to be used in this format:
26845
25072
  * ```ts
26846
- * ɵɵpropertyInterpolateV(
26847
- * 'title', ['prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, '-', v9,
26848
- * 'suffix']);
25073
+ * for (let i = parseStyle(text); i >= 0; i = parseStyleNext(text, i))) {
25074
+ * const key = getLastParsedKey();
25075
+ * const value = getLastParsedValue();
25076
+ * ...
25077
+ * }
26849
25078
  * ```
25079
+ * @param text `cssText` to parse
25080
+ * @returns index where the next invocation of `parseStyleNext` should resume.
25081
+ */
25082
+ function parseStyle(text) {
25083
+ resetParserState(text);
25084
+ return parseStyleNext(text, consumeWhitespace(text, 0, parserState.textEnd));
25085
+ }
25086
+ /**
25087
+ * Parses the next `cssText` key/values.
26850
25088
  *
26851
- * If the property name also exists as an input property on one of the element's directives,
26852
- * the component property will be set instead of the element property. This check must
26853
- * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.
25089
+ * This function is intended to be used in this format:
25090
+ * ```ts
25091
+ * for (let i = parseStyle(text); i >= 0; i = parseStyleNext(text, i))) {
25092
+ * const key = getLastParsedKey();
25093
+ * const value = getLastParsedValue();
25094
+ * ...
25095
+ * }
26854
25096
  *
26855
- * @param propName The name of the property to update.
26856
- * @param values The collection of values and the strings in between those values, beginning with a
26857
- * string prefix and ending with a string suffix.
26858
- * (e.g. `['prefix', value0, '-', value1, '-', value2, ..., value99, 'suffix']`)
26859
- * @param sanitizer An optional sanitizer function
26860
- * @returns itself, so that it may be chained.
26861
- * @codeGenApi
25097
+ * @param text `cssText` to parse
25098
+ * @param index where the parsing should resume.
25099
+ * @returns index where the next invocation of `parseStyleNext` should resume.
26862
25100
  */
26863
- function ɵɵpropertyInterpolateV(propName, values, sanitizer) {
26864
- const lView = getLView();
26865
- const interpolatedValue = interpolationV(lView, values);
26866
- if (interpolatedValue !== NO_CHANGE) {
26867
- const tView = getTView();
26868
- const tNode = getSelectedTNode();
26869
- setPropertyAndInputs(tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer);
26870
- if (ngDevMode) {
26871
- const interpolationInBetween = [values[0]]; // prefix
26872
- for (let i = 2; i < values.length; i += 2) {
26873
- interpolationInBetween.push(values[i]);
26874
- }
26875
- storePropertyBindingMetadata(tView.data, tNode, propName, getBindingIndex() - interpolationInBetween.length + 1, ...interpolationInBetween);
26876
- }
25101
+ function parseStyleNext(text, startIndex) {
25102
+ const end = parserState.textEnd;
25103
+ let index = (parserState.key = consumeWhitespace(text, startIndex, end));
25104
+ if (end === index) {
25105
+ // we reached an end so just quit
25106
+ return -1;
26877
25107
  }
26878
- return ɵɵpropertyInterpolateV;
25108
+ index = parserState.keyEnd = consumeStyleKey(text, index, end);
25109
+ index = consumeSeparator(text, index, end, 58 /* CharCode.COLON */);
25110
+ index = parserState.value = consumeWhitespace(text, index, end);
25111
+ index = parserState.valueEnd = consumeStyleValue(text, index, end);
25112
+ return consumeSeparator(text, index, end, 59 /* CharCode.SEMI_COLON */);
26879
25113
  }
26880
-
26881
25114
  /**
26882
- * Registers a QueryList, associated with a content query, for later refresh (part of a view
26883
- * refresh).
26884
- *
26885
- * @param directiveIndex Current directive index
26886
- * @param predicate The type for which the query will search
26887
- * @param flags Flags associated with the query
26888
- * @param read What to save in the query
26889
- * @returns QueryList<T>
25115
+ * Reset the global state of the styling parser.
25116
+ * @param text The styling text to parse.
25117
+ */
25118
+ function resetParserState(text) {
25119
+ parserState.key = 0;
25120
+ parserState.keyEnd = 0;
25121
+ parserState.value = 0;
25122
+ parserState.valueEnd = 0;
25123
+ parserState.textEnd = text.length;
25124
+ }
25125
+ /**
25126
+ * Returns index of next non-whitespace character.
26890
25127
  *
26891
- * @codeGenApi
25128
+ * @param text Text to scan
25129
+ * @param startIndex Starting index of character where the scan should start.
25130
+ * @param endIndex Ending index of character where the scan should end.
25131
+ * @returns Index of next non-whitespace character (May be the same as `start` if no whitespace at
25132
+ * that location.)
26892
25133
  */
26893
- function ɵɵcontentQuery(directiveIndex, predicate, flags, read) {
26894
- createContentQuery(directiveIndex, predicate, flags, read);
25134
+ function consumeWhitespace(text, startIndex, endIndex) {
25135
+ while (startIndex < endIndex && text.charCodeAt(startIndex) <= 32 /* CharCode.SPACE */) {
25136
+ startIndex++;
25137
+ }
25138
+ return startIndex;
26895
25139
  }
26896
25140
  /**
26897
- * Creates a new view query by initializing internal data structures.
25141
+ * Returns index of last char in class token.
26898
25142
  *
26899
- * @param predicate The type for which the query will search
26900
- * @param flags Flags associated with the query
26901
- * @param read What to save in the query
25143
+ * @param text Text to scan
25144
+ * @param startIndex Starting index of character where the scan should start.
25145
+ * @param endIndex Ending index of character where the scan should end.
25146
+ * @returns Index after last char in class token.
25147
+ */
25148
+ function consumeClassToken(text, startIndex, endIndex) {
25149
+ while (startIndex < endIndex && text.charCodeAt(startIndex) > 32 /* CharCode.SPACE */) {
25150
+ startIndex++;
25151
+ }
25152
+ return startIndex;
25153
+ }
25154
+ /**
25155
+ * Consumes all of the characters belonging to style key and token.
26902
25156
  *
26903
- * @codeGenApi
25157
+ * @param text Text to scan
25158
+ * @param startIndex Starting index of character where the scan should start.
25159
+ * @param endIndex Ending index of character where the scan should end.
25160
+ * @returns Index after last style key character.
26904
25161
  */
26905
- function ɵɵviewQuery(predicate, flags, read) {
26906
- createViewQuery(predicate, flags, read);
25162
+ function consumeStyleKey(text, startIndex, endIndex) {
25163
+ let ch;
25164
+ while (startIndex < endIndex &&
25165
+ ((ch = text.charCodeAt(startIndex)) === 45 /* CharCode.DASH */ ||
25166
+ ch === 95 /* CharCode.UNDERSCORE */ ||
25167
+ ((ch & -33 /* CharCode.UPPER_CASE */) >= 65 /* CharCode.A */ && (ch & -33 /* CharCode.UPPER_CASE */) <= 90 /* CharCode.Z */) ||
25168
+ (ch >= 48 /* CharCode.ZERO */ && ch <= 57 /* CharCode.NINE */))) {
25169
+ startIndex++;
25170
+ }
25171
+ return startIndex;
26907
25172
  }
26908
25173
  /**
26909
- * Refreshes a query by combining matches from all active views and removing matches from deleted
26910
- * views.
25174
+ * Consumes all whitespace and the separator `:` after the style key.
26911
25175
  *
26912
- * @returns `true` if a query got dirty during change detection or if this is a static query
26913
- * resolving in creation mode, `false` otherwise.
25176
+ * @param text Text to scan
25177
+ * @param startIndex Starting index of character where the scan should start.
25178
+ * @param endIndex Ending index of character where the scan should end.
25179
+ * @returns Index after separator and surrounding whitespace.
25180
+ */
25181
+ function consumeSeparator(text, startIndex, endIndex, separator) {
25182
+ startIndex = consumeWhitespace(text, startIndex, endIndex);
25183
+ if (startIndex < endIndex) {
25184
+ if (ngDevMode && text.charCodeAt(startIndex) !== separator) {
25185
+ malformedStyleError(text, String.fromCharCode(separator), startIndex);
25186
+ }
25187
+ startIndex++;
25188
+ }
25189
+ return startIndex;
25190
+ }
25191
+ /**
25192
+ * Consumes style value honoring `url()` and `""` text.
26914
25193
  *
26915
- * @codeGenApi
25194
+ * @param text Text to scan
25195
+ * @param startIndex Starting index of character where the scan should start.
25196
+ * @param endIndex Ending index of character where the scan should end.
25197
+ * @returns Index after last style value character.
26916
25198
  */
26917
- function ɵɵqueryRefresh(queryList) {
26918
- const lView = getLView();
26919
- const tView = getTView();
26920
- const queryIndex = getCurrentQueryIndex();
26921
- setCurrentQueryIndex(queryIndex + 1);
26922
- const tQuery = getTQuery(tView, queryIndex);
26923
- if (queryList.dirty &&
26924
- isCreationMode(lView) ===
26925
- ((tQuery.metadata.flags & 2 /* QueryFlags.isStatic */) === 2 /* QueryFlags.isStatic */)) {
26926
- if (tQuery.matches === null) {
26927
- queryList.reset([]);
25199
+ function consumeStyleValue(text, startIndex, endIndex) {
25200
+ let ch1 = -1; // 1st previous character
25201
+ let ch2 = -1; // 2nd previous character
25202
+ let ch3 = -1; // 3rd previous character
25203
+ let i = startIndex;
25204
+ let lastChIndex = i;
25205
+ while (i < endIndex) {
25206
+ const ch = text.charCodeAt(i++);
25207
+ if (ch === 59 /* CharCode.SEMI_COLON */) {
25208
+ return lastChIndex;
26928
25209
  }
26929
- else {
26930
- const result = getQueryResults(lView, queryIndex);
26931
- queryList.reset(result, unwrapElementRef);
26932
- queryList.notifyOnChanges();
25210
+ else if (ch === 34 /* CharCode.DOUBLE_QUOTE */ || ch === 39 /* CharCode.SINGLE_QUOTE */) {
25211
+ lastChIndex = i = consumeQuotedText(text, ch, i, endIndex);
25212
+ }
25213
+ else if (startIndex === i - 4 && // We have seen only 4 characters so far "URL(" (Ignore "foo_URL()")
25214
+ ch3 === 85 /* CharCode.U */ &&
25215
+ ch2 === 82 /* CharCode.R */ &&
25216
+ ch1 === 76 /* CharCode.L */ &&
25217
+ ch === 40 /* CharCode.OPEN_PAREN */) {
25218
+ lastChIndex = i = consumeQuotedText(text, 41 /* CharCode.CLOSE_PAREN */, i, endIndex);
25219
+ }
25220
+ else if (ch > 32 /* CharCode.SPACE */) {
25221
+ // if we have a non-whitespace character then capture its location
25222
+ lastChIndex = i;
26933
25223
  }
26934
- return true;
25224
+ ch3 = ch2;
25225
+ ch2 = ch1;
25226
+ ch1 = ch & -33 /* CharCode.UPPER_CASE */;
26935
25227
  }
26936
- return false;
25228
+ return lastChIndex;
26937
25229
  }
26938
25230
  /**
26939
- * Loads a QueryList corresponding to the current view or content query.
25231
+ * Consumes all of the quoted characters.
26940
25232
  *
26941
- * @codeGenApi
25233
+ * @param text Text to scan
25234
+ * @param quoteCharCode CharCode of either `"` or `'` quote or `)` for `url(...)`.
25235
+ * @param startIndex Starting index of character where the scan should start.
25236
+ * @param endIndex Ending index of character where the scan should end.
25237
+ * @returns Index after quoted characters.
26942
25238
  */
26943
- function ɵɵloadQuery() {
26944
- return loadQueryInternal(getLView(), getCurrentQueryIndex());
25239
+ function consumeQuotedText(text, quoteCharCode, startIndex, endIndex) {
25240
+ let ch1 = -1; // 1st previous character
25241
+ let index = startIndex;
25242
+ while (index < endIndex) {
25243
+ const ch = text.charCodeAt(index++);
25244
+ if (ch == quoteCharCode && ch1 !== 92 /* CharCode.BACK_SLASH */) {
25245
+ return index;
25246
+ }
25247
+ if (ch == 92 /* CharCode.BACK_SLASH */ && ch1 === 92 /* CharCode.BACK_SLASH */) {
25248
+ // two back slashes cancel each other out. For example `"\\"` should properly end the
25249
+ // quotation. (It should not assume that the last `"` is escaped.)
25250
+ ch1 = 0;
25251
+ }
25252
+ else {
25253
+ ch1 = ch;
25254
+ }
25255
+ }
25256
+ throw ngDevMode
25257
+ ? malformedStyleError(text, String.fromCharCode(quoteCharCode), endIndex)
25258
+ : new Error();
26945
25259
  }
26946
-
26947
- /**
26948
- * Creates a new content query and binds it to a signal created by an authoring function.
26949
- *
26950
- * @param directiveIndex Current directive index
26951
- * @param target The target signal to which the query should be bound
26952
- * @param predicate The type for which the query will search
26953
- * @param flags Flags associated with the query
26954
- * @param read What to save in the query
26955
- *
26956
- * @codeGenApi
26957
- */
26958
- function ɵɵcontentQuerySignal(directiveIndex, target, predicate, flags, read) {
26959
- bindQueryToSignal(target, createContentQuery(directiveIndex, predicate, flags, read));
25260
+ function malformedStyleError(text, expecting, index) {
25261
+ ngDevMode && assertEqual(typeof text === 'string', true, 'String expected here');
25262
+ throw throwError(`Malformed style at location ${index} in string '` +
25263
+ text.substring(0, index) +
25264
+ '[>>' +
25265
+ text.substring(index, index + 1) +
25266
+ '<<]' +
25267
+ text.slice(index + 1) +
25268
+ `'. Expecting '${expecting}'.`);
26960
25269
  }
25270
+
26961
25271
  /**
26962
- * Creates a new view query by initializing internal data structures and binding a new query to the
26963
- * target signal.
25272
+ * Update a style binding on an element with the provided value.
26964
25273
  *
26965
- * @param target The target signal to assign the query results to.
26966
- * @param predicate The type or label that should match a given query
26967
- * @param flags Flags associated with the query
26968
- * @param read What to save in the query
25274
+ * If the style value is falsy then it will be removed from the element
25275
+ * (or assigned a different value depending if there are any styles placed
25276
+ * on the element with `styleMap` or any static styles that are
25277
+ * present from when the element was created with `styling`).
26969
25278
  *
26970
- * @codeGenApi
26971
- */
26972
- function ɵɵviewQuerySignal(target, predicate, flags, read) {
26973
- bindQueryToSignal(target, createViewQuery(predicate, flags, read));
26974
- }
26975
- /**
26976
- * Advances the current query index by a specified offset.
25279
+ * Note that the styling element is updated as part of `stylingApply`.
26977
25280
  *
26978
- * Adjusting the current query index is necessary in cases where a given directive has a mix of
26979
- * zone-based and signal-based queries. The signal-based queries don't require tracking of the
26980
- * current index (those are refreshed on demand and not during change detection) so this instruction
26981
- * is only necessary for backward-compatibility.
25281
+ * @param prop A valid CSS property.
25282
+ * @param value New value to write (`null` or an empty string to remove).
25283
+ * @param suffix Optional suffix. Used with scalar values to add unit such as `px`.
26982
25284
  *
26983
- * @param index offset to apply to the current query index (defaults to 1)
25285
+ * Note that this will apply the provided style value to the host element if this function is called
25286
+ * within a host binding function.
26984
25287
  *
26985
25288
  * @codeGenApi
26986
25289
  */
26987
- function ɵɵqueryAdvance(indexOffset = 1) {
26988
- setCurrentQueryIndex(getCurrentQueryIndex() + indexOffset);
25290
+ function ɵɵstyleProp(prop, value, suffix) {
25291
+ checkStylingProperty(prop, value, suffix, false);
25292
+ return ɵɵstyleProp;
26989
25293
  }
26990
-
26991
25294
  /**
26992
- * Retrieves a local reference from the current contextViewData.
25295
+ * Update a class binding on an element with the provided value.
26993
25296
  *
26994
- * If the reference to retrieve is in a parent view, this instruction is used in conjunction
26995
- * with a nextContext() call, which walks up the tree and updates the contextViewData instance.
25297
+ * This instruction is meant to handle the `[class.foo]="exp"` case and,
25298
+ * therefore, the class binding itself must already be allocated using
25299
+ * `styling` within the creation block.
26996
25300
  *
26997
- * @param index The index of the local ref in contextViewData.
25301
+ * @param prop A valid CSS class (only one).
25302
+ * @param value A true/false value which will turn the class on or off.
25303
+ *
25304
+ * Note that this will apply the provided class value to the host element if this function
25305
+ * is called within a host binding function.
26998
25306
  *
26999
25307
  * @codeGenApi
27000
25308
  */
27001
- function ɵɵreference(index) {
27002
- const contextLView = getContextLView();
27003
- return load(contextLView, HEADER_OFFSET + index);
25309
+ function ɵɵclassProp(className, value) {
25310
+ checkStylingProperty(className, value, null, true);
25311
+ return ɵɵclassProp;
27004
25312
  }
27005
-
27006
25313
  /**
25314
+ * Update style bindings using an object literal on an element.
27007
25315
  *
27008
- * Update an interpolated style on an element with single bound value surrounded by text.
27009
- *
27010
- * Used when the value passed to a property has 1 interpolated value in it:
25316
+ * This instruction is meant to apply styling via the `[style]="exp"` template bindings.
25317
+ * When styles are applied to the element they will then be updated with respect to
25318
+ * any styles/classes set via `styleProp`. If any styles are set to falsy
25319
+ * then they will be removed from the element.
27011
25320
  *
27012
- * ```html
27013
- * <div style="key: {{v0}}suffix"></div>
27014
- * ```
25321
+ * Note that the styling instruction will not be applied until `stylingApply` is called.
27015
25322
  *
27016
- * Its compiled representation is:
25323
+ * @param styles A key/value style map of the styles that will be applied to the given element.
25324
+ * Any missing styles (that have already been applied to the element beforehand) will be
25325
+ * removed (unset) from the element's styling.
27017
25326
  *
27018
- * ```ts
27019
- * ɵɵstyleMapInterpolate1('key: ', v0, 'suffix');
27020
- * ```
25327
+ * Note that this will apply the provided styleMap value to the host element if this function
25328
+ * is called within a host binding.
27021
25329
  *
27022
- * @param prefix Static value used for concatenation only.
27023
- * @param v0 Value checked for change.
27024
- * @param suffix Static value used for concatenation only.
27025
25330
  * @codeGenApi
27026
25331
  */
27027
- function ɵɵstyleMapInterpolate1(prefix, v0, suffix) {
27028
- const lView = getLView();
27029
- const interpolatedValue = interpolation1(lView, prefix, v0, suffix);
27030
- ɵɵstyleMap(interpolatedValue);
25332
+ function ɵɵstyleMap(styles) {
25333
+ checkStylingMap(styleKeyValueArraySet, styleStringParser, styles, false);
27031
25334
  }
27032
25335
  /**
25336
+ * Parse text as style and add values to KeyValueArray.
27033
25337
  *
27034
- * Update an interpolated style on an element with 2 bound values surrounded by text.
27035
- *
27036
- * Used when the value passed to a property has 2 interpolated values in it:
27037
- *
27038
- * ```html
27039
- * <div style="key: {{v0}}; key1: {{v1}}suffix"></div>
27040
- * ```
27041
- *
27042
- * Its compiled representation is:
27043
- *
27044
- * ```ts
27045
- * ɵɵstyleMapInterpolate2('key: ', v0, '; key1: ', v1, 'suffix');
27046
- * ```
25338
+ * This code is pulled out to a separate function so that it can be tree shaken away if it is not
25339
+ * needed. It is only referenced from `ɵɵstyleMap`.
27047
25340
  *
27048
- * @param prefix Static value used for concatenation only.
27049
- * @param v0 Value checked for change.
27050
- * @param i0 Static value used for concatenation only.
27051
- * @param v1 Value checked for change.
27052
- * @param suffix Static value used for concatenation only.
27053
- * @codeGenApi
25341
+ * @param keyValueArray KeyValueArray to add parsed values to.
25342
+ * @param text text to parse.
27054
25343
  */
27055
- function ɵɵstyleMapInterpolate2(prefix, v0, i0, v1, suffix) {
27056
- const lView = getLView();
27057
- const interpolatedValue = interpolation2(lView, prefix, v0, i0, v1, suffix);
27058
- ɵɵstyleMap(interpolatedValue);
25344
+ function styleStringParser(keyValueArray, text) {
25345
+ for (let i = parseStyle(text); i >= 0; i = parseStyleNext(text, i)) {
25346
+ styleKeyValueArraySet(keyValueArray, getLastParsedKey(text), getLastParsedValue(text));
25347
+ }
27059
25348
  }
27060
25349
  /**
25350
+ * Update class bindings using an object literal or class-string on an element.
27061
25351
  *
27062
- * Update an interpolated style on an element with 3 bound values surrounded by text.
27063
- *
27064
- * Used when the value passed to a property has 3 interpolated values in it:
27065
- *
27066
- * ```html
27067
- * <div style="key: {{v0}}; key2: {{v1}}; key2: {{v2}}suffix"></div>
27068
- * ```
25352
+ * This instruction is meant to apply styling via the `[class]="exp"` template bindings.
25353
+ * When classes are applied to the element they will then be updated with
25354
+ * respect to any styles/classes set via `classProp`. If any
25355
+ * classes are set to falsy then they will be removed from the element.
27069
25356
  *
27070
- * Its compiled representation is:
25357
+ * Note that the styling instruction will not be applied until `stylingApply` is called.
25358
+ * Note that this will the provided classMap value to the host element if this function is called
25359
+ * within a host binding.
27071
25360
  *
27072
- * ```ts
27073
- * ɵɵstyleMapInterpolate3(
27074
- * 'key: ', v0, '; key1: ', v1, '; key2: ', v2, 'suffix');
27075
- * ```
25361
+ * @param classes A key/value map or string of CSS classes that will be added to the
25362
+ * given element. Any missing classes (that have already been applied to the element
25363
+ * beforehand) will be removed (unset) from the element's list of CSS classes.
27076
25364
  *
27077
- * @param prefix Static value used for concatenation only.
27078
- * @param v0 Value checked for change.
27079
- * @param i0 Static value used for concatenation only.
27080
- * @param v1 Value checked for change.
27081
- * @param i1 Static value used for concatenation only.
27082
- * @param v2 Value checked for change.
27083
- * @param suffix Static value used for concatenation only.
27084
25365
  * @codeGenApi
27085
25366
  */
27086
- function ɵɵstyleMapInterpolate3(prefix, v0, i0, v1, i1, v2, suffix) {
27087
- const lView = getLView();
27088
- const interpolatedValue = interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix);
27089
- ɵɵstyleMap(interpolatedValue);
25367
+ function ɵɵclassMap(classes) {
25368
+ checkStylingMap(classKeyValueArraySet, classStringParser, classes, true);
27090
25369
  }
27091
25370
  /**
25371
+ * Parse text as class and add values to KeyValueArray.
27092
25372
  *
27093
- * Update an interpolated style on an element with 4 bound values surrounded by text.
27094
- *
27095
- * Used when the value passed to a property has 4 interpolated values in it:
27096
- *
27097
- * ```html
27098
- * <div style="key: {{v0}}; key1: {{v1}}; key2: {{v2}}; key3: {{v3}}suffix"></div>
27099
- * ```
27100
- *
27101
- * Its compiled representation is:
27102
- *
27103
- * ```ts
27104
- * ɵɵstyleMapInterpolate4(
27105
- * 'key: ', v0, '; key1: ', v1, '; key2: ', v2, '; key3: ', v3, 'suffix');
27106
- * ```
25373
+ * This code is pulled out to a separate function so that it can be tree shaken away if it is not
25374
+ * needed. It is only referenced from `ɵɵclassMap`.
27107
25375
  *
27108
- * @param prefix Static value used for concatenation only.
27109
- * @param v0 Value checked for change.
27110
- * @param i0 Static value used for concatenation only.
27111
- * @param v1 Value checked for change.
27112
- * @param i1 Static value used for concatenation only.
27113
- * @param v2 Value checked for change.
27114
- * @param i2 Static value used for concatenation only.
27115
- * @param v3 Value checked for change.
27116
- * @param suffix Static value used for concatenation only.
27117
- * @codeGenApi
25376
+ * @param keyValueArray KeyValueArray to add parsed values to.
25377
+ * @param text text to parse.
27118
25378
  */
27119
- function ɵɵstyleMapInterpolate4(prefix, v0, i0, v1, i1, v2, i2, v3, suffix) {
27120
- const lView = getLView();
27121
- const interpolatedValue = interpolation4(lView, prefix, v0, i0, v1, i1, v2, i2, v3, suffix);
27122
- ɵɵstyleMap(interpolatedValue);
25379
+ function classStringParser(keyValueArray, text) {
25380
+ for (let i = parseClassName(text); i >= 0; i = parseClassNameNext(text, i)) {
25381
+ keyValueArraySet(keyValueArray, getLastParsedKey(text), true);
25382
+ }
27123
25383
  }
27124
25384
  /**
25385
+ * Common code between `ɵɵclassProp` and `ɵɵstyleProp`.
27125
25386
  *
27126
- * Update an interpolated style on an element with 5 bound values surrounded by text.
27127
- *
27128
- * Used when the value passed to a property has 5 interpolated values in it:
27129
- *
27130
- * ```html
27131
- * <div style="key: {{v0}}; key1: {{v1}}; key2: {{v2}}; key3: {{v3}}; key4: {{v4}}suffix"></div>
27132
- * ```
27133
- *
27134
- * Its compiled representation is:
27135
- *
27136
- * ```ts
27137
- * ɵɵstyleMapInterpolate5(
27138
- * 'key: ', v0, '; key1: ', v1, '; key2: ', v2, '; key3: ', v3, '; key4: ', v4, 'suffix');
27139
- * ```
27140
- *
27141
- * @param prefix Static value used for concatenation only.
27142
- * @param v0 Value checked for change.
27143
- * @param i0 Static value used for concatenation only.
27144
- * @param v1 Value checked for change.
27145
- * @param i1 Static value used for concatenation only.
27146
- * @param v2 Value checked for change.
27147
- * @param i2 Static value used for concatenation only.
27148
- * @param v3 Value checked for change.
27149
- * @param i3 Static value used for concatenation only.
27150
- * @param v4 Value checked for change.
27151
- * @param suffix Static value used for concatenation only.
27152
- * @codeGenApi
25387
+ * @param prop property name.
25388
+ * @param value binding value.
25389
+ * @param suffix suffix for the property (e.g. `em` or `px`)
25390
+ * @param isClassBased `true` if `class` change (`false` if `style`)
27153
25391
  */
27154
- function ɵɵstyleMapInterpolate5(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix) {
25392
+ function checkStylingProperty(prop, value, suffix, isClassBased) {
27155
25393
  const lView = getLView();
27156
- const interpolatedValue = interpolation5(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix);
27157
- ɵɵstyleMap(interpolatedValue);
25394
+ const tView = getTView();
25395
+ // Styling instructions use 2 slots per binding.
25396
+ // 1. one for the value / TStylingKey
25397
+ // 2. one for the intermittent-value / TStylingRange
25398
+ const bindingIndex = incrementBindingIndex(2);
25399
+ if (tView.firstUpdatePass) {
25400
+ stylingFirstUpdatePass(tView, prop, bindingIndex, isClassBased);
25401
+ }
25402
+ if (value !== NO_CHANGE && bindingUpdated(lView, bindingIndex, value)) {
25403
+ const tNode = tView.data[getSelectedIndex()];
25404
+ updateStyling(tView, tNode, lView, lView[RENDERER], prop, (lView[bindingIndex + 1] = normalizeSuffix(value, suffix)), isClassBased, bindingIndex);
25405
+ }
27158
25406
  }
27159
25407
  /**
25408
+ * Common code between `ɵɵclassMap` and `ɵɵstyleMap`.
27160
25409
  *
27161
- * Update an interpolated style on an element with 6 bound values surrounded by text.
27162
- *
27163
- * Used when the value passed to a property has 6 interpolated values in it:
27164
- *
27165
- * ```html
27166
- * <div style="key: {{v0}}; key1: {{v1}}; key2: {{v2}}; key3: {{v3}}; key4: {{v4}};
27167
- * key5: {{v5}}suffix"></div>
27168
- * ```
27169
- *
27170
- * Its compiled representation is:
27171
- *
27172
- * ```ts
27173
- * ɵɵstyleMapInterpolate6(
27174
- * 'key: ', v0, '; key1: ', v1, '; key2: ', v2, '; key3: ', v3, '; key4: ', v4, '; key5: ', v5,
27175
- * 'suffix');
27176
- * ```
27177
- *
27178
- * @param prefix Static value used for concatenation only.
27179
- * @param v0 Value checked for change.
27180
- * @param i0 Static value used for concatenation only.
27181
- * @param v1 Value checked for change.
27182
- * @param i1 Static value used for concatenation only.
27183
- * @param v2 Value checked for change.
27184
- * @param i2 Static value used for concatenation only.
27185
- * @param v3 Value checked for change.
27186
- * @param i3 Static value used for concatenation only.
27187
- * @param v4 Value checked for change.
27188
- * @param i4 Static value used for concatenation only.
27189
- * @param v5 Value checked for change.
27190
- * @param suffix Static value used for concatenation only.
27191
- * @codeGenApi
25410
+ * @param keyValueArraySet (See `keyValueArraySet` in "util/array_utils") Gets passed in as a
25411
+ * function so that `style` can be processed. This is done for tree shaking purposes.
25412
+ * @param stringParser Parser used to parse `value` if `string`. (Passed in as `style` and `class`
25413
+ * have different parsers.)
25414
+ * @param value bound value from application
25415
+ * @param isClassBased `true` if `class` change (`false` if `style`)
27192
25416
  */
27193
- function ɵɵstyleMapInterpolate6(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix) {
25417
+ function checkStylingMap(keyValueArraySet, stringParser, value, isClassBased) {
25418
+ const tView = getTView();
25419
+ const bindingIndex = incrementBindingIndex(2);
25420
+ if (tView.firstUpdatePass) {
25421
+ stylingFirstUpdatePass(tView, null, bindingIndex, isClassBased);
25422
+ }
27194
25423
  const lView = getLView();
27195
- const interpolatedValue = interpolation6(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix);
27196
- ɵɵstyleMap(interpolatedValue);
25424
+ if (value !== NO_CHANGE && bindingUpdated(lView, bindingIndex, value)) {
25425
+ // `getSelectedIndex()` should be here (rather than in instruction) so that it is guarded by the
25426
+ // if so as not to read unnecessarily.
25427
+ const tNode = tView.data[getSelectedIndex()];
25428
+ if (hasStylingInputShadow(tNode, isClassBased) && !isInHostBindings(tView, bindingIndex)) {
25429
+ if (ngDevMode) {
25430
+ // verify that if we are shadowing then `TData` is appropriately marked so that we skip
25431
+ // processing this binding in styling resolution.
25432
+ const tStylingKey = tView.data[bindingIndex];
25433
+ assertEqual(Array.isArray(tStylingKey) ? tStylingKey[1] : tStylingKey, false, "Styling linked list shadow input should be marked as 'false'");
25434
+ }
25435
+ // VE does not concatenate the static portion like we are doing here.
25436
+ // Instead VE just ignores the static completely if dynamic binding is present.
25437
+ // Because of locality we have already set the static portion because we don't know if there
25438
+ // is a dynamic portion until later. If we would ignore the static portion it would look like
25439
+ // the binding has removed it. This would confuse `[ngStyle]`/`[ngClass]` to do the wrong
25440
+ // thing as it would think that the static portion was removed. For this reason we
25441
+ // concatenate it so that `[ngStyle]`/`[ngClass]` can continue to work on changed.
25442
+ let staticPrefix = isClassBased ? tNode.classesWithoutHost : tNode.stylesWithoutHost;
25443
+ ngDevMode &&
25444
+ isClassBased === false &&
25445
+ staticPrefix !== null &&
25446
+ assertEqual(staticPrefix.endsWith(';'), true, "Expecting static portion to end with ';'");
25447
+ if (staticPrefix !== null) {
25448
+ // We want to make sure that falsy values of `value` become empty strings.
25449
+ value = concatStringsWithSpace(staticPrefix, value ? value : '');
25450
+ }
25451
+ // Given `<div [style] my-dir>` such that `my-dir` has `@Input('style')`.
25452
+ // This takes over the `[style]` binding. (Same for `[class]`)
25453
+ setDirectiveInputsWhichShadowsStyling(tView, tNode, lView, value, isClassBased);
25454
+ }
25455
+ else {
25456
+ updateStylingMap(tView, tNode, lView, lView[RENDERER], lView[bindingIndex + 1], (lView[bindingIndex + 1] = toStylingKeyValueArray(keyValueArraySet, stringParser, value)), isClassBased, bindingIndex);
25457
+ }
25458
+ }
27197
25459
  }
27198
25460
  /**
25461
+ * Determines when the binding is in `hostBindings` section
27199
25462
  *
27200
- * Update an interpolated style on an element with 7 bound values surrounded by text.
27201
- *
27202
- * Used when the value passed to a property has 7 interpolated values in it:
27203
- *
27204
- * ```html
27205
- * <div style="key: {{v0}}; key1: {{v1}}; key2: {{v2}}; key3: {{v3}}; key4: {{v4}}; key5: {{v5}};
27206
- * key6: {{v6}}suffix"></div>
27207
- * ```
27208
- *
27209
- * Its compiled representation is:
27210
- *
27211
- * ```ts
27212
- * ɵɵstyleMapInterpolate7(
27213
- * 'key: ', v0, '; key1: ', v1, '; key2: ', v2, '; key3: ', v3, '; key4: ', v4, '; key5: ', v5,
27214
- * '; key6: ', v6, 'suffix');
27215
- * ```
27216
- *
27217
- * @param prefix Static value used for concatenation only.
27218
- * @param v0 Value checked for change.
27219
- * @param i0 Static value used for concatenation only.
27220
- * @param v1 Value checked for change.
27221
- * @param i1 Static value used for concatenation only.
27222
- * @param v2 Value checked for change.
27223
- * @param i2 Static value used for concatenation only.
27224
- * @param v3 Value checked for change.
27225
- * @param i3 Static value used for concatenation only.
27226
- * @param v4 Value checked for change.
27227
- * @param i4 Static value used for concatenation only.
27228
- * @param v5 Value checked for change.
27229
- * @param i5 Static value used for concatenation only.
27230
- * @param v6 Value checked for change.
27231
- * @param suffix Static value used for concatenation only.
27232
- * @codeGenApi
25463
+ * @param tView Current `TView`
25464
+ * @param bindingIndex index of binding which we would like if it is in `hostBindings`
27233
25465
  */
27234
- function ɵɵstyleMapInterpolate7(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix) {
27235
- const lView = getLView();
27236
- const interpolatedValue = interpolation7(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix);
27237
- ɵɵstyleMap(interpolatedValue);
25466
+ function isInHostBindings(tView, bindingIndex) {
25467
+ // All host bindings are placed after the expando section.
25468
+ return bindingIndex >= tView.expandoStartIndex;
27238
25469
  }
27239
25470
  /**
25471
+ * Collects the necessary information to insert the binding into a linked list of style bindings
25472
+ * using `insertTStylingBinding`.
27240
25473
  *
27241
- * Update an interpolated style on an element with 8 bound values surrounded by text.
27242
- *
27243
- * Used when the value passed to a property has 8 interpolated values in it:
27244
- *
27245
- * ```html
27246
- * <div style="key: {{v0}}; key1: {{v1}}; key2: {{v2}}; key3: {{v3}}; key4: {{v4}}; key5: {{v5}};
27247
- * key6: {{v6}}; key7: {{v7}}suffix"></div>
27248
- * ```
25474
+ * @param tView `TView` where the binding linked list will be stored.
25475
+ * @param tStylingKey Property/key of the binding.
25476
+ * @param bindingIndex Index of binding associated with the `prop`
25477
+ * @param isClassBased `true` if `class` change (`false` if `style`)
25478
+ */
25479
+ function stylingFirstUpdatePass(tView, tStylingKey, bindingIndex, isClassBased) {
25480
+ ngDevMode && assertFirstUpdatePass(tView);
25481
+ const tData = tView.data;
25482
+ if (tData[bindingIndex + 1] === null) {
25483
+ // The above check is necessary because we don't clear first update pass until first successful
25484
+ // (no exception) template execution. This prevents the styling instruction from double adding
25485
+ // itself to the list.
25486
+ // `getSelectedIndex()` should be here (rather than in instruction) so that it is guarded by the
25487
+ // if so as not to read unnecessarily.
25488
+ const tNode = tData[getSelectedIndex()];
25489
+ ngDevMode && assertDefined(tNode, 'TNode expected');
25490
+ const isHostBindings = isInHostBindings(tView, bindingIndex);
25491
+ if (hasStylingInputShadow(tNode, isClassBased) && tStylingKey === null && !isHostBindings) {
25492
+ // `tStylingKey === null` implies that we are either `[style]` or `[class]` binding.
25493
+ // If there is a directive which uses `@Input('style')` or `@Input('class')` than
25494
+ // we need to neutralize this binding since that directive is shadowing it.
25495
+ // We turn this into a noop by setting the key to `false`
25496
+ tStylingKey = false;
25497
+ }
25498
+ tStylingKey = wrapInStaticStylingKey(tData, tNode, tStylingKey, isClassBased);
25499
+ insertTStylingBinding(tData, tNode, tStylingKey, bindingIndex, isHostBindings, isClassBased);
25500
+ }
25501
+ }
25502
+ /**
25503
+ * Adds static styling information to the binding if applicable.
27249
25504
  *
27250
- * Its compiled representation is:
25505
+ * The linked list of styles not only stores the list and keys, but also stores static styling
25506
+ * information on some of the keys. This function determines if the key should contain the styling
25507
+ * information and computes it.
27251
25508
  *
27252
- * ```ts
27253
- * ɵɵstyleMapInterpolate8(
27254
- * 'key: ', v0, '; key1: ', v1, '; key2: ', v2, '; key3: ', v3, '; key4: ', v4, '; key5: ', v5,
27255
- * '; key6: ', v6, '; key7: ', v7, 'suffix');
27256
- * ```
25509
+ * See `TStylingStatic` for more details.
27257
25510
  *
27258
- * @param prefix Static value used for concatenation only.
27259
- * @param v0 Value checked for change.
27260
- * @param i0 Static value used for concatenation only.
27261
- * @param v1 Value checked for change.
27262
- * @param i1 Static value used for concatenation only.
27263
- * @param v2 Value checked for change.
27264
- * @param i2 Static value used for concatenation only.
27265
- * @param v3 Value checked for change.
27266
- * @param i3 Static value used for concatenation only.
27267
- * @param v4 Value checked for change.
27268
- * @param i4 Static value used for concatenation only.
27269
- * @param v5 Value checked for change.
27270
- * @param i5 Static value used for concatenation only.
27271
- * @param v6 Value checked for change.
27272
- * @param i6 Static value used for concatenation only.
27273
- * @param v7 Value checked for change.
27274
- * @param suffix Static value used for concatenation only.
27275
- * @codeGenApi
25511
+ * @param tData `TData` where the linked list is stored.
25512
+ * @param tNode `TNode` for which the styling is being computed.
25513
+ * @param stylingKey `TStylingKeyPrimitive` which may need to be wrapped into `TStylingKey`
25514
+ * @param isClassBased `true` if `class` (`false` if `style`)
27276
25515
  */
27277
- function ɵɵstyleMapInterpolate8(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix) {
27278
- const lView = getLView();
27279
- const interpolatedValue = interpolation8(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix);
27280
- ɵɵstyleMap(interpolatedValue);
25516
+ function wrapInStaticStylingKey(tData, tNode, stylingKey, isClassBased) {
25517
+ const hostDirectiveDef = getCurrentDirectiveDef(tData);
25518
+ let residual = isClassBased ? tNode.residualClasses : tNode.residualStyles;
25519
+ if (hostDirectiveDef === null) {
25520
+ // We are in template node.
25521
+ // If template node already had styling instruction then it has already collected the static
25522
+ // styling and there is no need to collect them again. We know that we are the first styling
25523
+ // instruction because the `TNode.*Bindings` points to 0 (nothing has been inserted yet).
25524
+ const isFirstStylingInstructionInTemplate = (isClassBased ? tNode.classBindings : tNode.styleBindings) === 0;
25525
+ if (isFirstStylingInstructionInTemplate) {
25526
+ // It would be nice to be able to get the statics from `mergeAttrs`, however, at this point
25527
+ // they are already merged and it would not be possible to figure which property belongs where
25528
+ // in the priority.
25529
+ stylingKey = collectStylingFromDirectives(null, tData, tNode, stylingKey, isClassBased);
25530
+ stylingKey = collectStylingFromTAttrs(stylingKey, tNode.attrs, isClassBased);
25531
+ // We know that if we have styling binding in template we can't have residual.
25532
+ residual = null;
25533
+ }
25534
+ }
25535
+ else {
25536
+ // We are in host binding node and there was no binding instruction in template node.
25537
+ // This means that we need to compute the residual.
25538
+ const directiveStylingLast = tNode.directiveStylingLast;
25539
+ const isFirstStylingInstructionInHostBinding = directiveStylingLast === -1 || tData[directiveStylingLast] !== hostDirectiveDef;
25540
+ if (isFirstStylingInstructionInHostBinding) {
25541
+ stylingKey = collectStylingFromDirectives(hostDirectiveDef, tData, tNode, stylingKey, isClassBased);
25542
+ if (residual === null) {
25543
+ // - If `null` than either:
25544
+ // - Template styling instruction already ran and it has consumed the static
25545
+ // styling into its `TStylingKey` and so there is no need to update residual. Instead
25546
+ // we need to update the `TStylingKey` associated with the first template node
25547
+ // instruction. OR
25548
+ // - Some other styling instruction ran and determined that there are no residuals
25549
+ let templateStylingKey = getTemplateHeadTStylingKey(tData, tNode, isClassBased);
25550
+ if (templateStylingKey !== undefined && Array.isArray(templateStylingKey)) {
25551
+ // Only recompute if `templateStylingKey` had static values. (If no static value found
25552
+ // then there is nothing to do since this operation can only produce less static keys, not
25553
+ // more.)
25554
+ templateStylingKey = collectStylingFromDirectives(null, tData, tNode, templateStylingKey[1] /* unwrap previous statics */, isClassBased);
25555
+ templateStylingKey = collectStylingFromTAttrs(templateStylingKey, tNode.attrs, isClassBased);
25556
+ setTemplateHeadTStylingKey(tData, tNode, isClassBased, templateStylingKey);
25557
+ }
25558
+ }
25559
+ else {
25560
+ // We only need to recompute residual if it is not `null`.
25561
+ // - If existing residual (implies there was no template styling). This means that some of
25562
+ // the statics may have moved from the residual to the `stylingKey` and so we have to
25563
+ // recompute.
25564
+ // - If `undefined` this is the first time we are running.
25565
+ residual = collectResidual(tData, tNode, isClassBased);
25566
+ }
25567
+ }
25568
+ }
25569
+ if (residual !== undefined) {
25570
+ isClassBased ? (tNode.residualClasses = residual) : (tNode.residualStyles = residual);
25571
+ }
25572
+ return stylingKey;
27281
25573
  }
27282
25574
  /**
27283
- * Update an interpolated style on an element with 9 or more bound values surrounded by text.
27284
- *
27285
- * Used when the number of interpolated values exceeds 8.
27286
- *
27287
- * ```html
27288
- * <div
27289
- * class="key: {{v0}}; key1: {{v1}}; key2: {{v2}}; key3: {{v3}}; key4: {{v4}}; key5: {{v5}};
27290
- * key6: {{v6}}; key7: {{v7}}; key8: {{v8}}; key9: {{v9}}suffix"></div>
27291
- * ```
25575
+ * Retrieve the `TStylingKey` for the template styling instruction.
27292
25576
  *
27293
- * Its compiled representation is:
25577
+ * This is needed since `hostBinding` styling instructions are inserted after the template
25578
+ * instruction. While the template instruction needs to update the residual in `TNode` the
25579
+ * `hostBinding` instructions need to update the `TStylingKey` of the template instruction because
25580
+ * the template instruction is downstream from the `hostBindings` instructions.
27294
25581
  *
27295
- * ```ts
27296
- * ɵɵstyleMapInterpolateV(
27297
- * ['key: ', v0, '; key1: ', v1, '; key2: ', v2, '; key3: ', v3, '; key4: ', v4, '; key5: ', v5,
27298
- * '; key6: ', v6, '; key7: ', v7, '; key8: ', v8, '; key9: ', v9, 'suffix']);
27299
- * ```
27300
- *.
27301
- * @param values The collection of values and the strings in-between those values, beginning with
27302
- * a string prefix and ending with a string suffix.
27303
- * (e.g. `['prefix', value0, '; key2: ', value1, '; key2: ', value2, ..., value99, 'suffix']`)
27304
- * @codeGenApi
25582
+ * @param tData `TData` where the linked list is stored.
25583
+ * @param tNode `TNode` for which the styling is being computed.
25584
+ * @param isClassBased `true` if `class` (`false` if `style`)
25585
+ * @return `TStylingKey` if found or `undefined` if not found.
27305
25586
  */
27306
- function ɵɵstyleMapInterpolateV(values) {
27307
- const lView = getLView();
27308
- const interpolatedValue = interpolationV(lView, values);
27309
- ɵɵstyleMap(interpolatedValue);
25587
+ function getTemplateHeadTStylingKey(tData, tNode, isClassBased) {
25588
+ const bindings = isClassBased ? tNode.classBindings : tNode.styleBindings;
25589
+ if (getTStylingRangeNext(bindings) === 0) {
25590
+ // There does not seem to be a styling instruction in the `template`.
25591
+ return undefined;
25592
+ }
25593
+ return tData[getTStylingRangePrev(bindings)];
27310
25594
  }
27311
-
27312
25595
  /**
25596
+ * Update the `TStylingKey` of the first template instruction in `TNode`.
27313
25597
  *
27314
- * Update an interpolated style property on an element with single bound value surrounded by text.
25598
+ * Logically `hostBindings` styling instructions are of lower priority than that of the template.
25599
+ * However, they execute after the template styling instructions. This means that they get inserted
25600
+ * in front of the template styling instructions.
27315
25601
  *
27316
- * Used when the value passed to a property has 1 interpolated value in it:
25602
+ * If we have a template styling instruction and a new `hostBindings` styling instruction is
25603
+ * executed it means that it may need to steal static fields from the template instruction. This
25604
+ * method allows us to update the first template instruction `TStylingKey` with a new value.
27317
25605
  *
27318
- * ```html
27319
- * <div style.color="prefix{{v0}}suffix"></div>
27320
- * ```
25606
+ * Assume:
25607
+ * ```angular-ts
25608
+ * <div my-dir style="color: red" [style.color]="tmplExp"></div>
27321
25609
  *
27322
- * Its compiled representation is:
25610
+ * @Directive({
25611
+ * host: {
25612
+ * 'style': 'width: 100px',
25613
+ * '[style.color]': 'dirExp',
25614
+ * }
25615
+ * })
25616
+ * class MyDir {}
25617
+ * ```
27323
25618
  *
25619
+ * when `[style.color]="tmplExp"` executes it creates this data structure.
27324
25620
  * ```ts
27325
- * ɵɵstylePropInterpolate1(0, 'prefix', v0, 'suffix');
25621
+ * ['', 'color', 'color', 'red', 'width', '100px'],
27326
25622
  * ```
27327
25623
  *
27328
- * @param styleIndex Index of style to update. This index value refers to the
27329
- * index of the style in the style bindings array that was passed into
27330
- * `styling`.
27331
- * @param prefix Static value used for concatenation only.
27332
- * @param v0 Value checked for change.
27333
- * @param suffix Static value used for concatenation only.
27334
- * @param valueSuffix Optional suffix. Used with scalar values to add unit such as `px`.
27335
- * @returns itself, so that it may be chained.
27336
- * @codeGenApi
27337
- */
27338
- function ɵɵstylePropInterpolate1(prop, prefix, v0, suffix, valueSuffix) {
27339
- const lView = getLView();
27340
- const interpolatedValue = interpolation1(lView, prefix, v0, suffix);
27341
- checkStylingProperty(prop, interpolatedValue, valueSuffix, false);
27342
- return ɵɵstylePropInterpolate1;
27343
- }
27344
- /**
27345
- *
27346
- * Update an interpolated style property on an element with 2 bound values surrounded by text.
27347
- *
27348
- * Used when the value passed to a property has 2 interpolated values in it:
25624
+ * The reason for this is that the template instruction does not know if there are styling
25625
+ * instructions and must assume that there are none and must collect all of the static styling.
25626
+ * (both
25627
+ * `color' and 'width`)
27349
25628
  *
27350
- * ```html
27351
- * <div style.color="prefix{{v0}}-{{v1}}suffix"></div>
25629
+ * When `'[style.color]': 'dirExp',` executes we need to insert a new data into the linked list.
25630
+ * ```ts
25631
+ * ['', 'color', 'width', '100px'], // newly inserted
25632
+ * ['', 'color', 'color', 'red', 'width', '100px'], // this is wrong
27352
25633
  * ```
27353
25634
  *
27354
- * Its compiled representation is:
27355
- *
25635
+ * Notice that the template statics is now wrong as it incorrectly contains `width` so we need to
25636
+ * update it like so:
27356
25637
  * ```ts
27357
- * ɵɵstylePropInterpolate2(0, 'prefix', v0, '-', v1, 'suffix');
25638
+ * ['', 'color', 'width', '100px'],
25639
+ * ['', 'color', 'color', 'red'], // UPDATE
27358
25640
  * ```
27359
25641
  *
27360
- * @param styleIndex Index of style to update. This index value refers to the
27361
- * index of the style in the style bindings array that was passed into
27362
- * `styling`.
27363
- * @param prefix Static value used for concatenation only.
27364
- * @param v0 Value checked for change.
27365
- * @param i0 Static value used for concatenation only.
27366
- * @param v1 Value checked for change.
27367
- * @param suffix Static value used for concatenation only.
27368
- * @param valueSuffix Optional suffix. Used with scalar values to add unit such as `px`.
27369
- * @returns itself, so that it may be chained.
27370
- * @codeGenApi
25642
+ * @param tData `TData` where the linked list is stored.
25643
+ * @param tNode `TNode` for which the styling is being computed.
25644
+ * @param isClassBased `true` if `class` (`false` if `style`)
25645
+ * @param tStylingKey New `TStylingKey` which is replacing the old one.
27371
25646
  */
27372
- function ɵɵstylePropInterpolate2(prop, prefix, v0, i0, v1, suffix, valueSuffix) {
27373
- const lView = getLView();
27374
- const interpolatedValue = interpolation2(lView, prefix, v0, i0, v1, suffix);
27375
- checkStylingProperty(prop, interpolatedValue, valueSuffix, false);
27376
- return ɵɵstylePropInterpolate2;
25647
+ function setTemplateHeadTStylingKey(tData, tNode, isClassBased, tStylingKey) {
25648
+ const bindings = isClassBased ? tNode.classBindings : tNode.styleBindings;
25649
+ ngDevMode &&
25650
+ assertNotEqual(getTStylingRangeNext(bindings), 0, 'Expecting to have at least one template styling binding.');
25651
+ tData[getTStylingRangePrev(bindings)] = tStylingKey;
27377
25652
  }
27378
25653
  /**
25654
+ * Collect all static values after the current `TNode.directiveStylingLast` index.
27379
25655
  *
27380
- * Update an interpolated style property on an element with 3 bound values surrounded by text.
27381
- *
27382
- * Used when the value passed to a property has 3 interpolated values in it:
27383
- *
27384
- * ```html
27385
- * <div style.color="prefix{{v0}}-{{v1}}-{{v2}}suffix"></div>
27386
- * ```
27387
- *
27388
- * Its compiled representation is:
27389
- *
27390
- * ```ts
27391
- * ɵɵstylePropInterpolate3(0, 'prefix', v0, '-', v1, '-', v2, 'suffix');
27392
- * ```
25656
+ * Collect the remaining styling information which has not yet been collected by an existing
25657
+ * styling instruction.
27393
25658
  *
27394
- * @param styleIndex Index of style to update. This index value refers to the
27395
- * index of the style in the style bindings array that was passed into
27396
- * `styling`.
27397
- * @param prefix Static value used for concatenation only.
27398
- * @param v0 Value checked for change.
27399
- * @param i0 Static value used for concatenation only.
27400
- * @param v1 Value checked for change.
27401
- * @param i1 Static value used for concatenation only.
27402
- * @param v2 Value checked for change.
27403
- * @param suffix Static value used for concatenation only.
27404
- * @param valueSuffix Optional suffix. Used with scalar values to add unit such as `px`.
27405
- * @returns itself, so that it may be chained.
27406
- * @codeGenApi
25659
+ * @param tData `TData` where the `DirectiveDefs` are stored.
25660
+ * @param tNode `TNode` which contains the directive range.
25661
+ * @param isClassBased `true` if `class` (`false` if `style`)
27407
25662
  */
27408
- function ɵɵstylePropInterpolate3(prop, prefix, v0, i0, v1, i1, v2, suffix, valueSuffix) {
27409
- const lView = getLView();
27410
- const interpolatedValue = interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix);
27411
- checkStylingProperty(prop, interpolatedValue, valueSuffix, false);
27412
- return ɵɵstylePropInterpolate3;
25663
+ function collectResidual(tData, tNode, isClassBased) {
25664
+ let residual = undefined;
25665
+ const directiveEnd = tNode.directiveEnd;
25666
+ ngDevMode &&
25667
+ assertNotEqual(tNode.directiveStylingLast, -1, 'By the time this function gets called at least one hostBindings-node styling instruction must have executed.');
25668
+ // We add `1 + tNode.directiveStart` because we need to skip the current directive (as we are
25669
+ // collecting things after the last `hostBindings` directive which had a styling instruction.)
25670
+ for (let i = 1 + tNode.directiveStylingLast; i < directiveEnd; i++) {
25671
+ const attrs = tData[i].hostAttrs;
25672
+ residual = collectStylingFromTAttrs(residual, attrs, isClassBased);
25673
+ }
25674
+ return collectStylingFromTAttrs(residual, tNode.attrs, isClassBased);
27413
25675
  }
27414
25676
  /**
25677
+ * Collect the static styling information with lower priority than `hostDirectiveDef`.
27415
25678
  *
27416
- * Update an interpolated style property on an element with 4 bound values surrounded by text.
27417
- *
27418
- * Used when the value passed to a property has 4 interpolated values in it:
27419
- *
27420
- * ```html
27421
- * <div style.color="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}suffix"></div>
27422
- * ```
27423
- *
27424
- * Its compiled representation is:
27425
- *
27426
- * ```ts
27427
- * ɵɵstylePropInterpolate4(0, 'prefix', v0, '-', v1, '-', v2, '-', v3, 'suffix');
27428
- * ```
25679
+ * (This is opposite of residual styling.)
27429
25680
  *
27430
- * @param styleIndex Index of style to update. This index value refers to the
27431
- * index of the style in the style bindings array that was passed into
27432
- * `styling`.
27433
- * @param prefix Static value used for concatenation only.
27434
- * @param v0 Value checked for change.
27435
- * @param i0 Static value used for concatenation only.
27436
- * @param v1 Value checked for change.
27437
- * @param i1 Static value used for concatenation only.
27438
- * @param v2 Value checked for change.
27439
- * @param i2 Static value used for concatenation only.
27440
- * @param v3 Value checked for change.
27441
- * @param suffix Static value used for concatenation only.
27442
- * @param valueSuffix Optional suffix. Used with scalar values to add unit such as `px`.
27443
- * @returns itself, so that it may be chained.
27444
- * @codeGenApi
25681
+ * @param hostDirectiveDef `DirectiveDef` for which we want to collect lower priority static
25682
+ * styling. (Or `null` if template styling)
25683
+ * @param tData `TData` where the linked list is stored.
25684
+ * @param tNode `TNode` for which the styling is being computed.
25685
+ * @param stylingKey Existing `TStylingKey` to update or wrap.
25686
+ * @param isClassBased `true` if `class` (`false` if `style`)
27445
25687
  */
27446
- function ɵɵstylePropInterpolate4(prop, prefix, v0, i0, v1, i1, v2, i2, v3, suffix, valueSuffix) {
27447
- const lView = getLView();
27448
- const interpolatedValue = interpolation4(lView, prefix, v0, i0, v1, i1, v2, i2, v3, suffix);
27449
- checkStylingProperty(prop, interpolatedValue, valueSuffix, false);
27450
- return ɵɵstylePropInterpolate4;
25688
+ function collectStylingFromDirectives(hostDirectiveDef, tData, tNode, stylingKey, isClassBased) {
25689
+ // We need to loop because there can be directives which have `hostAttrs` but don't have
25690
+ // `hostBindings` so this loop catches up to the current directive..
25691
+ let currentDirective = null;
25692
+ const directiveEnd = tNode.directiveEnd;
25693
+ let directiveStylingLast = tNode.directiveStylingLast;
25694
+ if (directiveStylingLast === -1) {
25695
+ directiveStylingLast = tNode.directiveStart;
25696
+ }
25697
+ else {
25698
+ directiveStylingLast++;
25699
+ }
25700
+ while (directiveStylingLast < directiveEnd) {
25701
+ currentDirective = tData[directiveStylingLast];
25702
+ ngDevMode && assertDefined(currentDirective, 'expected to be defined');
25703
+ stylingKey = collectStylingFromTAttrs(stylingKey, currentDirective.hostAttrs, isClassBased);
25704
+ if (currentDirective === hostDirectiveDef)
25705
+ break;
25706
+ directiveStylingLast++;
25707
+ }
25708
+ if (hostDirectiveDef !== null) {
25709
+ // we only advance the styling cursor if we are collecting data from host bindings.
25710
+ // Template executes before host bindings and so if we would update the index,
25711
+ // host bindings would not get their statics.
25712
+ tNode.directiveStylingLast = directiveStylingLast;
25713
+ }
25714
+ return stylingKey;
27451
25715
  }
27452
25716
  /**
25717
+ * Convert `TAttrs` into `TStylingStatic`.
27453
25718
  *
27454
- * Update an interpolated style property on an element with 5 bound values surrounded by text.
25719
+ * @param stylingKey existing `TStylingKey` to update or wrap.
25720
+ * @param attrs `TAttributes` to process.
25721
+ * @param isClassBased `true` if `class` (`false` if `style`)
25722
+ */
25723
+ function collectStylingFromTAttrs(stylingKey, attrs, isClassBased) {
25724
+ const desiredMarker = isClassBased ? 1 /* AttributeMarker.Classes */ : 2 /* AttributeMarker.Styles */;
25725
+ let currentMarker = -1 /* AttributeMarker.ImplicitAttributes */;
25726
+ if (attrs !== null) {
25727
+ for (let i = 0; i < attrs.length; i++) {
25728
+ const item = attrs[i];
25729
+ if (typeof item === 'number') {
25730
+ currentMarker = item;
25731
+ }
25732
+ else {
25733
+ if (currentMarker === desiredMarker) {
25734
+ if (!Array.isArray(stylingKey)) {
25735
+ stylingKey = stylingKey === undefined ? [] : ['', stylingKey];
25736
+ }
25737
+ keyValueArraySet(stylingKey, item, isClassBased ? true : attrs[++i]);
25738
+ }
25739
+ }
25740
+ }
25741
+ }
25742
+ return stylingKey === undefined ? null : stylingKey;
25743
+ }
25744
+ /**
25745
+ * Convert user input to `KeyValueArray`.
27455
25746
  *
27456
- * Used when the value passed to a property has 5 interpolated values in it:
25747
+ * This function takes user input which could be `string`, Object literal, or iterable and converts
25748
+ * it into a consistent representation. The output of this is `KeyValueArray` (which is an array
25749
+ * where
25750
+ * even indexes contain keys and odd indexes contain values for those keys).
27457
25751
  *
27458
- * ```html
27459
- * <div style.color="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}suffix"></div>
27460
- * ```
25752
+ * The advantage of converting to `KeyValueArray` is that we can perform diff in an input
25753
+ * independent
25754
+ * way.
25755
+ * (ie we can compare `foo bar` to `['bar', 'baz'] and determine a set of changes which need to be
25756
+ * applied)
27461
25757
  *
27462
- * Its compiled representation is:
25758
+ * The fact that `KeyValueArray` is sorted is very important because it allows us to compute the
25759
+ * difference in linear fashion without the need to allocate any additional data.
27463
25760
  *
27464
- * ```ts
27465
- * ɵɵstylePropInterpolate5(0, 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, 'suffix');
27466
- * ```
25761
+ * For example if we kept this as a `Map` we would have to iterate over previous `Map` to determine
25762
+ * which values need to be deleted, over the new `Map` to determine additions, and we would have to
25763
+ * keep additional `Map` to keep track of duplicates or items which have not yet been visited.
27467
25764
  *
27468
- * @param styleIndex Index of style to update. This index value refers to the
27469
- * index of the style in the style bindings array that was passed into
27470
- * `styling`.
27471
- * @param prefix Static value used for concatenation only.
27472
- * @param v0 Value checked for change.
27473
- * @param i0 Static value used for concatenation only.
27474
- * @param v1 Value checked for change.
27475
- * @param i1 Static value used for concatenation only.
27476
- * @param v2 Value checked for change.
27477
- * @param i2 Static value used for concatenation only.
27478
- * @param v3 Value checked for change.
27479
- * @param i3 Static value used for concatenation only.
27480
- * @param v4 Value checked for change.
27481
- * @param suffix Static value used for concatenation only.
27482
- * @param valueSuffix Optional suffix. Used with scalar values to add unit such as `px`.
27483
- * @returns itself, so that it may be chained.
27484
- * @codeGenApi
25765
+ * @param keyValueArraySet (See `keyValueArraySet` in "util/array_utils") Gets passed in as a
25766
+ * function so that `style` can be processed. This is done
25767
+ * for tree shaking purposes.
25768
+ * @param stringParser The parser is passed in so that it will be tree shakable. See
25769
+ * `styleStringParser` and `classStringParser`
25770
+ * @param value The value to parse/convert to `KeyValueArray`
27485
25771
  */
27486
- function ɵɵstylePropInterpolate5(prop, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix, valueSuffix) {
27487
- const lView = getLView();
27488
- const interpolatedValue = interpolation5(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix);
27489
- checkStylingProperty(prop, interpolatedValue, valueSuffix, false);
27490
- return ɵɵstylePropInterpolate5;
25772
+ function toStylingKeyValueArray(keyValueArraySet, stringParser, value) {
25773
+ if (value == null /*|| value === undefined */ || value === '')
25774
+ return EMPTY_ARRAY;
25775
+ const styleKeyValueArray = [];
25776
+ const unwrappedValue = unwrapSafeValue(value);
25777
+ if (Array.isArray(unwrappedValue)) {
25778
+ for (let i = 0; i < unwrappedValue.length; i++) {
25779
+ keyValueArraySet(styleKeyValueArray, unwrappedValue[i], true);
25780
+ }
25781
+ }
25782
+ else if (typeof unwrappedValue === 'object') {
25783
+ for (const key in unwrappedValue) {
25784
+ if (unwrappedValue.hasOwnProperty(key)) {
25785
+ keyValueArraySet(styleKeyValueArray, key, unwrappedValue[key]);
25786
+ }
25787
+ }
25788
+ }
25789
+ else if (typeof unwrappedValue === 'string') {
25790
+ stringParser(styleKeyValueArray, unwrappedValue);
25791
+ }
25792
+ else {
25793
+ ngDevMode &&
25794
+ throwError('Unsupported styling type: ' + typeof unwrappedValue + ' (' + unwrappedValue + ')');
25795
+ }
25796
+ return styleKeyValueArray;
27491
25797
  }
27492
25798
  /**
25799
+ * Set a `value` for a `key`.
27493
25800
  *
27494
- * Update an interpolated style property on an element with 6 bound values surrounded by text.
25801
+ * See: `keyValueArraySet` for details
27495
25802
  *
27496
- * Used when the value passed to a property has 6 interpolated values in it:
25803
+ * @param keyValueArray KeyValueArray to add to.
25804
+ * @param key Style key to add.
25805
+ * @param value The value to set.
25806
+ */
25807
+ function styleKeyValueArraySet(keyValueArray, key, value) {
25808
+ keyValueArraySet(keyValueArray, key, unwrapSafeValue(value));
25809
+ }
25810
+ /**
25811
+ * Class-binding-specific function for setting the `value` for a `key`.
27497
25812
  *
27498
- * ```html
27499
- * <div style.color="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}suffix"></div>
27500
- * ```
25813
+ * See: `keyValueArraySet` for details
27501
25814
  *
27502
- * Its compiled representation is:
25815
+ * @param keyValueArray KeyValueArray to add to.
25816
+ * @param key Style key to add.
25817
+ * @param value The value to set.
25818
+ */
25819
+ function classKeyValueArraySet(keyValueArray, key, value) {
25820
+ // We use `classList.add` to eventually add the CSS classes to the DOM node. Any value passed into
25821
+ // `add` is stringified and added to the `class` attribute, e.g. even null, undefined or numbers
25822
+ // will be added. Stringify the key here so that our internal data structure matches the value in
25823
+ // the DOM. The only exceptions are empty strings and strings that contain spaces for which
25824
+ // the browser throws an error. We ignore such values, because the error is somewhat cryptic.
25825
+ const stringKey = String(key);
25826
+ if (stringKey !== '' && !stringKey.includes(' ')) {
25827
+ keyValueArraySet(keyValueArray, stringKey, value);
25828
+ }
25829
+ }
25830
+ /**
25831
+ * Update map based styling.
27503
25832
  *
27504
- * ```ts
27505
- * ɵɵstylePropInterpolate6(0, 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, 'suffix');
27506
- * ```
25833
+ * Map based styling could be anything which contains more than one binding. For example `string`,
25834
+ * or object literal. Dealing with all of these types would complicate the logic so
25835
+ * instead this function expects that the complex input is first converted into normalized
25836
+ * `KeyValueArray`. The advantage of normalization is that we get the values sorted, which makes it
25837
+ * very cheap to compute deltas between the previous and current value.
27507
25838
  *
27508
- * @param styleIndex Index of style to update. This index value refers to the
27509
- * index of the style in the style bindings array that was passed into
27510
- * `styling`.
27511
- * @param prefix Static value used for concatenation only.
27512
- * @param v0 Value checked for change.
27513
- * @param i0 Static value used for concatenation only.
27514
- * @param v1 Value checked for change.
27515
- * @param i1 Static value used for concatenation only.
27516
- * @param v2 Value checked for change.
27517
- * @param i2 Static value used for concatenation only.
27518
- * @param v3 Value checked for change.
27519
- * @param i3 Static value used for concatenation only.
27520
- * @param v4 Value checked for change.
27521
- * @param i4 Static value used for concatenation only.
27522
- * @param v5 Value checked for change.
27523
- * @param suffix Static value used for concatenation only.
27524
- * @param valueSuffix Optional suffix. Used with scalar values to add unit such as `px`.
27525
- * @returns itself, so that it may be chained.
27526
- * @codeGenApi
25839
+ * @param tView Associated `TView.data` contains the linked list of binding priorities.
25840
+ * @param tNode `TNode` where the binding is located.
25841
+ * @param lView `LView` contains the values associated with other styling binding at this `TNode`.
25842
+ * @param renderer Renderer to use if any updates.
25843
+ * @param oldKeyValueArray Previous value represented as `KeyValueArray`
25844
+ * @param newKeyValueArray Current value represented as `KeyValueArray`
25845
+ * @param isClassBased `true` if `class` (`false` if `style`)
25846
+ * @param bindingIndex Binding index of the binding.
27527
25847
  */
27528
- function ɵɵstylePropInterpolate6(prop, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix, valueSuffix) {
27529
- const lView = getLView();
27530
- const interpolatedValue = interpolation6(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix);
27531
- checkStylingProperty(prop, interpolatedValue, valueSuffix, false);
27532
- return ɵɵstylePropInterpolate6;
25848
+ function updateStylingMap(tView, tNode, lView, renderer, oldKeyValueArray, newKeyValueArray, isClassBased, bindingIndex) {
25849
+ if (oldKeyValueArray === NO_CHANGE) {
25850
+ // On first execution the oldKeyValueArray is NO_CHANGE => treat it as empty KeyValueArray.
25851
+ oldKeyValueArray = EMPTY_ARRAY;
25852
+ }
25853
+ let oldIndex = 0;
25854
+ let newIndex = 0;
25855
+ let oldKey = 0 < oldKeyValueArray.length ? oldKeyValueArray[0] : null;
25856
+ let newKey = 0 < newKeyValueArray.length ? newKeyValueArray[0] : null;
25857
+ while (oldKey !== null || newKey !== null) {
25858
+ ngDevMode && assertLessThan(oldIndex, 999, 'Are we stuck in infinite loop?');
25859
+ ngDevMode && assertLessThan(newIndex, 999, 'Are we stuck in infinite loop?');
25860
+ const oldValue = oldIndex < oldKeyValueArray.length ? oldKeyValueArray[oldIndex + 1] : undefined;
25861
+ const newValue = newIndex < newKeyValueArray.length ? newKeyValueArray[newIndex + 1] : undefined;
25862
+ let setKey = null;
25863
+ let setValue = undefined;
25864
+ if (oldKey === newKey) {
25865
+ // UPDATE: Keys are equal => new value is overwriting old value.
25866
+ oldIndex += 2;
25867
+ newIndex += 2;
25868
+ if (oldValue !== newValue) {
25869
+ setKey = newKey;
25870
+ setValue = newValue;
25871
+ }
25872
+ }
25873
+ else if (newKey === null || (oldKey !== null && oldKey < newKey)) {
25874
+ // DELETE: oldKey key is missing or we did not find the oldKey in the newValue
25875
+ // (because the keyValueArray is sorted and `newKey` is found later alphabetically).
25876
+ // `"background" < "color"` so we need to delete `"background"` because it is not found in the
25877
+ // new array.
25878
+ oldIndex += 2;
25879
+ setKey = oldKey;
25880
+ }
25881
+ else {
25882
+ // CREATE: newKey's is earlier alphabetically than oldKey's (or no oldKey) => we have new key.
25883
+ // `"color" > "background"` so we need to add `color` because it is in new array but not in
25884
+ // old array.
25885
+ ngDevMode && assertDefined(newKey, 'Expecting to have a valid key');
25886
+ newIndex += 2;
25887
+ setKey = newKey;
25888
+ setValue = newValue;
25889
+ }
25890
+ if (setKey !== null) {
25891
+ updateStyling(tView, tNode, lView, renderer, setKey, setValue, isClassBased, bindingIndex);
25892
+ }
25893
+ oldKey = oldIndex < oldKeyValueArray.length ? oldKeyValueArray[oldIndex] : null;
25894
+ newKey = newIndex < newKeyValueArray.length ? newKeyValueArray[newIndex] : null;
25895
+ }
27533
25896
  }
27534
25897
  /**
25898
+ * Update a simple (property name) styling.
27535
25899
  *
27536
- * Update an interpolated style property on an element with 7 bound values surrounded by text.
25900
+ * This function takes `prop` and updates the DOM to that value. The function takes the binding
25901
+ * value as well as binding priority into consideration to determine which value should be written
25902
+ * to DOM. (For example it may be determined that there is a higher priority overwrite which blocks
25903
+ * the DOM write, or if the value goes to `undefined` a lower priority overwrite may be consulted.)
27537
25904
  *
27538
- * Used when the value passed to a property has 7 interpolated values in it:
25905
+ * @param tView Associated `TView.data` contains the linked list of binding priorities.
25906
+ * @param tNode `TNode` where the binding is located.
25907
+ * @param lView `LView` contains the values associated with other styling binding at this `TNode`.
25908
+ * @param renderer Renderer to use if any updates.
25909
+ * @param prop Either style property name or a class name.
25910
+ * @param value Either style value for `prop` or `true`/`false` if `prop` is class.
25911
+ * @param isClassBased `true` if `class` (`false` if `style`)
25912
+ * @param bindingIndex Binding index of the binding.
25913
+ */
25914
+ function updateStyling(tView, tNode, lView, renderer, prop, value, isClassBased, bindingIndex) {
25915
+ if (!(tNode.type & 3 /* TNodeType.AnyRNode */)) {
25916
+ // It is possible to have styling on non-elements (such as ng-container).
25917
+ // This is rare, but it does happen. In such a case, just ignore the binding.
25918
+ return;
25919
+ }
25920
+ const tData = tView.data;
25921
+ const tRange = tData[bindingIndex + 1];
25922
+ const higherPriorityValue = getTStylingRangeNextDuplicate(tRange)
25923
+ ? findStylingValue(tData, tNode, lView, prop, getTStylingRangeNext(tRange), isClassBased)
25924
+ : undefined;
25925
+ if (!isStylingValuePresent(higherPriorityValue)) {
25926
+ // We don't have a next duplicate, or we did not find a duplicate value.
25927
+ if (!isStylingValuePresent(value)) {
25928
+ // We should delete current value or restore to lower priority value.
25929
+ if (getTStylingRangePrevDuplicate(tRange)) {
25930
+ // We have a possible prev duplicate, let's retrieve it.
25931
+ value = findStylingValue(tData, null, lView, prop, bindingIndex, isClassBased);
25932
+ }
25933
+ }
25934
+ const rNode = getNativeByIndex(getSelectedIndex(), lView);
25935
+ applyStyling(renderer, isClassBased, rNode, prop, value);
25936
+ }
25937
+ }
25938
+ /**
25939
+ * Search for styling value with higher priority which is overwriting current value, or a
25940
+ * value of lower priority to which we should fall back if the value is `undefined`.
27539
25941
  *
27540
- * ```html
27541
- * <div style.color="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}suffix"></div>
27542
- * ```
25942
+ * When value is being applied at a location, related values need to be consulted.
25943
+ * - If there is a higher priority binding, we should be using that one instead.
25944
+ * For example `<div [style]="{color:exp1}" [style.color]="exp2">` change to `exp1`
25945
+ * requires that we check `exp2` to see if it is set to value other than `undefined`.
25946
+ * - If there is a lower priority binding and we are changing to `undefined`
25947
+ * For example `<div [style]="{color:exp1}" [style.color]="exp2">` change to `exp2` to
25948
+ * `undefined` requires that we check `exp1` (and static values) and use that as new value.
27543
25949
  *
27544
- * Its compiled representation is:
25950
+ * NOTE: The styling stores two values.
25951
+ * 1. The raw value which came from the application is stored at `index + 0` location. (This value
25952
+ * is used for dirty checking).
25953
+ * 2. The normalized value is stored at `index + 1`.
27545
25954
  *
27546
- * ```ts
27547
- * ɵɵstylePropInterpolate7(
27548
- * 0, 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, 'suffix');
27549
- * ```
25955
+ * @param tData `TData` used for traversing the priority.
25956
+ * @param tNode `TNode` to use for resolving static styling. Also controls search direction.
25957
+ * - `TNode` search next and quit as soon as `isStylingValuePresent(value)` is true.
25958
+ * If no value found consult `tNode.residualStyle`/`tNode.residualClass` for default value.
25959
+ * - `null` search prev and go all the way to end. Return last value where
25960
+ * `isStylingValuePresent(value)` is true.
25961
+ * @param lView `LView` used for retrieving the actual values.
25962
+ * @param prop Property which we are interested in.
25963
+ * @param index Starting index in the linked list of styling bindings where the search should start.
25964
+ * @param isClassBased `true` if `class` (`false` if `style`)
25965
+ */
25966
+ function findStylingValue(tData, tNode, lView, prop, index, isClassBased) {
25967
+ // `TNode` to use for resolving static styling. Also controls search direction.
25968
+ // - `TNode` search next and quit as soon as `isStylingValuePresent(value)` is true.
25969
+ // If no value found consult `tNode.residualStyle`/`tNode.residualClass` for default value.
25970
+ // - `null` search prev and go all the way to end. Return last value where
25971
+ // `isStylingValuePresent(value)` is true.
25972
+ const isPrevDirection = tNode === null;
25973
+ let value = undefined;
25974
+ while (index > 0) {
25975
+ const rawKey = tData[index];
25976
+ const containsStatics = Array.isArray(rawKey);
25977
+ // Unwrap the key if we contain static values.
25978
+ const key = containsStatics ? rawKey[1] : rawKey;
25979
+ const isStylingMap = key === null;
25980
+ let valueAtLViewIndex = lView[index + 1];
25981
+ if (valueAtLViewIndex === NO_CHANGE) {
25982
+ // In firstUpdatePass the styling instructions create a linked list of styling.
25983
+ // On subsequent passes it is possible for a styling instruction to try to read a binding
25984
+ // which
25985
+ // has not yet executed. In that case we will find `NO_CHANGE` and we should assume that
25986
+ // we have `undefined` (or empty array in case of styling-map instruction) instead. This
25987
+ // allows the resolution to apply the value (which may later be overwritten when the
25988
+ // binding actually executes.)
25989
+ valueAtLViewIndex = isStylingMap ? EMPTY_ARRAY : undefined;
25990
+ }
25991
+ let currentValue = isStylingMap
25992
+ ? keyValueArrayGet(valueAtLViewIndex, prop)
25993
+ : key === prop
25994
+ ? valueAtLViewIndex
25995
+ : undefined;
25996
+ if (containsStatics && !isStylingValuePresent(currentValue)) {
25997
+ currentValue = keyValueArrayGet(rawKey, prop);
25998
+ }
25999
+ if (isStylingValuePresent(currentValue)) {
26000
+ value = currentValue;
26001
+ if (isPrevDirection) {
26002
+ return value;
26003
+ }
26004
+ }
26005
+ const tRange = tData[index + 1];
26006
+ index = isPrevDirection ? getTStylingRangePrev(tRange) : getTStylingRangeNext(tRange);
26007
+ }
26008
+ if (tNode !== null) {
26009
+ // in case where we are going in next direction AND we did not find anything, we need to
26010
+ // consult residual styling
26011
+ let residual = isClassBased ? tNode.residualClasses : tNode.residualStyles;
26012
+ if (residual != null /** OR residual !=== undefined */) {
26013
+ value = keyValueArrayGet(residual, prop);
26014
+ }
26015
+ }
26016
+ return value;
26017
+ }
26018
+ /**
26019
+ * Determines if the binding value should be used (or if the value is 'undefined' and hence priority
26020
+ * resolution should be used.)
27550
26021
  *
27551
- * @param styleIndex Index of style to update. This index value refers to the
27552
- * index of the style in the style bindings array that was passed into
27553
- * `styling`.
27554
- * @param prefix Static value used for concatenation only.
27555
- * @param v0 Value checked for change.
27556
- * @param i0 Static value used for concatenation only.
27557
- * @param v1 Value checked for change.
27558
- * @param i1 Static value used for concatenation only.
27559
- * @param v2 Value checked for change.
27560
- * @param i2 Static value used for concatenation only.
27561
- * @param v3 Value checked for change.
27562
- * @param i3 Static value used for concatenation only.
27563
- * @param v4 Value checked for change.
27564
- * @param i4 Static value used for concatenation only.
27565
- * @param v5 Value checked for change.
27566
- * @param i5 Static value used for concatenation only.
27567
- * @param v6 Value checked for change.
27568
- * @param suffix Static value used for concatenation only.
27569
- * @param valueSuffix Optional suffix. Used with scalar values to add unit such as `px`.
27570
- * @returns itself, so that it may be chained.
27571
- * @codeGenApi
26022
+ * @param value Binding style value.
27572
26023
  */
27573
- function ɵɵstylePropInterpolate7(prop, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix, valueSuffix) {
27574
- const lView = getLView();
27575
- const interpolatedValue = interpolation7(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix);
27576
- checkStylingProperty(prop, interpolatedValue, valueSuffix, false);
27577
- return ɵɵstylePropInterpolate7;
26024
+ function isStylingValuePresent(value) {
26025
+ // Currently only `undefined` value is considered non-binding. That is `undefined` says I don't
26026
+ // have an opinion as to what this binding should be and you should consult other bindings by
26027
+ // priority to determine the valid value.
26028
+ // This is extracted into a single function so that we have a single place to control this.
26029
+ return value !== undefined;
27578
26030
  }
27579
26031
  /**
26032
+ * Normalizes and/or adds a suffix to the value.
27580
26033
  *
27581
- * Update an interpolated style property on an element with 8 bound values surrounded by text.
27582
- *
27583
- * Used when the value passed to a property has 8 interpolated values in it:
27584
- *
27585
- * ```html
27586
- * <div style.color="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}suffix"></div>
27587
- * ```
27588
- *
27589
- * Its compiled representation is:
27590
- *
27591
- * ```ts
27592
- * ɵɵstylePropInterpolate8(0, 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6,
27593
- * '-', v7, 'suffix');
27594
- * ```
27595
- *
27596
- * @param styleIndex Index of style to update. This index value refers to the
27597
- * index of the style in the style bindings array that was passed into
27598
- * `styling`.
27599
- * @param prefix Static value used for concatenation only.
27600
- * @param v0 Value checked for change.
27601
- * @param i0 Static value used for concatenation only.
27602
- * @param v1 Value checked for change.
27603
- * @param i1 Static value used for concatenation only.
27604
- * @param v2 Value checked for change.
27605
- * @param i2 Static value used for concatenation only.
27606
- * @param v3 Value checked for change.
27607
- * @param i3 Static value used for concatenation only.
27608
- * @param v4 Value checked for change.
27609
- * @param i4 Static value used for concatenation only.
27610
- * @param v5 Value checked for change.
27611
- * @param i5 Static value used for concatenation only.
27612
- * @param v6 Value checked for change.
27613
- * @param i6 Static value used for concatenation only.
27614
- * @param v7 Value checked for change.
27615
- * @param suffix Static value used for concatenation only.
27616
- * @param valueSuffix Optional suffix. Used with scalar values to add unit such as `px`.
27617
- * @returns itself, so that it may be chained.
27618
- * @codeGenApi
26034
+ * If value is `null`/`undefined` no suffix is added
26035
+ * @param value
26036
+ * @param suffix
27619
26037
  */
27620
- function ɵɵstylePropInterpolate8(prop, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix, valueSuffix) {
27621
- const lView = getLView();
27622
- const interpolatedValue = interpolation8(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix);
27623
- checkStylingProperty(prop, interpolatedValue, valueSuffix, false);
27624
- return ɵɵstylePropInterpolate8;
26038
+ function normalizeSuffix(value, suffix) {
26039
+ if (value == null || value === '') ;
26040
+ else if (typeof suffix === 'string') {
26041
+ value = value + suffix;
26042
+ }
26043
+ else if (typeof value === 'object') {
26044
+ value = stringify(unwrapSafeValue(value));
26045
+ }
26046
+ return value;
27625
26047
  }
27626
26048
  /**
27627
- * Update an interpolated style property on an element with 9 or more bound values surrounded by
27628
- * text.
27629
- *
27630
- * Used when the number of interpolated values exceeds 8.
27631
- *
27632
- * ```html
27633
- * <div
27634
- * style.color="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}-{{v8}}-{{v9}}suffix">
27635
- * </div>
27636
- * ```
27637
- *
27638
- * Its compiled representation is:
26049
+ * Tests if the `TNode` has input shadow.
27639
26050
  *
27640
- * ```ts
27641
- * ɵɵstylePropInterpolateV(
27642
- * 0, ['prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, '-', v9,
27643
- * 'suffix']);
27644
- * ```
26051
+ * An input shadow is when a directive steals (shadows) the input by using `@Input('style')` or
26052
+ * `@Input('class')` as input.
27645
26053
  *
27646
- * @param styleIndex Index of style to update. This index value refers to the
27647
- * index of the style in the style bindings array that was passed into
27648
- * `styling`..
27649
- * @param values The collection of values and the strings in-between those values, beginning with
27650
- * a string prefix and ending with a string suffix.
27651
- * (e.g. `['prefix', value0, '-', value1, '-', value2, ..., value99, 'suffix']`)
27652
- * @param valueSuffix Optional suffix. Used with scalar values to add unit such as `px`.
27653
- * @returns itself, so that it may be chained.
27654
- * @codeGenApi
26054
+ * @param tNode `TNode` which we would like to see if it has shadow.
26055
+ * @param isClassBased `true` if `class` (`false` if `style`)
27655
26056
  */
27656
- function ɵɵstylePropInterpolateV(prop, values, valueSuffix) {
27657
- const lView = getLView();
27658
- const interpolatedValue = interpolationV(lView, values);
27659
- checkStylingProperty(prop, interpolatedValue, valueSuffix, false);
27660
- return ɵɵstylePropInterpolateV;
26057
+ function hasStylingInputShadow(tNode, isClassBased) {
26058
+ return (tNode.flags & (isClassBased ? 8 /* TNodeFlags.hasClassInput */ : 16 /* TNodeFlags.hasStyleInput */)) !== 0;
27661
26059
  }
27662
26060
 
27663
26061
  /**
@@ -27715,6 +26113,189 @@ function enableLocateOrCreateTextNodeImpl() {
27715
26113
  _locateOrCreateTextNode = locateOrCreateTextNodeImpl;
27716
26114
  }
27717
26115
 
26116
+ /**
26117
+ * Create interpolation bindings with a variable number of expressions.
26118
+ *
26119
+ * If there are 1 to 8 expressions `interpolation1()` to `interpolation8()` should be used instead.
26120
+ * Those are faster because there is no need to create an array of expressions and iterate over it.
26121
+ *
26122
+ * `values`:
26123
+ * - has static text at even indexes,
26124
+ * - has evaluated expressions at odd indexes.
26125
+ *
26126
+ * Returns the concatenated string when any of the arguments changes, `NO_CHANGE` otherwise.
26127
+ */
26128
+ function interpolationV(lView, values) {
26129
+ ngDevMode && assertLessThan(2, values.length, 'should have at least 3 values');
26130
+ let isBindingUpdated = false;
26131
+ let bindingIndex = getBindingIndex();
26132
+ for (let i = 1; i < values.length; i += 2) {
26133
+ // Check if bindings (odd indexes) have changed
26134
+ isBindingUpdated = bindingUpdated(lView, bindingIndex++, values[i]) || isBindingUpdated;
26135
+ }
26136
+ setBindingIndex(bindingIndex);
26137
+ if (!isBindingUpdated) {
26138
+ return NO_CHANGE;
26139
+ }
26140
+ // Build the updated content
26141
+ let content = values[0];
26142
+ for (let i = 1; i < values.length; i += 2) {
26143
+ // The condition is to prevent an out-of-bound read
26144
+ content += renderStringify(values[i]) + (i + 1 !== values.length ? values[i + 1] : '');
26145
+ }
26146
+ return content;
26147
+ }
26148
+ /**
26149
+ * Creates an interpolation binding with 1 expression.
26150
+ *
26151
+ * @param prefix static value used for concatenation only.
26152
+ * @param v0 value checked for change.
26153
+ * @param suffix static value used for concatenation only.
26154
+ */
26155
+ function interpolation1(lView, prefix, v0, suffix = '') {
26156
+ const different = bindingUpdated(lView, nextBindingIndex(), v0);
26157
+ return different ? prefix + renderStringify(v0) + suffix : NO_CHANGE;
26158
+ }
26159
+ /**
26160
+ * Creates an interpolation binding with 2 expressions.
26161
+ */
26162
+ function interpolation2(lView, prefix, v0, i0, v1, suffix = '') {
26163
+ const bindingIndex = getBindingIndex();
26164
+ const different = bindingUpdated2(lView, bindingIndex, v0, v1);
26165
+ incrementBindingIndex(2);
26166
+ return different ? prefix + renderStringify(v0) + i0 + renderStringify(v1) + suffix : NO_CHANGE;
26167
+ }
26168
+ /**
26169
+ * Creates an interpolation binding with 3 expressions.
26170
+ */
26171
+ function interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix = '') {
26172
+ const bindingIndex = getBindingIndex();
26173
+ const different = bindingUpdated3(lView, bindingIndex, v0, v1, v2);
26174
+ incrementBindingIndex(3);
26175
+ return different
26176
+ ? prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 + renderStringify(v2) + suffix
26177
+ : NO_CHANGE;
26178
+ }
26179
+ /**
26180
+ * Create an interpolation binding with 4 expressions.
26181
+ */
26182
+ function interpolation4(lView, prefix, v0, i0, v1, i1, v2, i2, v3, suffix = '') {
26183
+ const bindingIndex = getBindingIndex();
26184
+ const different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);
26185
+ incrementBindingIndex(4);
26186
+ return different
26187
+ ? prefix +
26188
+ renderStringify(v0) +
26189
+ i0 +
26190
+ renderStringify(v1) +
26191
+ i1 +
26192
+ renderStringify(v2) +
26193
+ i2 +
26194
+ renderStringify(v3) +
26195
+ suffix
26196
+ : NO_CHANGE;
26197
+ }
26198
+ /**
26199
+ * Creates an interpolation binding with 5 expressions.
26200
+ */
26201
+ function interpolation5(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix = '') {
26202
+ const bindingIndex = getBindingIndex();
26203
+ let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);
26204
+ different = bindingUpdated(lView, bindingIndex + 4, v4) || different;
26205
+ incrementBindingIndex(5);
26206
+ return different
26207
+ ? prefix +
26208
+ renderStringify(v0) +
26209
+ i0 +
26210
+ renderStringify(v1) +
26211
+ i1 +
26212
+ renderStringify(v2) +
26213
+ i2 +
26214
+ renderStringify(v3) +
26215
+ i3 +
26216
+ renderStringify(v4) +
26217
+ suffix
26218
+ : NO_CHANGE;
26219
+ }
26220
+ /**
26221
+ * Creates an interpolation binding with 6 expressions.
26222
+ */
26223
+ function interpolation6(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix = '') {
26224
+ const bindingIndex = getBindingIndex();
26225
+ let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);
26226
+ different = bindingUpdated2(lView, bindingIndex + 4, v4, v5) || different;
26227
+ incrementBindingIndex(6);
26228
+ return different
26229
+ ? prefix +
26230
+ renderStringify(v0) +
26231
+ i0 +
26232
+ renderStringify(v1) +
26233
+ i1 +
26234
+ renderStringify(v2) +
26235
+ i2 +
26236
+ renderStringify(v3) +
26237
+ i3 +
26238
+ renderStringify(v4) +
26239
+ i4 +
26240
+ renderStringify(v5) +
26241
+ suffix
26242
+ : NO_CHANGE;
26243
+ }
26244
+ /**
26245
+ * Creates an interpolation binding with 7 expressions.
26246
+ */
26247
+ function interpolation7(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix = '') {
26248
+ const bindingIndex = getBindingIndex();
26249
+ let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);
26250
+ different = bindingUpdated3(lView, bindingIndex + 4, v4, v5, v6) || different;
26251
+ incrementBindingIndex(7);
26252
+ return different
26253
+ ? prefix +
26254
+ renderStringify(v0) +
26255
+ i0 +
26256
+ renderStringify(v1) +
26257
+ i1 +
26258
+ renderStringify(v2) +
26259
+ i2 +
26260
+ renderStringify(v3) +
26261
+ i3 +
26262
+ renderStringify(v4) +
26263
+ i4 +
26264
+ renderStringify(v5) +
26265
+ i5 +
26266
+ renderStringify(v6) +
26267
+ suffix
26268
+ : NO_CHANGE;
26269
+ }
26270
+ /**
26271
+ * Creates an interpolation binding with 8 expressions.
26272
+ */
26273
+ function interpolation8(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix = '') {
26274
+ const bindingIndex = getBindingIndex();
26275
+ let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);
26276
+ different = bindingUpdated4(lView, bindingIndex + 4, v4, v5, v6, v7) || different;
26277
+ incrementBindingIndex(8);
26278
+ return different
26279
+ ? prefix +
26280
+ renderStringify(v0) +
26281
+ i0 +
26282
+ renderStringify(v1) +
26283
+ i1 +
26284
+ renderStringify(v2) +
26285
+ i2 +
26286
+ renderStringify(v3) +
26287
+ i3 +
26288
+ renderStringify(v4) +
26289
+ i4 +
26290
+ renderStringify(v5) +
26291
+ i5 +
26292
+ renderStringify(v6) +
26293
+ i6 +
26294
+ renderStringify(v7) +
26295
+ suffix
26296
+ : NO_CHANGE;
26297
+ }
26298
+
27718
26299
  /**
27719
26300
  *
27720
26301
  * Update text content with a lone bound value
@@ -28176,7 +26757,9 @@ function ɵɵattachSourceLocations(templatePath, locations) {
28176
26757
  * @codeGenApi
28177
26758
  */
28178
26759
  function ɵɵinterpolate(v0) {
28179
- return interpolation1(getLView(), '', v0, '');
26760
+ // Avoid calling into the `interpolate` functions since
26761
+ // we know that we don't have a prefix or suffix.
26762
+ return bindingUpdated(getLView(), nextBindingIndex(), v0) ? renderStringify(v0) : NO_CHANGE;
28180
26763
  }
28181
26764
  /**
28182
26765
  * Interpolate a value with a single bound value.
@@ -29647,16 +28230,6 @@ const angularCoreEnv = (() => ({
29647
28230
  'ɵɵprojectionDef': ɵɵprojectionDef,
29648
28231
  'ɵɵdomProperty': ɵɵdomProperty,
29649
28232
  'ɵɵproperty': ɵɵproperty,
29650
- 'ɵɵpropertyInterpolate': ɵɵpropertyInterpolate,
29651
- 'ɵɵpropertyInterpolate1': ɵɵpropertyInterpolate1,
29652
- 'ɵɵpropertyInterpolate2': ɵɵpropertyInterpolate2,
29653
- 'ɵɵpropertyInterpolate3': ɵɵpropertyInterpolate3,
29654
- 'ɵɵpropertyInterpolate4': ɵɵpropertyInterpolate4,
29655
- 'ɵɵpropertyInterpolate5': ɵɵpropertyInterpolate5,
29656
- 'ɵɵpropertyInterpolate6': ɵɵpropertyInterpolate6,
29657
- 'ɵɵpropertyInterpolate7': ɵɵpropertyInterpolate7,
29658
- 'ɵɵpropertyInterpolate8': ɵɵpropertyInterpolate8,
29659
- 'ɵɵpropertyInterpolateV': ɵɵpropertyInterpolateV,
29660
28233
  'ɵɵpipe': ɵɵpipe,
29661
28234
  'ɵɵqueryRefresh': ɵɵqueryRefresh,
29662
28235
  'ɵɵqueryAdvance': ɵɵqueryAdvance,
@@ -29667,35 +28240,8 @@ const angularCoreEnv = (() => ({
29667
28240
  'ɵɵcontentQuerySignal': ɵɵcontentQuerySignal,
29668
28241
  'ɵɵreference': ɵɵreference,
29669
28242
  'ɵɵclassMap': ɵɵclassMap,
29670
- 'ɵɵclassMapInterpolate1': ɵɵclassMapInterpolate1,
29671
- 'ɵɵclassMapInterpolate2': ɵɵclassMapInterpolate2,
29672
- 'ɵɵclassMapInterpolate3': ɵɵclassMapInterpolate3,
29673
- 'ɵɵclassMapInterpolate4': ɵɵclassMapInterpolate4,
29674
- 'ɵɵclassMapInterpolate5': ɵɵclassMapInterpolate5,
29675
- 'ɵɵclassMapInterpolate6': ɵɵclassMapInterpolate6,
29676
- 'ɵɵclassMapInterpolate7': ɵɵclassMapInterpolate7,
29677
- 'ɵɵclassMapInterpolate8': ɵɵclassMapInterpolate8,
29678
- 'ɵɵclassMapInterpolateV': ɵɵclassMapInterpolateV,
29679
28243
  'ɵɵstyleMap': ɵɵstyleMap,
29680
- 'ɵɵstyleMapInterpolate1': ɵɵstyleMapInterpolate1,
29681
- 'ɵɵstyleMapInterpolate2': ɵɵstyleMapInterpolate2,
29682
- 'ɵɵstyleMapInterpolate3': ɵɵstyleMapInterpolate3,
29683
- 'ɵɵstyleMapInterpolate4': ɵɵstyleMapInterpolate4,
29684
- 'ɵɵstyleMapInterpolate5': ɵɵstyleMapInterpolate5,
29685
- 'ɵɵstyleMapInterpolate6': ɵɵstyleMapInterpolate6,
29686
- 'ɵɵstyleMapInterpolate7': ɵɵstyleMapInterpolate7,
29687
- 'ɵɵstyleMapInterpolate8': ɵɵstyleMapInterpolate8,
29688
- 'ɵɵstyleMapInterpolateV': ɵɵstyleMapInterpolateV,
29689
28244
  'ɵɵstyleProp': ɵɵstyleProp,
29690
- 'ɵɵstylePropInterpolate1': ɵɵstylePropInterpolate1,
29691
- 'ɵɵstylePropInterpolate2': ɵɵstylePropInterpolate2,
29692
- 'ɵɵstylePropInterpolate3': ɵɵstylePropInterpolate3,
29693
- 'ɵɵstylePropInterpolate4': ɵɵstylePropInterpolate4,
29694
- 'ɵɵstylePropInterpolate5': ɵɵstylePropInterpolate5,
29695
- 'ɵɵstylePropInterpolate6': ɵɵstylePropInterpolate6,
29696
- 'ɵɵstylePropInterpolate7': ɵɵstylePropInterpolate7,
29697
- 'ɵɵstylePropInterpolate8': ɵɵstylePropInterpolate8,
29698
- 'ɵɵstylePropInterpolateV': ɵɵstylePropInterpolateV,
29699
28245
  'ɵɵclassProp': ɵɵclassProp,
29700
28246
  'ɵɵadvance': ɵɵadvance,
29701
28247
  'ɵɵtemplate': ɵɵtemplate,
@@ -32177,5 +30723,5 @@ function getDebugNode(nativeNode) {
32177
30723
  return null;
32178
30724
  }
32179
30725
 
32180
- export { AFTER_RENDER_PHASES, ANIMATION_MODULE_TYPE, APP_BOOTSTRAP_LISTENER, APP_ID, APP_INITIALIZER, AcxChangeDetectionStrategy, AcxViewEncapsulation, AfterRenderImpl, AfterRenderManager, AfterRenderSequence, ApplicationInitStatus, ApplicationRef, Attribute, COMPILER_OPTIONS, CONTAINERS, CSP_NONCE, CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionSchedulerImpl, ChangeDetectionStrategy, Compiler, CompilerFactory, Component, ComponentFactory, ComponentFactory$1, ComponentFactoryResolver$1 as ComponentFactoryResolver, ComponentRef$1 as ComponentRef, ComponentRef as ComponentRef$1, Console, DEFAULT_CURRENCY_CODE, DEFAULT_LOCALE_ID, DEFER_BLOCK_CONFIG, DEFER_BLOCK_DEPENDENCY_INTERCEPTOR, DEFER_BLOCK_ID, DEFER_BLOCK_SSR_ID_ATTRIBUTE, DEFER_BLOCK_STATE$1 as DEFER_BLOCK_STATE, DEFER_BLOCK_STATE as DEFER_BLOCK_STATE$1, DEFER_HYDRATE_TRIGGERS, DEFER_PARENT_BLOCK_ID, DEHYDRATED_BLOCK_REGISTRY, DISCONNECTED_NODES, DebugElement, DebugEventListener, DebugNode, DeferBlockBehavior, DeferBlockState, DehydratedBlockRegistry, Directive, ELEMENT_CONTAINERS, EVENT_REPLAY_ENABLED_DEFAULT, ElementRef, EnvironmentNgModuleRefAdapter, EventEmitter, Framework, Host, HostBinding, HostListener, I18N_DATA, IMAGE_CONFIG, IMAGE_CONFIG_DEFAULTS, IS_EVENT_REPLAY_ENABLED, IS_HYDRATION_DOM_REUSE_ENABLED, IS_I18N_HYDRATION_ENABLED, IS_INCREMENTAL_HYDRATION_ENABLED, Inject, Injectable, Input, JSACTION_BLOCK_ELEMENT_MAP, JSACTION_EVENT_CONTRACT, LContext, LOCALE_ID, LocaleDataIndex, MULTIPLIER, MissingTranslationStrategy, ModuleWithComponentFactories, NGH_ATTR_NAME, NGH_DATA_KEY, NGH_DEFER_BLOCKS_KEY, NODES, NOOP_AFTER_RENDER_REF, NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR, NO_CHANGE, NO_ERRORS_SCHEMA, NUM_ROOT_NODES, NgModule, NgModuleFactory, NgModuleFactory$1, NgModuleRef, NgModuleRef$1, NgProbeToken, NgZone, NoopNgZone, Optional, Output, PACKAGE_ROOT_URL, PLATFORM_ID, PLATFORM_INITIALIZER, PRESERVE_HOST_CONTENT, PROVIDED_NG_ZONE, Pipe, QueryList, ReflectionCapabilities, Renderer2, RendererFactory2, RendererStyleFlags2, SKIP_HYDRATION_ATTR_NAME, SSR_CONTENT_INTEGRITY_MARKER, Sanitizer, SecurityContext, Self, SimpleChange, SkipSelf, TEMPLATES, TEMPLATE_ID, TESTABILITY, TESTABILITY_GETTER, TRANSLATIONS, TRANSLATIONS_FORMAT, TemplateRef, Testability, TestabilityRegistry, TracingAction, TracingService, TransferState, Type, UseExhaustiveCheckNoChanges, ViewContainerRef, ViewEncapsulation, ViewRef, _sanitizeHtml, _sanitizeUrl, afterEveryRender, afterNextRender, allowSanitizationBypassAndThrow, angularCoreEnv, appendDeferBlocksToJSActionMap, asNativeElements, assertComponentDef, assertStandaloneComponentType, bypassSanitizationTrustHtml, bypassSanitizationTrustResourceUrl, bypassSanitizationTrustScript, bypassSanitizationTrustStyle, bypassSanitizationTrustUrl, calcPathForNode, checkNoChangesInternal, cleanupDehydratedViews, clearResolutionOfComponentResourcesQueue, collectNativeNodes, collectNativeNodesInLContainer, compileComponent, compileDirective, compileNgModule, compileNgModuleDefs, compilePipe, convertHydrateTriggersToJsAction, countBlocksSkippedByHydration, createEnvironmentInjector, createMultiResultQuerySignalFn, createNgModule, createNgModuleRef, createNgModuleRefWithProviders, createSingleResultOptionalQuerySignalFn, createSingleResultRequiredQuerySignalFn, depsTracker, devModeEqual, enableApplyRootElementTransformImpl, enableClaimDehydratedIcuCaseImpl, enableFindMatchingDehydratedViewImpl, enableLocateOrCreateContainerAnchorImpl, enableLocateOrCreateContainerRefImpl, enableLocateOrCreateElementContainerNodeImpl, enableLocateOrCreateElementNodeImpl, enableLocateOrCreateI18nNodeImpl, enableLocateOrCreateTextNodeImpl, enablePrepareI18nBlockForHydrationImpl, enableProfiling, enableRetrieveDeferBlockDataImpl, enableRetrieveHydrationInfoImpl, enableStashEventListenerImpl, findLocaleData, flushModuleScopingQueueAsMuchAsPossible, gatherDeferBlocksCommentNodes, generateStandaloneInDeclarationsError, getAsyncClassMetadataFn, getCompilerFacade, getDebugNode, getDeferBlocks$1 as getDeferBlocks, getDirectives, getDocument, getHostElement, getLContext, getLDeferBlockDetails, getLNodeForHydration, getLocaleCurrencyCode, getLocalePluralCase, getNgZone, getNgZoneOptions, getOrComputeI18nChildren, getRegisteredNgModuleType, getSanitizationBypassType, getTDeferBlockDetails, inputBinding, internalProvideZoneChangeDetection, invokeListeners, isBoundToModule, isComponentDefPendingResolution, isComponentResourceResolutionQueueEmpty, isDeferBlock, isDetachedByI18n, isDisconnectedNode, isI18nHydrationEnabled, isI18nHydrationSupportEnabled, isInSkipHydrationBlock, isIncrementalHydrationEnabled, isJsObject, isLetDeclaration, isListLikeIterable, isNgModule, isPromise, isSubscribable, isTNodeShape, isViewDirty, iterateListLike, makePropDecorator, makeStateKey, markForRefresh, noSideEffects, optionsReducer, outputBinding, patchComponentDefWithScope, performanceMarkFeature, processAndInitTriggers, processBlockData, processTextNodeBeforeSerialization, profiler, provideAppInitializer, provideNgReflectAttributes, provideZoneChangeDetection, provideZonelessChangeDetection, publishDefaultGlobalUtils, publishExternalGlobalUtil, publishSignalConfiguration, readHydrationInfo, readPatchedLView, registerLocaleData, registerNgModuleType, remove, removeListeners, renderDeferBlockState, resetCompiledComponents, resetJitOptions, resolveComponentResources, restoreComponentResolutionQueue, setAllowDuplicateNgModuleIdsForTest, setClassMetadata, setClassMetadataAsync, setDocument, setIsI18nHydrationSupportEnabled, setJSActionAttributes, setJitOptions, setLocaleId, setStashFn, setTestabilityGetter, sharedMapFunction, sharedStashFunction, transitiveScopesFor, triggerHydrationFromBlockName, triggerResourceLoading, trySerializeI18nBlock, twoWayBinding, unregisterAllLocaleData, unsupportedProjectionOfDomNodes, unwrapSafeValue, validateMatchingNode, validateNodeExists, verifySsrContentsIntegrity, ɵgetUnknownElementStrictMode, ɵgetUnknownPropertyStrictMode, ɵsetClassDebugInfo, ɵsetUnknownElementStrictMode, ɵsetUnknownPropertyStrictMode, ɵɵCopyDefinitionFeature, ɵɵExternalStylesFeature, ɵɵHostDirectivesFeature, ɵɵInheritDefinitionFeature, ɵɵNgOnChangesFeature, ɵɵProvidersFeature, ɵɵadvance, ɵɵattachSourceLocations, ɵɵattribute, ɵɵclassMap, ɵɵclassMapInterpolate1, ɵɵclassMapInterpolate2, ɵɵclassMapInterpolate3, ɵɵclassMapInterpolate4, ɵɵclassMapInterpolate5, ɵɵclassMapInterpolate6, ɵɵclassMapInterpolate7, ɵɵclassMapInterpolate8, ɵɵclassMapInterpolateV, ɵɵclassProp, ɵɵcomponentInstance, ɵɵconditional, ɵɵconditionalBranchCreate, ɵɵconditionalCreate, ɵɵcontentQuery, ɵɵcontentQuerySignal, ɵɵdeclareLet, ɵɵdefer, ɵɵdeferEnableTimerScheduling, ɵɵdeferHydrateNever, ɵɵdeferHydrateOnHover, ɵɵdeferHydrateOnIdle, ɵɵdeferHydrateOnImmediate, ɵɵdeferHydrateOnInteraction, ɵɵdeferHydrateOnTimer, ɵɵdeferHydrateOnViewport, ɵɵdeferHydrateWhen, ɵɵdeferOnHover, ɵɵdeferOnIdle, ɵɵdeferOnImmediate, ɵɵdeferOnInteraction, ɵɵdeferOnTimer, ɵɵdeferOnViewport, ɵɵdeferPrefetchOnHover, ɵɵdeferPrefetchOnIdle, ɵɵdeferPrefetchOnImmediate, ɵɵdeferPrefetchOnInteraction, ɵɵdeferPrefetchOnTimer, ɵɵdeferPrefetchOnViewport, ɵɵdeferPrefetchWhen, ɵɵdeferWhen, ɵɵdefineComponent, ɵɵdefineDirective, ɵɵdefineNgModule, ɵɵdefinePipe, ɵɵdirectiveInject, ɵɵdomProperty, ɵɵelement, ɵɵelementContainer, ɵɵelementContainerEnd, ɵɵelementContainerStart, ɵɵelementEnd, ɵɵelementStart, ɵɵgetComponentDepsFactory, ɵɵgetCurrentView, ɵɵgetInheritedFactory, ɵɵgetReplaceMetadataURL, ɵɵi18n, ɵɵi18nApply, ɵɵi18nAttributes, ɵɵi18nEnd, ɵɵi18nExp, ɵɵi18nPostprocess, ɵɵi18nStart, ɵɵinjectAttribute, ɵɵinterpolate, ɵɵinterpolate1, ɵɵinterpolate2, ɵɵinterpolate3, ɵɵinterpolate4, ɵɵinterpolate5, ɵɵinterpolate6, ɵɵinterpolate7, ɵɵinterpolate8, ɵɵinterpolateV, ɵɵinvalidFactory, ɵɵlistener, ɵɵloadQuery, ɵɵnextContext, ɵɵpipe, ɵɵpipeBind1, ɵɵpipeBind2, ɵɵpipeBind3, ɵɵpipeBind4, ɵɵpipeBindV, ɵɵprojection, ɵɵprojectionDef, ɵɵproperty, ɵɵpropertyInterpolate, ɵɵpropertyInterpolate1, ɵɵpropertyInterpolate2, ɵɵpropertyInterpolate3, ɵɵpropertyInterpolate4, ɵɵpropertyInterpolate5, ɵɵpropertyInterpolate6, ɵɵpropertyInterpolate7, ɵɵpropertyInterpolate8, ɵɵpropertyInterpolateV, ɵɵpureFunction0, ɵɵpureFunction1, ɵɵpureFunction2, ɵɵpureFunction3, ɵɵpureFunction4, ɵɵpureFunction5, ɵɵpureFunction6, ɵɵpureFunction7, ɵɵpureFunction8, ɵɵpureFunctionV, ɵɵqueryAdvance, ɵɵqueryRefresh, ɵɵreadContextLet, ɵɵreference, ɵɵrepeater, ɵɵrepeaterCreate, ɵɵrepeaterTrackByIdentity, ɵɵrepeaterTrackByIndex, ɵɵreplaceMetadata, ɵɵresolveBody, ɵɵresolveDocument, ɵɵresolveWindow, ɵɵsanitizeHtml, ɵɵsanitizeResourceUrl, ɵɵsanitizeScript, ɵɵsanitizeStyle, ɵɵsanitizeUrl, ɵɵsanitizeUrlOrResourceUrl, ɵɵsetComponentScope, ɵɵsetNgModuleScope, ɵɵstoreLet, ɵɵstyleMap, ɵɵstyleMapInterpolate1, ɵɵstyleMapInterpolate2, ɵɵstyleMapInterpolate3, ɵɵstyleMapInterpolate4, ɵɵstyleMapInterpolate5, ɵɵstyleMapInterpolate6, ɵɵstyleMapInterpolate7, ɵɵstyleMapInterpolate8, ɵɵstyleMapInterpolateV, ɵɵstyleProp, ɵɵstylePropInterpolate1, ɵɵstylePropInterpolate2, ɵɵstylePropInterpolate3, ɵɵstylePropInterpolate4, ɵɵstylePropInterpolate5, ɵɵstylePropInterpolate6, ɵɵstylePropInterpolate7, ɵɵstylePropInterpolate8, ɵɵstylePropInterpolateV, ɵɵsyntheticHostListener, ɵɵsyntheticHostProperty, ɵɵtemplate, ɵɵtemplateRefExtractor, ɵɵtext, ɵɵtextInterpolate, ɵɵtextInterpolate1, ɵɵtextInterpolate2, ɵɵtextInterpolate3, ɵɵtextInterpolate4, ɵɵtextInterpolate5, ɵɵtextInterpolate6, ɵɵtextInterpolate7, ɵɵtextInterpolate8, ɵɵtextInterpolateV, ɵɵtrustConstantHtml, ɵɵtrustConstantResourceUrl, ɵɵtwoWayBindingSet, ɵɵtwoWayListener, ɵɵtwoWayProperty, ɵɵvalidateIframeAttribute, ɵɵviewQuery, ɵɵviewQuerySignal };
32181
- //# sourceMappingURL=debug_node-Nc-zr65s.mjs.map
30726
+ export { AFTER_RENDER_PHASES, ANIMATION_MODULE_TYPE, APP_BOOTSTRAP_LISTENER, APP_ID, APP_INITIALIZER, AcxChangeDetectionStrategy, AcxViewEncapsulation, AfterRenderImpl, AfterRenderManager, AfterRenderSequence, ApplicationInitStatus, ApplicationRef, Attribute, COMPILER_OPTIONS, CONTAINERS, CSP_NONCE, CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionSchedulerImpl, ChangeDetectionStrategy, Compiler, CompilerFactory, Component, ComponentFactory, ComponentFactory$1, ComponentFactoryResolver$1 as ComponentFactoryResolver, ComponentRef$1 as ComponentRef, ComponentRef as ComponentRef$1, Console, DEFAULT_CURRENCY_CODE, DEFAULT_LOCALE_ID, DEFER_BLOCK_CONFIG, DEFER_BLOCK_DEPENDENCY_INTERCEPTOR, DEFER_BLOCK_ID, DEFER_BLOCK_SSR_ID_ATTRIBUTE, DEFER_BLOCK_STATE$1 as DEFER_BLOCK_STATE, DEFER_BLOCK_STATE as DEFER_BLOCK_STATE$1, DEFER_HYDRATE_TRIGGERS, DEFER_PARENT_BLOCK_ID, DEHYDRATED_BLOCK_REGISTRY, DISCONNECTED_NODES, DebugElement, DebugEventListener, DebugNode, DeferBlockBehavior, DeferBlockState, DehydratedBlockRegistry, Directive, ELEMENT_CONTAINERS, EVENT_REPLAY_ENABLED_DEFAULT, ElementRef, EnvironmentNgModuleRefAdapter, EventEmitter, Framework, Host, HostBinding, HostListener, HydrationStatus, I18N_DATA, IMAGE_CONFIG, IMAGE_CONFIG_DEFAULTS, IS_EVENT_REPLAY_ENABLED, IS_HYDRATION_DOM_REUSE_ENABLED, IS_I18N_HYDRATION_ENABLED, IS_INCREMENTAL_HYDRATION_ENABLED, Inject, Injectable, Input, JSACTION_BLOCK_ELEMENT_MAP, JSACTION_EVENT_CONTRACT, LContext, LOCALE_ID, LocaleDataIndex, MULTIPLIER, MissingTranslationStrategy, ModuleWithComponentFactories, NGH_ATTR_NAME, NGH_DATA_KEY, NGH_DEFER_BLOCKS_KEY, NODES, NOOP_AFTER_RENDER_REF, NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR, NO_CHANGE, NO_ERRORS_SCHEMA, NUM_ROOT_NODES, NgModule, NgModuleFactory, NgModuleFactory$1, NgModuleRef, NgModuleRef$1, NgProbeToken, NgZone, NoopNgZone, Optional, Output, PACKAGE_ROOT_URL, PLATFORM_ID, PLATFORM_INITIALIZER, PRESERVE_HOST_CONTENT, PROVIDED_NG_ZONE, Pipe, QueryList, ReflectionCapabilities, Renderer2, RendererFactory2, RendererStyleFlags2, SKIP_HYDRATION_ATTR_NAME, SSR_CONTENT_INTEGRITY_MARKER, Sanitizer, SecurityContext, Self, SimpleChange, SkipSelf, TEMPLATES, TEMPLATE_ID, TESTABILITY, TESTABILITY_GETTER, TRANSLATIONS, TRANSLATIONS_FORMAT, TemplateRef, Testability, TestabilityRegistry, TimerScheduler, TracingAction, TracingService, TransferState, Type, UseExhaustiveCheckNoChanges, ViewContainerRef, ViewEncapsulation, ViewRef, _sanitizeHtml, _sanitizeUrl, afterEveryRender, afterNextRender, allowSanitizationBypassAndThrow, angularCoreEnv, appendDeferBlocksToJSActionMap, asNativeElements, assertComponentDef, assertStandaloneComponentType, bypassSanitizationTrustHtml, bypassSanitizationTrustResourceUrl, bypassSanitizationTrustScript, bypassSanitizationTrustStyle, bypassSanitizationTrustUrl, calcPathForNode, checkNoChangesInternal, cleanupDehydratedViews, clearResolutionOfComponentResourcesQueue, collectNativeNodes, collectNativeNodesInLContainer, compileComponent, compileDirective, compileNgModule, compileNgModuleDefs, compilePipe, convertHydrateTriggersToJsAction, countBlocksSkippedByHydration, createEnvironmentInjector, createMultiResultQuerySignalFn, createNgModule, createNgModuleRef, createNgModuleRefWithProviders, createSingleResultOptionalQuerySignalFn, createSingleResultRequiredQuerySignalFn, depsTracker, devModeEqual, enableApplyRootElementTransformImpl, enableClaimDehydratedIcuCaseImpl, enableFindMatchingDehydratedViewImpl, enableLocateOrCreateContainerAnchorImpl, enableLocateOrCreateContainerRefImpl, enableLocateOrCreateElementContainerNodeImpl, enableLocateOrCreateElementNodeImpl, enableLocateOrCreateI18nNodeImpl, enableLocateOrCreateTextNodeImpl, enablePrepareI18nBlockForHydrationImpl, enableProfiling, enableRetrieveDeferBlockDataImpl, enableRetrieveHydrationInfoImpl, enableStashEventListenerImpl, findLocaleData, flushModuleScopingQueueAsMuchAsPossible, gatherDeferBlocksCommentNodes, generateStandaloneInDeclarationsError, getAsyncClassMetadataFn, getCompilerFacade, getDebugNode, getDeferBlocks$1 as getDeferBlocks, getDirectives, getDocument, getHostElement, getLContext, getLDeferBlockDetails, getLNodeForHydration, getLocaleCurrencyCode, getLocalePluralCase, getNgZone, getNgZoneOptions, getOrComputeI18nChildren, getRegisteredNgModuleType, getSanitizationBypassType, getTDeferBlockDetails, inputBinding, internalProvideZoneChangeDetection, invokeListeners, isBoundToModule, isComponentDefPendingResolution, isComponentResourceResolutionQueueEmpty, isDeferBlock, isDetachedByI18n, isDisconnectedNode, isI18nHydrationEnabled, isI18nHydrationSupportEnabled, isInSkipHydrationBlock, isIncrementalHydrationEnabled, isJsObject, isLetDeclaration, isListLikeIterable, isNgModule, isPromise, isSubscribable, isTNodeShape, isViewDirty, iterateListLike, makePropDecorator, makeStateKey, markForRefresh, noSideEffects, optionsReducer, outputBinding, patchComponentDefWithScope, performanceMarkFeature, processAndInitTriggers, processBlockData, processTextNodeBeforeSerialization, profiler, provideAppInitializer, provideNgReflectAttributes, provideZoneChangeDetection, provideZonelessChangeDetection, publishDefaultGlobalUtils, publishExternalGlobalUtil, publishSignalConfiguration, readHydrationInfo, readPatchedLView, registerLocaleData, registerNgModuleType, remove, removeListeners, renderDeferBlockState, resetCompiledComponents, resetJitOptions, resolveComponentResources, restoreComponentResolutionQueue, setAllowDuplicateNgModuleIdsForTest, setClassMetadata, setClassMetadataAsync, setDocument, setIsI18nHydrationSupportEnabled, setJSActionAttributes, setJitOptions, setLocaleId, setStashFn, setTestabilityGetter, sharedMapFunction, sharedStashFunction, transitiveScopesFor, triggerHydrationFromBlockName, triggerResourceLoading, trySerializeI18nBlock, twoWayBinding, unregisterAllLocaleData, unsupportedProjectionOfDomNodes, unwrapSafeValue, validateMatchingNode, validateNodeExists, verifySsrContentsIntegrity, ɵgetUnknownElementStrictMode, ɵgetUnknownPropertyStrictMode, ɵsetClassDebugInfo, ɵsetUnknownElementStrictMode, ɵsetUnknownPropertyStrictMode, ɵɵCopyDefinitionFeature, ɵɵExternalStylesFeature, ɵɵHostDirectivesFeature, ɵɵInheritDefinitionFeature, ɵɵNgOnChangesFeature, ɵɵProvidersFeature, ɵɵadvance, ɵɵattachSourceLocations, ɵɵattribute, ɵɵclassMap, ɵɵclassProp, ɵɵcomponentInstance, ɵɵconditional, ɵɵconditionalBranchCreate, ɵɵconditionalCreate, ɵɵcontentQuery, ɵɵcontentQuerySignal, ɵɵdeclareLet, ɵɵdefer, ɵɵdeferEnableTimerScheduling, ɵɵdeferHydrateNever, ɵɵdeferHydrateOnHover, ɵɵdeferHydrateOnIdle, ɵɵdeferHydrateOnImmediate, ɵɵdeferHydrateOnInteraction, ɵɵdeferHydrateOnTimer, ɵɵdeferHydrateOnViewport, ɵɵdeferHydrateWhen, ɵɵdeferOnHover, ɵɵdeferOnIdle, ɵɵdeferOnImmediate, ɵɵdeferOnInteraction, ɵɵdeferOnTimer, ɵɵdeferOnViewport, ɵɵdeferPrefetchOnHover, ɵɵdeferPrefetchOnIdle, ɵɵdeferPrefetchOnImmediate, ɵɵdeferPrefetchOnInteraction, ɵɵdeferPrefetchOnTimer, ɵɵdeferPrefetchOnViewport, ɵɵdeferPrefetchWhen, ɵɵdeferWhen, ɵɵdefineComponent, ɵɵdefineDirective, ɵɵdefineNgModule, ɵɵdefinePipe, ɵɵdirectiveInject, ɵɵdomProperty, ɵɵelement, ɵɵelementContainer, ɵɵelementContainerEnd, ɵɵelementContainerStart, ɵɵelementEnd, ɵɵelementStart, ɵɵgetComponentDepsFactory, ɵɵgetCurrentView, ɵɵgetInheritedFactory, ɵɵgetReplaceMetadataURL, ɵɵi18n, ɵɵi18nApply, ɵɵi18nAttributes, ɵɵi18nEnd, ɵɵi18nExp, ɵɵi18nPostprocess, ɵɵi18nStart, ɵɵinjectAttribute, ɵɵinterpolate, ɵɵinterpolate1, ɵɵinterpolate2, ɵɵinterpolate3, ɵɵinterpolate4, ɵɵinterpolate5, ɵɵinterpolate6, ɵɵinterpolate7, ɵɵinterpolate8, ɵɵinterpolateV, ɵɵinvalidFactory, ɵɵlistener, ɵɵloadQuery, ɵɵnextContext, ɵɵpipe, ɵɵpipeBind1, ɵɵpipeBind2, ɵɵpipeBind3, ɵɵpipeBind4, ɵɵpipeBindV, ɵɵprojection, ɵɵprojectionDef, ɵɵproperty, ɵɵpureFunction0, ɵɵpureFunction1, ɵɵpureFunction2, ɵɵpureFunction3, ɵɵpureFunction4, ɵɵpureFunction5, ɵɵpureFunction6, ɵɵpureFunction7, ɵɵpureFunction8, ɵɵpureFunctionV, ɵɵqueryAdvance, ɵɵqueryRefresh, ɵɵreadContextLet, ɵɵreference, ɵɵrepeater, ɵɵrepeaterCreate, ɵɵrepeaterTrackByIdentity, ɵɵrepeaterTrackByIndex, ɵɵreplaceMetadata, ɵɵresolveBody, ɵɵresolveDocument, ɵɵresolveWindow, ɵɵsanitizeHtml, ɵɵsanitizeResourceUrl, ɵɵsanitizeScript, ɵɵsanitizeStyle, ɵɵsanitizeUrl, ɵɵsanitizeUrlOrResourceUrl, ɵɵsetComponentScope, ɵɵsetNgModuleScope, ɵɵstoreLet, ɵɵstyleMap, ɵɵstyleProp, ɵɵsyntheticHostListener, ɵɵsyntheticHostProperty, ɵɵtemplate, ɵɵtemplateRefExtractor, ɵɵtext, ɵɵtextInterpolate, ɵɵtextInterpolate1, ɵɵtextInterpolate2, ɵɵtextInterpolate3, ɵɵtextInterpolate4, ɵɵtextInterpolate5, ɵɵtextInterpolate6, ɵɵtextInterpolate7, ɵɵtextInterpolate8, ɵɵtextInterpolateV, ɵɵtrustConstantHtml, ɵɵtrustConstantResourceUrl, ɵɵtwoWayBindingSet, ɵɵtwoWayListener, ɵɵtwoWayProperty, ɵɵvalidateIframeAttribute, ɵɵviewQuery, ɵɵviewQuerySignal };
30727
+ //# sourceMappingURL=debug_node-Dn-GvQJo.mjs.map