@angular/core 14.1.0-next.3 → 14.1.0-next.4

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 (41) hide show
  1. package/esm2020/src/application_ref.mjs +1 -1
  2. package/esm2020/src/core.mjs +1 -1
  3. package/esm2020/src/core_render3_private_export.mjs +2 -2
  4. package/esm2020/src/debug/debug_node.mjs +2 -3
  5. package/esm2020/src/di/index.mjs +1 -1
  6. package/esm2020/src/di/injector_compatibility.mjs +11 -1
  7. package/esm2020/src/di/interface/injector.mjs +2 -1
  8. package/esm2020/src/di/r3_injector.mjs +13 -1
  9. package/esm2020/src/errors.mjs +1 -1
  10. package/esm2020/src/linker/component_factory.mjs +1 -1
  11. package/esm2020/src/metadata/di.mjs +1 -1
  12. package/esm2020/src/render/api.mjs +2 -11
  13. package/esm2020/src/render3/component.mjs +3 -58
  14. package/esm2020/src/render3/component_ref.mjs +30 -5
  15. package/esm2020/src/render3/index.mjs +3 -3
  16. package/esm2020/src/render3/instructions/element_validation.mjs +4 -1
  17. package/esm2020/src/render3/instructions/listener.mjs +34 -44
  18. package/esm2020/src/render3/instructions/lview_debug.mjs +1 -1
  19. package/esm2020/src/render3/instructions/shared.mjs +22 -59
  20. package/esm2020/src/render3/instructions/styling.mjs +2 -2
  21. package/esm2020/src/render3/interfaces/renderer.mjs +1 -26
  22. package/esm2020/src/render3/interfaces/view.mjs +1 -1
  23. package/esm2020/src/render3/ng_module_ref.mjs +4 -1
  24. package/esm2020/src/render3/node_manipulation.mjs +24 -87
  25. package/esm2020/src/render3/node_manipulation_i18n.mjs +1 -1
  26. package/esm2020/src/render3/util/attrs_utils.mjs +4 -12
  27. package/esm2020/src/render3/util/view_utils.mjs +3 -6
  28. package/esm2020/src/version.mjs +1 -1
  29. package/esm2020/testing/src/logger.mjs +3 -3
  30. package/esm2020/testing/src/ng_zone_mock.mjs +3 -3
  31. package/fesm2015/core.mjs +1798 -1946
  32. package/fesm2015/core.mjs.map +1 -1
  33. package/fesm2015/testing.mjs +1429 -1669
  34. package/fesm2015/testing.mjs.map +1 -1
  35. package/fesm2020/core.mjs +1798 -1946
  36. package/fesm2020/core.mjs.map +1 -1
  37. package/fesm2020/testing.mjs +1429 -1669
  38. package/fesm2020/testing.mjs.map +1 -1
  39. package/index.d.ts +138 -128
  40. package/package.json +1 -1
  41. package/testing/index.d.ts +1 -1
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Angular v14.1.0-next.3
2
+ * @license Angular v14.1.0-next.4
3
3
  * (c) 2010-2022 Google LLC. https://angular.io/
4
4
  * License: MIT
5
5
  */
@@ -1933,6 +1933,7 @@ function throwProviderNotFoundError(token, injectorName) {
1933
1933
  * Injection flags for DI.
1934
1934
  *
1935
1935
  * @publicApi
1936
+ * @deprecated use an options object for `inject` instead.
1936
1937
  */
1937
1938
  var InjectFlags;
1938
1939
  (function (InjectFlags) {
@@ -2140,6 +2141,16 @@ Please check that 1) the type for the parameter at index ${index} is correct and
2140
2141
  * @publicApi
2141
2142
  */
2142
2143
  function inject$1(token, flags = InjectFlags.Default) {
2144
+ if (typeof flags !== 'number') {
2145
+ // While TypeScript doesn't accept it without a cast, bitwise OR with false-y values in
2146
+ // JavaScript is a no-op. We can use that for a very codesize-efficient conversion from
2147
+ // `InjectOptions` to `InjectFlags`.
2148
+ flags = (0 /* InternalInjectFlags.Default */ | // comment to force a line break in the formatter
2149
+ (flags.optional && 8 /* InternalInjectFlags.Optional */) |
2150
+ (flags.host && 1 /* InternalInjectFlags.Host */) |
2151
+ (flags.self && 2 /* InternalInjectFlags.Self */) |
2152
+ (flags.skipSelf && 4 /* InternalInjectFlags.SkipSelf */));
2153
+ }
2143
2154
  return ɵɵinject(token, flags);
2144
2155
  }
2145
2156
  function injectArgs(types) {
@@ -3183,96 +3194,6 @@ function getNamespaceUri(namespace) {
3183
3194
  (name === MATH_ML_NAMESPACE ? MATH_ML_NAMESPACE_URI : null);
3184
3195
  }
3185
3196
 
3186
- /**
3187
- * @license
3188
- * Copyright Google LLC All Rights Reserved.
3189
- *
3190
- * Use of this source code is governed by an MIT-style license that can be
3191
- * found in the LICENSE file at https://angular.io/license
3192
- */
3193
- /**
3194
- * Most of the use of `document` in Angular is from within the DI system so it is possible to simply
3195
- * inject the `DOCUMENT` token and are done.
3196
- *
3197
- * Ivy is special because it does not rely upon the DI and must get hold of the document some other
3198
- * way.
3199
- *
3200
- * The solution is to define `getDocument()` and `setDocument()` top-level functions for ivy.
3201
- * Wherever ivy needs the global document, it calls `getDocument()` instead.
3202
- *
3203
- * When running ivy outside of a browser environment, it is necessary to call `setDocument()` to
3204
- * tell ivy what the global `document` is.
3205
- *
3206
- * Angular does this for us in each of the standard platforms (`Browser`, `Server`, and `WebWorker`)
3207
- * by calling `setDocument()` when providing the `DOCUMENT` token.
3208
- */
3209
- let DOCUMENT = undefined;
3210
- /**
3211
- * Tell ivy what the `document` is for this platform.
3212
- *
3213
- * It is only necessary to call this if the current platform is not a browser.
3214
- *
3215
- * @param document The object representing the global `document` in this environment.
3216
- */
3217
- function setDocument(document) {
3218
- DOCUMENT = document;
3219
- }
3220
- /**
3221
- * Access the object that represents the `document` for this platform.
3222
- *
3223
- * Ivy calls this whenever it needs to access the `document` object.
3224
- * For example to create the renderer or to do sanitization.
3225
- */
3226
- function getDocument() {
3227
- if (DOCUMENT !== undefined) {
3228
- return DOCUMENT;
3229
- }
3230
- else if (typeof document !== 'undefined') {
3231
- return document;
3232
- }
3233
- // No "document" can be found. This should only happen if we are running ivy outside Angular and
3234
- // the current platform is not a browser. Since this is not a supported scenario at the moment
3235
- // this should not happen in Angular apps.
3236
- // Once we support running ivy outside of Angular we will need to publish `setDocument()` as a
3237
- // public API. Meanwhile we just return `undefined` and let the application fail.
3238
- return undefined;
3239
- }
3240
-
3241
- /**
3242
- * @license
3243
- * Copyright Google LLC All Rights Reserved.
3244
- *
3245
- * Use of this source code is governed by an MIT-style license that can be
3246
- * found in the LICENSE file at https://angular.io/license
3247
- */
3248
- // TODO: cleanup once the code is merged in angular/angular
3249
- var RendererStyleFlags3;
3250
- (function (RendererStyleFlags3) {
3251
- RendererStyleFlags3[RendererStyleFlags3["Important"] = 1] = "Important";
3252
- RendererStyleFlags3[RendererStyleFlags3["DashCase"] = 2] = "DashCase";
3253
- })(RendererStyleFlags3 || (RendererStyleFlags3 = {}));
3254
- /** Returns whether the `renderer` is a `ProceduralRenderer3` */
3255
- function isProceduralRenderer(renderer) {
3256
- return !!(renderer.listen);
3257
- }
3258
- let renderer3Enabled = false;
3259
- function enableRenderer3() {
3260
- renderer3Enabled = true;
3261
- }
3262
- const domRendererFactory3 = {
3263
- createRenderer: (hostElement, rendererType) => {
3264
- if (!renderer3Enabled) {
3265
- throw new Error(ngDevMode ?
3266
- `Renderer3 is not supported. This problem is likely caused by some component in the hierarchy was constructed without a correct parent injector.` :
3267
- 'Renderer3 disabled');
3268
- }
3269
- return getDocument();
3270
- }
3271
- };
3272
- // Note: This hack is necessary so we don't erroneously get a circular dependency
3273
- // failure based on types.
3274
- const unusedValueExportToPlacateAjd$6 = 1;
3275
-
3276
3197
  /**
3277
3198
  * @license
3278
3199
  * Copyright Google LLC All Rights Reserved.
@@ -3355,7 +3276,6 @@ function getNativeByTNode(tNode, lView) {
3355
3276
  ngDevMode && assertTNodeForLView(tNode, lView);
3356
3277
  ngDevMode && assertIndexInRange(lView, tNode.index);
3357
3278
  const node = unwrapRNode(lView[tNode.index]);
3358
- ngDevMode && !isProceduralRenderer(lView[RENDERER]) && assertDomNode(node);
3359
3279
  return node;
3360
3280
  }
3361
3281
  /**
@@ -3371,7 +3291,6 @@ function getNativeByTNodeOrNull(tNode, lView) {
3371
3291
  if (index !== -1) {
3372
3292
  ngDevMode && assertTNodeForLView(tNode, lView);
3373
3293
  const node = unwrapRNode(lView[index]);
3374
- ngDevMode && node !== null && !isProceduralRenderer(lView[RENDERER]) && assertDomNode(node);
3375
3294
  return node;
3376
3295
  }
3377
3296
  return null;
@@ -4320,7 +4239,7 @@ function isFactory(obj) {
4320
4239
  }
4321
4240
  // Note: This hack is necessary so we don't erroneously get a circular dependency
4322
4241
  // failure based on types.
4323
- const unusedValueExportToPlacateAjd$5 = 1;
4242
+ const unusedValueExportToPlacateAjd$6 = 1;
4324
4243
 
4325
4244
  /**
4326
4245
  * Converts `TNodeType` into human readable text.
@@ -4339,7 +4258,7 @@ function toTNodeTypeAsString(tNodeType) {
4339
4258
  }
4340
4259
  // Note: This hack is necessary so we don't erroneously get a circular dependency
4341
4260
  // failure based on types.
4342
- const unusedValueExportToPlacateAjd$4 = 1;
4261
+ const unusedValueExportToPlacateAjd$5 = 1;
4343
4262
  /**
4344
4263
  * Returns `true` if the `TNode` has a directive which has `@Input()` for `class` binding.
4345
4264
  *
@@ -4443,7 +4362,6 @@ function assertPureTNodeType(type) {
4443
4362
  * @returns the index value that was last accessed in the attributes array
4444
4363
  */
4445
4364
  function setUpAttributes(renderer, native, attrs) {
4446
- const isProc = isProceduralRenderer(renderer);
4447
4365
  let i = 0;
4448
4366
  while (i < attrs.length) {
4449
4367
  const value = attrs[i];
@@ -4460,9 +4378,7 @@ function setUpAttributes(renderer, native, attrs) {
4460
4378
  const attrName = attrs[i++];
4461
4379
  const attrVal = attrs[i++];
4462
4380
  ngDevMode && ngDevMode.rendererSetAttribute++;
4463
- isProc ?
4464
- renderer.setAttribute(native, attrName, attrVal, namespaceURI) :
4465
- native.setAttributeNS(namespaceURI, attrName, attrVal);
4381
+ renderer.setAttribute(native, attrName, attrVal, namespaceURI);
4466
4382
  }
4467
4383
  else {
4468
4384
  // attrName is string;
@@ -4471,14 +4387,10 @@ function setUpAttributes(renderer, native, attrs) {
4471
4387
  // Standard attributes
4472
4388
  ngDevMode && ngDevMode.rendererSetAttribute++;
4473
4389
  if (isAnimationProp(attrName)) {
4474
- if (isProc) {
4475
- renderer.setProperty(native, attrName, attrVal);
4476
- }
4390
+ renderer.setProperty(native, attrName, attrVal);
4477
4391
  }
4478
4392
  else {
4479
- isProc ?
4480
- renderer.setAttribute(native, attrName, attrVal) :
4481
- native.setAttribute(attrName, attrVal);
4393
+ renderer.setAttribute(native, attrName, attrVal);
4482
4394
  }
4483
4395
  i++;
4484
4396
  }
@@ -5612,6 +5524,61 @@ function maybeUnwrapFn$1(value) {
5612
5524
  }
5613
5525
  }
5614
5526
 
5527
+ /**
5528
+ * @license
5529
+ * Copyright Google LLC All Rights Reserved.
5530
+ *
5531
+ * Use of this source code is governed by an MIT-style license that can be
5532
+ * found in the LICENSE file at https://angular.io/license
5533
+ */
5534
+ /**
5535
+ * Most of the use of `document` in Angular is from within the DI system so it is possible to simply
5536
+ * inject the `DOCUMENT` token and are done.
5537
+ *
5538
+ * Ivy is special because it does not rely upon the DI and must get hold of the document some other
5539
+ * way.
5540
+ *
5541
+ * The solution is to define `getDocument()` and `setDocument()` top-level functions for ivy.
5542
+ * Wherever ivy needs the global document, it calls `getDocument()` instead.
5543
+ *
5544
+ * When running ivy outside of a browser environment, it is necessary to call `setDocument()` to
5545
+ * tell ivy what the global `document` is.
5546
+ *
5547
+ * Angular does this for us in each of the standard platforms (`Browser`, `Server`, and `WebWorker`)
5548
+ * by calling `setDocument()` when providing the `DOCUMENT` token.
5549
+ */
5550
+ let DOCUMENT = undefined;
5551
+ /**
5552
+ * Tell ivy what the `document` is for this platform.
5553
+ *
5554
+ * It is only necessary to call this if the current platform is not a browser.
5555
+ *
5556
+ * @param document The object representing the global `document` in this environment.
5557
+ */
5558
+ function setDocument(document) {
5559
+ DOCUMENT = document;
5560
+ }
5561
+ /**
5562
+ * Access the object that represents the `document` for this platform.
5563
+ *
5564
+ * Ivy calls this whenever it needs to access the `document` object.
5565
+ * For example to create the renderer or to do sanitization.
5566
+ */
5567
+ function getDocument() {
5568
+ if (DOCUMENT !== undefined) {
5569
+ return DOCUMENT;
5570
+ }
5571
+ else if (typeof document !== 'undefined') {
5572
+ return document;
5573
+ }
5574
+ // No "document" can be found. This should only happen if we are running ivy outside Angular and
5575
+ // the current platform is not a browser. Since this is not a supported scenario at the moment
5576
+ // this should not happen in Angular apps.
5577
+ // Once we support running ivy outside of Angular we will need to publish `setDocument()` as a
5578
+ // public API. Meanwhile we just return `undefined` and let the application fail.
5579
+ return undefined;
5580
+ }
5581
+
5615
5582
  /**
5616
5583
  * @license
5617
5584
  * Copyright Google LLC All Rights Reserved.
@@ -7287,6 +7254,17 @@ function ensureIcuContainerVisitorLoaded(loader) {
7287
7254
  }
7288
7255
  }
7289
7256
 
7257
+ /**
7258
+ * @license
7259
+ * Copyright Google LLC All Rights Reserved.
7260
+ *
7261
+ * Use of this source code is governed by an MIT-style license that can be
7262
+ * found in the LICENSE file at https://angular.io/license
7263
+ */
7264
+ // Note: This hack is necessary so we don't erroneously get a circular dependency
7265
+ // failure based on types.
7266
+ const unusedValueExportToPlacateAjd$4 = 1;
7267
+
7290
7268
  /**
7291
7269
  * @license
7292
7270
  * Copyright Google LLC All Rights Reserved.
@@ -7369,7 +7347,7 @@ function getNearestLContainer(viewOrContainer) {
7369
7347
  * Use of this source code is governed by an MIT-style license that can be
7370
7348
  * found in the LICENSE file at https://angular.io/license
7371
7349
  */
7372
- const unusedValueToPlacateAjd$2 = unusedValueExportToPlacateAjd$8 + unusedValueExportToPlacateAjd$4 + unusedValueExportToPlacateAjd$3 + unusedValueExportToPlacateAjd$6 + unusedValueExportToPlacateAjd$7;
7350
+ const unusedValueToPlacateAjd$2 = unusedValueExportToPlacateAjd$8 + unusedValueExportToPlacateAjd$5 + unusedValueExportToPlacateAjd$4 + unusedValueExportToPlacateAjd$3 + unusedValueExportToPlacateAjd$7;
7373
7351
  /**
7374
7352
  * NOTE: for performance reasons, the possible actions are inlined within the function instead of
7375
7353
  * being passed as an argument.
@@ -7394,7 +7372,6 @@ function applyToElementOrContainer(action, renderer, parent, lNodeToHandle, befo
7394
7372
  lNodeToHandle = lNodeToHandle[HOST];
7395
7373
  }
7396
7374
  const rNode = unwrapRNode(lNodeToHandle);
7397
- ngDevMode && !isProceduralRenderer(renderer) && assertDomNode(rNode);
7398
7375
  if (action === 0 /* WalkTNodeTreeAction.Create */ && parent !== null) {
7399
7376
  if (beforeNode == null) {
7400
7377
  nativeAppendChild(renderer, parent, rNode);
@@ -7421,17 +7398,14 @@ function applyToElementOrContainer(action, renderer, parent, lNodeToHandle, befo
7421
7398
  function createTextNode(renderer, value) {
7422
7399
  ngDevMode && ngDevMode.rendererCreateTextNode++;
7423
7400
  ngDevMode && ngDevMode.rendererSetText++;
7424
- return isProceduralRenderer(renderer) ? renderer.createText(value) :
7425
- renderer.createTextNode(value);
7401
+ return renderer.createText(value);
7426
7402
  }
7427
7403
  function updateTextNode(renderer, rNode, value) {
7428
7404
  ngDevMode && ngDevMode.rendererSetText++;
7429
- isProceduralRenderer(renderer) ? renderer.setValue(rNode, value) : rNode.textContent = value;
7405
+ renderer.setValue(rNode, value);
7430
7406
  }
7431
7407
  function createCommentNode(renderer, value) {
7432
7408
  ngDevMode && ngDevMode.rendererCreateComment++;
7433
- // isProceduralRenderer check is not needed because both `Renderer2` and `Renderer3` have the same
7434
- // method name.
7435
7409
  return renderer.createComment(escapeCommentText(value));
7436
7410
  }
7437
7411
  /**
@@ -7443,14 +7417,7 @@ function createCommentNode(renderer, value) {
7443
7417
  */
7444
7418
  function createElementNode(renderer, name, namespace) {
7445
7419
  ngDevMode && ngDevMode.rendererCreateElement++;
7446
- if (isProceduralRenderer(renderer)) {
7447
- return renderer.createElement(name, namespace);
7448
- }
7449
- else {
7450
- const namespaceUri = namespace !== null ? getNamespaceUri(namespace) : null;
7451
- return namespaceUri === null ? renderer.createElement(name) :
7452
- renderer.createElementNS(namespaceUri, name);
7453
- }
7420
+ return renderer.createElement(name, namespace);
7454
7421
  }
7455
7422
  /**
7456
7423
  * Removes all DOM elements associated with a view.
@@ -7682,7 +7649,7 @@ function detachView(lContainer, removeIndex) {
7682
7649
  function destroyLView(tView, lView) {
7683
7650
  if (!(lView[FLAGS] & 128 /* LViewFlags.Destroyed */)) {
7684
7651
  const renderer = lView[RENDERER];
7685
- if (isProceduralRenderer(renderer) && renderer.destroyNode) {
7652
+ if (renderer.destroyNode) {
7686
7653
  applyView(tView, lView, renderer, 3 /* WalkTNodeTreeAction.Destroy */, null, null);
7687
7654
  }
7688
7655
  destroyViewTree(lView);
@@ -7710,7 +7677,7 @@ function cleanUpView(tView, lView) {
7710
7677
  executeOnDestroys(tView, lView);
7711
7678
  processCleanups(tView, lView);
7712
7679
  // For component views only, the local renderer is destroyed at clean up time.
7713
- if (lView[TVIEW].type === 1 /* TViewType.Component */ && isProceduralRenderer(lView[RENDERER])) {
7680
+ if (lView[TVIEW].type === 1 /* TViewType.Component */) {
7714
7681
  ngDevMode && ngDevMode.rendererDestroy++;
7715
7682
  lView[RENDERER].destroy();
7716
7683
  }
@@ -7886,30 +7853,17 @@ function getClosestRElement(tView, tNode, lView) {
7886
7853
  }
7887
7854
  }
7888
7855
  /**
7889
- * Inserts a native node before another native node for a given parent using {@link Renderer3}.
7890
- * This is a utility function that can be used when native nodes were determined - it abstracts an
7891
- * actual renderer being used.
7856
+ * Inserts a native node before another native node for a given parent.
7857
+ * This is a utility function that can be used when native nodes were determined.
7892
7858
  */
7893
7859
  function nativeInsertBefore(renderer, parent, child, beforeNode, isMove) {
7894
7860
  ngDevMode && ngDevMode.rendererInsertBefore++;
7895
- if (isProceduralRenderer(renderer)) {
7896
- renderer.insertBefore(parent, child, beforeNode, isMove);
7897
- }
7898
- else {
7899
- const targetParent = isTemplateNode(parent) ? parent.content : parent;
7900
- targetParent.insertBefore(child, beforeNode, isMove);
7901
- }
7861
+ renderer.insertBefore(parent, child, beforeNode, isMove);
7902
7862
  }
7903
7863
  function nativeAppendChild(renderer, parent, child) {
7904
7864
  ngDevMode && ngDevMode.rendererAppendChild++;
7905
7865
  ngDevMode && assertDefined(parent, 'parent node must be defined');
7906
- if (isProceduralRenderer(renderer)) {
7907
- renderer.appendChild(parent, child);
7908
- }
7909
- else {
7910
- const targetParent = isTemplateNode(parent) ? parent.content : parent;
7911
- targetParent.appendChild(child);
7912
- }
7866
+ renderer.appendChild(parent, child);
7913
7867
  }
7914
7868
  function nativeAppendOrInsertBefore(renderer, parent, child, beforeNode, isMove) {
7915
7869
  if (beforeNode !== null) {
@@ -7921,12 +7875,7 @@ function nativeAppendOrInsertBefore(renderer, parent, child, beforeNode, isMove)
7921
7875
  }
7922
7876
  /** Removes a node from the DOM given its native parent. */
7923
7877
  function nativeRemoveChild(renderer, parent, child, isHostElement) {
7924
- if (isProceduralRenderer(renderer)) {
7925
- renderer.removeChild(parent, child, isHostElement);
7926
- }
7927
- else {
7928
- parent.removeChild(child);
7929
- }
7878
+ renderer.removeChild(parent, child, isHostElement);
7930
7879
  }
7931
7880
  /** Checks if an element is a `<template>` node. */
7932
7881
  function isTemplateNode(node) {
@@ -7936,13 +7885,13 @@ function isTemplateNode(node) {
7936
7885
  * Returns a native parent of a given native node.
7937
7886
  */
7938
7887
  function nativeParentNode(renderer, node) {
7939
- return (isProceduralRenderer(renderer) ? renderer.parentNode(node) : node.parentNode);
7888
+ return renderer.parentNode(node);
7940
7889
  }
7941
7890
  /**
7942
7891
  * Returns a native sibling of a given native node.
7943
7892
  */
7944
7893
  function nativeNextSibling(renderer, node) {
7945
- return isProceduralRenderer(renderer) ? renderer.nextSibling(node) : node.nextSibling;
7894
+ return renderer.nextSibling(node);
7946
7895
  }
7947
7896
  /**
7948
7897
  * Find a node in front of which `currentTNode` should be inserted.
@@ -8251,39 +8200,22 @@ function applyContainer(renderer, action, lContainer, parentRElement, beforeNode
8251
8200
  * otherwise).
8252
8201
  */
8253
8202
  function applyStyling(renderer, isClassBased, rNode, prop, value) {
8254
- const isProcedural = isProceduralRenderer(renderer);
8255
8203
  if (isClassBased) {
8256
8204
  // We actually want JS true/false here because any truthy value should add the class
8257
8205
  if (!value) {
8258
8206
  ngDevMode && ngDevMode.rendererRemoveClass++;
8259
- if (isProcedural) {
8260
- renderer.removeClass(rNode, prop);
8261
- }
8262
- else {
8263
- rNode.classList.remove(prop);
8264
- }
8207
+ renderer.removeClass(rNode, prop);
8265
8208
  }
8266
8209
  else {
8267
8210
  ngDevMode && ngDevMode.rendererAddClass++;
8268
- if (isProcedural) {
8269
- renderer.addClass(rNode, prop);
8270
- }
8271
- else {
8272
- ngDevMode && assertDefined(rNode.classList, 'HTMLElement expected');
8273
- rNode.classList.add(prop);
8274
- }
8211
+ renderer.addClass(rNode, prop);
8275
8212
  }
8276
8213
  }
8277
8214
  else {
8278
8215
  let flags = prop.indexOf('-') === -1 ? undefined : RendererStyleFlags2.DashCase;
8279
8216
  if (value == null /** || value === undefined */) {
8280
8217
  ngDevMode && ngDevMode.rendererRemoveStyle++;
8281
- if (isProcedural) {
8282
- renderer.removeStyle(rNode, prop, flags);
8283
- }
8284
- else {
8285
- rNode.style.removeProperty(prop);
8286
- }
8218
+ renderer.removeStyle(rNode, prop, flags);
8287
8219
  }
8288
8220
  else {
8289
8221
  // A value is important if it ends with `!important`. The style
@@ -8295,13 +8227,7 @@ function applyStyling(renderer, isClassBased, rNode, prop, value) {
8295
8227
  flags |= RendererStyleFlags2.Important;
8296
8228
  }
8297
8229
  ngDevMode && ngDevMode.rendererSetStyle++;
8298
- if (isProcedural) {
8299
- renderer.setStyle(rNode, prop, value, flags);
8300
- }
8301
- else {
8302
- ngDevMode && assertDefined(rNode.style, 'HTMLElement expected');
8303
- rNode.style.setProperty(prop, value, isImportant ? 'important' : '');
8304
- }
8230
+ renderer.setStyle(rNode, prop, value, flags);
8305
8231
  }
8306
8232
  }
8307
8233
  }
@@ -8317,12 +8243,7 @@ function applyStyling(renderer, isClassBased, rNode, prop, value) {
8317
8243
  */
8318
8244
  function writeDirectStyle(renderer, element, newValue) {
8319
8245
  ngDevMode && assertString(newValue, '\'newValue\' should be a string');
8320
- if (isProceduralRenderer(renderer)) {
8321
- renderer.setAttribute(element, 'style', newValue);
8322
- }
8323
- else {
8324
- element.style.cssText = newValue;
8325
- }
8246
+ renderer.setAttribute(element, 'style', newValue);
8326
8247
  ngDevMode && ngDevMode.rendererSetStyle++;
8327
8248
  }
8328
8249
  /**
@@ -8337,17 +8258,12 @@ function writeDirectStyle(renderer, element, newValue) {
8337
8258
  */
8338
8259
  function writeDirectClass(renderer, element, newValue) {
8339
8260
  ngDevMode && assertString(newValue, '\'newValue\' should be a string');
8340
- if (isProceduralRenderer(renderer)) {
8341
- if (newValue === '') {
8342
- // There are tests in `google3` which expect `element.getAttribute('class')` to be `null`.
8343
- renderer.removeAttribute(element, 'class');
8344
- }
8345
- else {
8346
- renderer.setAttribute(element, 'class', newValue);
8347
- }
8261
+ if (newValue === '') {
8262
+ // There are tests in `google3` which expect `element.getAttribute('class')` to be `null`.
8263
+ renderer.removeAttribute(element, 'class');
8348
8264
  }
8349
8265
  else {
8350
- element.className = newValue;
8266
+ renderer.setAttribute(element, 'class', newValue);
8351
8267
  }
8352
8268
  ngDevMode && ngDevMode.rendererSetClassName++;
8353
8269
  }
@@ -8397,7 +8313,7 @@ function classIndexOf(className, classToSearch, startingIndex) {
8397
8313
  * Use of this source code is governed by an MIT-style license that can be
8398
8314
  * found in the LICENSE file at https://angular.io/license
8399
8315
  */
8400
- const unusedValueToPlacateAjd$1 = unusedValueExportToPlacateAjd$4 + unusedValueExportToPlacateAjd$3;
8316
+ const unusedValueToPlacateAjd$1 = unusedValueExportToPlacateAjd$5 + unusedValueExportToPlacateAjd$4;
8401
8317
  const NG_TEMPLATE_SELECTOR = 'ng-template';
8402
8318
  /**
8403
8319
  * Search the `TAttributes` to see if it contains `cssClassToMatch` (case insensitive)
@@ -9512,6 +9428,18 @@ class R3Injector extends EnvironmentInjector {
9512
9428
  onDestroy(callback) {
9513
9429
  this._onDestroyHooks.push(callback);
9514
9430
  }
9431
+ runInContext(fn) {
9432
+ this.assertNotDestroyed();
9433
+ const previousInjector = setCurrentInjector(this);
9434
+ const previousInjectImplementation = setInjectImplementation(undefined);
9435
+ try {
9436
+ return fn();
9437
+ }
9438
+ finally {
9439
+ setCurrentInjector(previousInjector);
9440
+ setInjectImplementation(previousInjectImplementation);
9441
+ }
9442
+ }
9515
9443
  get(token, notFoundValue = THROW_IF_NOT_FOUND, flags = InjectFlags.Default) {
9516
9444
  this.assertNotDestroyed();
9517
9445
  // Set the injection context.
@@ -10927,6 +10855,9 @@ function handleUnknownPropertyError(propName, tagName, nodeType, lView) {
10927
10855
  `the ${schemas} of this component.`;
10928
10856
  }
10929
10857
  }
10858
+ reportUnknownPropertyError(message);
10859
+ }
10860
+ function reportUnknownPropertyError(message) {
10930
10861
  if (shouldThrowErrorOnUnknownProperty) {
10931
10862
  throw new RuntimeError(303 /* RuntimeErrorCode.UNKNOWN_BINDING */, message);
10932
10863
  }
@@ -11814,6 +11745,13 @@ class LContainerDebug {
11814
11745
  }
11815
11746
  }
11816
11747
 
11748
+ /**
11749
+ * @license
11750
+ * Copyright Google LLC All Rights Reserved.
11751
+ *
11752
+ * Use of this source code is governed by an MIT-style license that can be
11753
+ * found in the LICENSE file at https://angular.io/license
11754
+ */
11817
11755
  /**
11818
11756
  * A permanent marker promise which signifies that the current CD tree is
11819
11757
  * clean.
@@ -11881,7 +11819,7 @@ function refreshChildComponents(hostLView, components) {
11881
11819
  /** Renders child components in the current view (creation mode). */
11882
11820
  function renderChildComponents(hostLView, components) {
11883
11821
  for (let i = 0; i < components.length; i++) {
11884
- renderComponent$1(hostLView, components[i]);
11822
+ renderComponent(hostLView, components[i]);
11885
11823
  }
11886
11824
  }
11887
11825
  function createLView(parentLView, tView, context, flags, host, tHostNode, rendererFactory, renderer, sanitizer, injector, embeddedViewInjector) {
@@ -12399,16 +12337,6 @@ function createViewBlueprint(bindingStartIndex, initialViewLength) {
12399
12337
  function createError(text, token) {
12400
12338
  return new Error(`Renderer: ${text} [${stringifyForError(token)}]`);
12401
12339
  }
12402
- function assertHostNodeExists(rElement, elementOrSelector) {
12403
- if (!rElement) {
12404
- if (typeof elementOrSelector === 'string') {
12405
- throw createError('Host node with selector not found:', elementOrSelector);
12406
- }
12407
- else {
12408
- throw createError('Host node is required:', elementOrSelector);
12409
- }
12410
- }
12411
- }
12412
12340
  /**
12413
12341
  * Locates the host native element, used for bootstrapping existing nodes into rendering pipeline.
12414
12342
  *
@@ -12417,21 +12345,9 @@ function assertHostNodeExists(rElement, elementOrSelector) {
12417
12345
  * @param encapsulation View Encapsulation defined for component that requests host element.
12418
12346
  */
12419
12347
  function locateHostElement(renderer, elementOrSelector, encapsulation) {
12420
- if (isProceduralRenderer(renderer)) {
12421
- // When using native Shadow DOM, do not clear host element to allow native slot projection
12422
- const preserveContent = encapsulation === ViewEncapsulation.ShadowDom;
12423
- return renderer.selectRootElement(elementOrSelector, preserveContent);
12424
- }
12425
- let rElement = typeof elementOrSelector === 'string' ?
12426
- renderer.querySelector(elementOrSelector) :
12427
- elementOrSelector;
12428
- ngDevMode && assertHostNodeExists(rElement, elementOrSelector);
12429
- // Always clear host element's content when Renderer3 is in use. For procedural renderer case we
12430
- // make it depend on whether ShadowDom encapsulation is used (in which case the content should be
12431
- // preserved to allow native slot projection). ShadowDom encapsulation requires procedural
12432
- // renderer, and procedural renderer case is handled above.
12433
- rElement.textContent = '';
12434
- return rElement;
12348
+ // When using native Shadow DOM, do not clear host element to allow native slot projection
12349
+ const preserveContent = encapsulation === ViewEncapsulation.ShadowDom;
12350
+ return renderer.selectRootElement(elementOrSelector, preserveContent);
12435
12351
  }
12436
12352
  /**
12437
12353
  * Saves context for this cleanup function in LView.cleanupInstances.
@@ -12646,13 +12562,7 @@ function elementPropertyInternal(tView, tNode, lView, propName, value, renderer,
12646
12562
  // It is assumed that the sanitizer is only added when the compiler determines that the
12647
12563
  // property is risky, so sanitization can be done without further checks.
12648
12564
  value = sanitizer != null ? sanitizer(value, tNode.value || '', propName) : value;
12649
- if (isProceduralRenderer(renderer)) {
12650
- renderer.setProperty(element, propName, value);
12651
- }
12652
- else if (!isAnimationProp(propName)) {
12653
- element.setProperty ? element.setProperty(propName, value) :
12654
- element[propName] = value;
12655
- }
12565
+ renderer.setProperty(element, propName, value);
12656
12566
  }
12657
12567
  else if (tNode.type & 12 /* TNodeType.AnyContainer */) {
12658
12568
  // If the node is a container and the property didn't
@@ -12676,23 +12586,15 @@ function setNgReflectProperty(lView, element, type, attrName, value) {
12676
12586
  const debugValue = normalizeDebugBindingValue(value);
12677
12587
  if (type & 3 /* TNodeType.AnyRNode */) {
12678
12588
  if (value == null) {
12679
- isProceduralRenderer(renderer) ? renderer.removeAttribute(element, attrName) :
12680
- element.removeAttribute(attrName);
12589
+ renderer.removeAttribute(element, attrName);
12681
12590
  }
12682
12591
  else {
12683
- isProceduralRenderer(renderer) ?
12684
- renderer.setAttribute(element, attrName, debugValue) :
12685
- element.setAttribute(attrName, debugValue);
12592
+ renderer.setAttribute(element, attrName, debugValue);
12686
12593
  }
12687
12594
  }
12688
12595
  else {
12689
12596
  const textContent = escapeCommentText(`bindings=${JSON.stringify({ [attrName]: debugValue }, null, 2)}`);
12690
- if (isProceduralRenderer(renderer)) {
12691
- renderer.setValue(element, textContent);
12692
- }
12693
- else {
12694
- element.textContent = textContent;
12695
- }
12597
+ renderer.setValue(element, textContent);
12696
12598
  }
12697
12599
  }
12698
12600
  function setNgReflectProperties(lView, element, type, dataValue, value) {
@@ -12722,6 +12624,7 @@ function instantiateRootComponent(tView, lView, def) {
12722
12624
  ngDevMode &&
12723
12625
  assertEqual(directiveIndex, rootTNode.directiveStart, 'Because this is a root component the allocated expando should match the TNode component.');
12724
12626
  configureViewWithDirective(tView, rootTNode, lView, directiveIndex, def);
12627
+ initializeInputAndOutputAliases(tView, rootTNode);
12725
12628
  }
12726
12629
  const directive = getNodeInjectable(lView, tView, rootTNode.directiveStart, rootTNode);
12727
12630
  attachPatchData(directive, lView);
@@ -13046,19 +12949,12 @@ function elementAttributeInternal(tNode, lView, name, value, sanitizer, namespac
13046
12949
  function setElementAttribute(renderer, element, namespace, tagName, name, value, sanitizer) {
13047
12950
  if (value == null) {
13048
12951
  ngDevMode && ngDevMode.rendererRemoveAttribute++;
13049
- isProceduralRenderer(renderer) ? renderer.removeAttribute(element, name, namespace) :
13050
- element.removeAttribute(name);
12952
+ renderer.removeAttribute(element, name, namespace);
13051
12953
  }
13052
12954
  else {
13053
12955
  ngDevMode && ngDevMode.rendererSetAttribute++;
13054
12956
  const strValue = sanitizer == null ? renderStringify(value) : sanitizer(value, tagName || '', name);
13055
- if (isProceduralRenderer(renderer)) {
13056
- renderer.setAttribute(element, name, strValue, namespace);
13057
- }
13058
- else {
13059
- namespace ? element.setAttributeNS(namespace, name, strValue) :
13060
- element.setAttribute(name, strValue);
13061
- }
12957
+ renderer.setAttribute(element, name, strValue, namespace);
13062
12958
  }
13063
12959
  }
13064
12960
  /**
@@ -13150,7 +13046,6 @@ const LContainerArray = class LContainer extends Array {
13150
13046
  */
13151
13047
  function createLContainer(hostNative, currentView, native, tNode) {
13152
13048
  ngDevMode && assertLView(currentView);
13153
- ngDevMode && !isProceduralRenderer(currentView[RENDERER]) && assertDomNode(native);
13154
13049
  // https://jsperf.com/array-literal-vs-new-array-really
13155
13050
  const lContainer = new (ngDevMode ? LContainerArray : Array)(hostNative, // host native
13156
13051
  true, // Boolean `true` in this position signifies that this is an `LContainer`
@@ -13266,7 +13161,7 @@ function refreshContainsDirtyView(lView) {
13266
13161
  }
13267
13162
  }
13268
13163
  }
13269
- function renderComponent$1(hostLView, componentHostIdx) {
13164
+ function renderComponent(hostLView, componentHostIdx) {
13270
13165
  ngDevMode && assertEqual(isCreationMode(hostLView), true, 'Should be run in creation mode');
13271
13166
  const componentView = getComponentLViewByIndex(componentHostIdx, hostLView);
13272
13167
  const componentTView = componentView[TVIEW];
@@ -13618,48 +13513,135 @@ function computeStaticStyling(tNode, attrs, writeToHost) {
13618
13513
  * Use of this source code is governed by an MIT-style license that can be
13619
13514
  * found in the LICENSE file at https://angular.io/license
13620
13515
  */
13516
+ // TODO: A hack to not pull in the NullInjector from @angular/core.
13517
+ const NULL_INJECTOR = {
13518
+ get: (token, notFoundValue) => {
13519
+ throwProviderNotFoundError(token, 'NullInjector');
13520
+ }
13521
+ };
13621
13522
  /**
13622
- * Synchronously perform change detection on a component (and possibly its sub-components).
13523
+ * Creates the root component view and the root component node.
13623
13524
  *
13624
- * This function triggers change detection in a synchronous way on a component.
13525
+ * @param rNode Render host element.
13526
+ * @param def ComponentDef
13527
+ * @param rootView The parent view where the host node is stored
13528
+ * @param rendererFactory Factory to be used for creating child renderers.
13529
+ * @param hostRenderer The current renderer
13530
+ * @param sanitizer The sanitizer, if provided
13625
13531
  *
13626
- * @param component The component which the change detection should be performed on.
13532
+ * @returns Component view created
13627
13533
  */
13628
- function detectChanges(component) {
13629
- const view = getComponentViewByInstance(component);
13630
- detectChangesInternal(view[TVIEW], view, component);
13534
+ function createRootComponentView(rNode, def, rootView, rendererFactory, hostRenderer, sanitizer) {
13535
+ const tView = rootView[TVIEW];
13536
+ const index = HEADER_OFFSET;
13537
+ ngDevMode && assertIndexInRange(rootView, index);
13538
+ rootView[index] = rNode;
13539
+ // '#host' is added here as we don't know the real host DOM name (we don't want to read it) and at
13540
+ // the same time we want to communicate the debug `TNode` that this is a special `TNode`
13541
+ // representing a host element.
13542
+ const tNode = getOrCreateTNode(tView, index, 2 /* TNodeType.Element */, '#host', null);
13543
+ const mergedAttrs = tNode.mergedAttrs = def.hostAttrs;
13544
+ if (mergedAttrs !== null) {
13545
+ computeStaticStyling(tNode, mergedAttrs, true);
13546
+ if (rNode !== null) {
13547
+ setUpAttributes(hostRenderer, rNode, mergedAttrs);
13548
+ if (tNode.classes !== null) {
13549
+ writeDirectClass(hostRenderer, rNode, tNode.classes);
13550
+ }
13551
+ if (tNode.styles !== null) {
13552
+ writeDirectStyle(hostRenderer, rNode, tNode.styles);
13553
+ }
13554
+ }
13555
+ }
13556
+ const viewRenderer = rendererFactory.createRenderer(rNode, def);
13557
+ const componentView = createLView(rootView, getOrCreateTComponentView(def), null, def.onPush ? 32 /* LViewFlags.Dirty */ : 16 /* LViewFlags.CheckAlways */, rootView[index], tNode, rendererFactory, viewRenderer, sanitizer || null, null, null);
13558
+ if (tView.firstCreatePass) {
13559
+ diPublicInInjector(getOrCreateNodeInjectorForNode(tNode, rootView), tView, def.type);
13560
+ markAsComponentHost(tView, tNode);
13561
+ initTNodeFlags(tNode, rootView.length, 1);
13562
+ }
13563
+ addToViewTree(rootView, componentView);
13564
+ // Store component view at node index, with node as the HOST
13565
+ return rootView[index] = componentView;
13631
13566
  }
13632
13567
  /**
13633
- * Marks the component as dirty (needing change detection). Marking a component dirty will
13634
- * schedule a change detection on it at some point in the future.
13635
- *
13636
- * Marking an already dirty component as dirty won't do anything. Only one outstanding change
13637
- * detection can be scheduled per component tree.
13568
+ * Creates a root component and sets it up with features and host bindings. Shared by
13569
+ * renderComponent() and ViewContainerRef.createComponent().
13570
+ */
13571
+ function createRootComponent(componentView, componentDef, rootLView, rootContext, hostFeatures) {
13572
+ const tView = rootLView[TVIEW];
13573
+ // Create directive instance with factory() and store at next index in viewData
13574
+ const component = instantiateRootComponent(tView, rootLView, componentDef);
13575
+ rootContext.components.push(component);
13576
+ componentView[CONTEXT] = component;
13577
+ if (hostFeatures !== null) {
13578
+ for (const feature of hostFeatures) {
13579
+ feature(component, componentDef);
13580
+ }
13581
+ }
13582
+ // We want to generate an empty QueryList for root content queries for backwards
13583
+ // compatibility with ViewEngine.
13584
+ if (componentDef.contentQueries) {
13585
+ const tNode = getCurrentTNode();
13586
+ ngDevMode && assertDefined(tNode, 'TNode expected');
13587
+ componentDef.contentQueries(1 /* RenderFlags.Create */, component, tNode.directiveStart);
13588
+ }
13589
+ const rootTNode = getCurrentTNode();
13590
+ ngDevMode && assertDefined(rootTNode, 'tNode should have been already created');
13591
+ if (tView.firstCreatePass &&
13592
+ (componentDef.hostBindings !== null || componentDef.hostAttrs !== null)) {
13593
+ setSelectedIndex(rootTNode.index);
13594
+ const rootTView = rootLView[TVIEW];
13595
+ registerHostBindingOpCodes(rootTView, rootTNode, rootLView, rootTNode.directiveStart, rootTNode.directiveEnd, componentDef);
13596
+ invokeHostBindingsInCreationMode(componentDef, component);
13597
+ }
13598
+ return component;
13599
+ }
13600
+ function createRootContext(scheduler, playerHandler) {
13601
+ return {
13602
+ components: [],
13603
+ scheduler: scheduler || defaultScheduler,
13604
+ clean: CLEAN_PROMISE,
13605
+ playerHandler: playerHandler || null,
13606
+ flags: 0 /* RootContextFlags.Empty */
13607
+ };
13608
+ }
13609
+ /**
13610
+ * Used to enable lifecycle hooks on the root component.
13638
13611
  *
13639
- * @param component Component to mark as dirty.
13612
+ * Include this feature when calling `renderComponent` if the root component
13613
+ * you are rendering has lifecycle hooks defined. Otherwise, the hooks won't
13614
+ * be called properly.
13615
+ *
13616
+ * Example:
13617
+ *
13618
+ * ```
13619
+ * renderComponent(AppComponent, {hostFeatures: [LifecycleHooksFeature]});
13620
+ * ```
13640
13621
  */
13641
- function markDirty(component) {
13642
- ngDevMode && assertDefined(component, 'component');
13643
- const rootView = markViewDirty(getComponentViewByInstance(component));
13644
- ngDevMode && assertDefined(rootView[CONTEXT], 'rootContext should be defined');
13645
- scheduleTick(rootView[CONTEXT], 1 /* RootContextFlags.DetectChanges */);
13622
+ function LifecycleHooksFeature() {
13623
+ const tNode = getCurrentTNode();
13624
+ ngDevMode && assertDefined(tNode, 'TNode is required');
13625
+ registerPostOrderHooks(getLView()[TVIEW], tNode);
13646
13626
  }
13647
13627
  /**
13648
- * Used to perform change detection on the whole application.
13628
+ * Wait on component until it is rendered.
13649
13629
  *
13650
- * This is equivalent to `detectChanges`, but invoked on root component. Additionally, `tick`
13651
- * executes lifecycle hooks and conditionally checks components based on their
13652
- * `ChangeDetectionStrategy` and dirtiness.
13630
+ * This function returns a `Promise` which is resolved when the component's
13631
+ * change detection is executed. This is determined by finding the scheduler
13632
+ * associated with the `component`'s render tree and waiting until the scheduler
13633
+ * flushes. If nothing is scheduled, the function returns a resolved promise.
13653
13634
  *
13654
- * The preferred way to trigger change detection is to call `markDirty`. `markDirty` internally
13655
- * schedules `tick` using a scheduler in order to coalesce multiple `markDirty` calls into a
13656
- * single change detection run. By default, the scheduler is `requestAnimationFrame`, but can
13657
- * be changed when calling `renderComponent` and providing the `scheduler` option.
13635
+ * Example:
13636
+ * ```
13637
+ * await whenRendered(myComponent);
13638
+ * ```
13639
+ *
13640
+ * @param component Component to wait upon
13641
+ * @returns Promise which resolves when the component is rendered.
13658
13642
  */
13659
- function tick(component) {
13660
- const rootView = getRootView(component);
13661
- const rootContext = rootView[CONTEXT];
13662
- tickRootContext(rootContext);
13643
+ function whenRendered(component) {
13644
+ return getRootContext(component).clean;
13663
13645
  }
13664
13646
 
13665
13647
  /**
@@ -13669,407 +13651,263 @@ function tick(component) {
13669
13651
  * Use of this source code is governed by an MIT-style license that can be
13670
13652
  * found in the LICENSE file at https://angular.io/license
13671
13653
  */
13654
+ function getSuperType(type) {
13655
+ return Object.getPrototypeOf(type.prototype).constructor;
13656
+ }
13672
13657
  /**
13673
- * Retrieves the component instance associated with a given DOM element.
13674
- *
13675
- * @usageNotes
13676
- * Given the following DOM structure:
13677
- *
13678
- * ```html
13679
- * <app-root>
13680
- * <div>
13681
- * <child-comp></child-comp>
13682
- * </div>
13683
- * </app-root>
13684
- * ```
13685
- *
13686
- * Calling `getComponent` on `<child-comp>` will return the instance of `ChildComponent`
13687
- * associated with this DOM element.
13688
- *
13689
- * Calling the function on `<app-root>` will return the `MyApp` instance.
13690
- *
13691
- *
13692
- * @param element DOM element from which the component should be retrieved.
13693
- * @returns Component instance associated with the element or `null` if there
13694
- * is no component associated with it.
13658
+ * Merges the definition from a super class to a sub class.
13659
+ * @param definition The definition that is a SubClass of another directive of component
13695
13660
  *
13696
- * @publicApi
13697
- * @globalApi ng
13661
+ * @codeGenApi
13698
13662
  */
13699
- function getComponent$1(element) {
13700
- ngDevMode && assertDomElement(element);
13701
- const context = getLContext(element);
13702
- if (context === null)
13703
- return null;
13704
- if (context.component === undefined) {
13705
- const lView = context.lView;
13706
- if (lView === null) {
13707
- return null;
13663
+ function ɵɵInheritDefinitionFeature(definition) {
13664
+ let superType = getSuperType(definition.type);
13665
+ let shouldInheritFields = true;
13666
+ const inheritanceChain = [definition];
13667
+ while (superType) {
13668
+ let superDef = undefined;
13669
+ if (isComponentDef(definition)) {
13670
+ // Don't use getComponentDef/getDirectiveDef. This logic relies on inheritance.
13671
+ superDef = superType.ɵcmp || superType.ɵdir;
13708
13672
  }
13709
- context.component = getComponentAtNodeIndex(context.nodeIndex, lView);
13673
+ else {
13674
+ if (superType.ɵcmp) {
13675
+ throw new RuntimeError(903 /* RuntimeErrorCode.INVALID_INHERITANCE */, ngDevMode &&
13676
+ `Directives cannot inherit Components. Directive ${stringifyForError(definition.type)} is attempting to extend component ${stringifyForError(superType)}`);
13677
+ }
13678
+ // Don't use getComponentDef/getDirectiveDef. This logic relies on inheritance.
13679
+ superDef = superType.ɵdir;
13680
+ }
13681
+ if (superDef) {
13682
+ if (shouldInheritFields) {
13683
+ inheritanceChain.push(superDef);
13684
+ // Some fields in the definition may be empty, if there were no values to put in them that
13685
+ // would've justified object creation. Unwrap them if necessary.
13686
+ const writeableDef = definition;
13687
+ writeableDef.inputs = maybeUnwrapEmpty(definition.inputs);
13688
+ writeableDef.declaredInputs = maybeUnwrapEmpty(definition.declaredInputs);
13689
+ writeableDef.outputs = maybeUnwrapEmpty(definition.outputs);
13690
+ // Merge hostBindings
13691
+ const superHostBindings = superDef.hostBindings;
13692
+ superHostBindings && inheritHostBindings(definition, superHostBindings);
13693
+ // Merge queries
13694
+ const superViewQuery = superDef.viewQuery;
13695
+ const superContentQueries = superDef.contentQueries;
13696
+ superViewQuery && inheritViewQuery(definition, superViewQuery);
13697
+ superContentQueries && inheritContentQueries(definition, superContentQueries);
13698
+ // Merge inputs and outputs
13699
+ fillProperties(definition.inputs, superDef.inputs);
13700
+ fillProperties(definition.declaredInputs, superDef.declaredInputs);
13701
+ fillProperties(definition.outputs, superDef.outputs);
13702
+ // Merge animations metadata.
13703
+ // If `superDef` is a Component, the `data` field is present (defaults to an empty object).
13704
+ if (isComponentDef(superDef) && superDef.data.animation) {
13705
+ // If super def is a Component, the `definition` is also a Component, since Directives can
13706
+ // not inherit Components (we throw an error above and cannot reach this code).
13707
+ const defData = definition.data;
13708
+ defData.animation = (defData.animation || []).concat(superDef.data.animation);
13709
+ }
13710
+ }
13711
+ // Run parent features
13712
+ const features = superDef.features;
13713
+ if (features) {
13714
+ for (let i = 0; i < features.length; i++) {
13715
+ const feature = features[i];
13716
+ if (feature && feature.ngInherit) {
13717
+ feature(definition);
13718
+ }
13719
+ // If `InheritDefinitionFeature` is a part of the current `superDef`, it means that this
13720
+ // def already has all the necessary information inherited from its super class(es), so we
13721
+ // can stop merging fields from super classes. However we need to iterate through the
13722
+ // prototype chain to look for classes that might contain other "features" (like
13723
+ // NgOnChanges), which we should invoke for the original `definition`. We set the
13724
+ // `shouldInheritFields` flag to indicate that, essentially skipping fields inheritance
13725
+ // logic and only invoking functions from the "features" list.
13726
+ if (feature === ɵɵInheritDefinitionFeature) {
13727
+ shouldInheritFields = false;
13728
+ }
13729
+ }
13730
+ }
13731
+ }
13732
+ superType = Object.getPrototypeOf(superType);
13710
13733
  }
13711
- return context.component;
13712
- }
13713
- /**
13714
- * If inside an embedded view (e.g. `*ngIf` or `*ngFor`), retrieves the context of the embedded
13715
- * view that the element is part of. Otherwise retrieves the instance of the component whose view
13716
- * owns the element (in this case, the result is the same as calling `getOwningComponent`).
13717
- *
13718
- * @param element Element for which to get the surrounding component instance.
13719
- * @returns Instance of the component that is around the element or null if the element isn't
13720
- * inside any component.
13721
- *
13722
- * @publicApi
13723
- * @globalApi ng
13724
- */
13725
- function getContext(element) {
13726
- assertDomElement(element);
13727
- const context = getLContext(element);
13728
- const lView = context ? context.lView : null;
13729
- return lView === null ? null : lView[CONTEXT];
13734
+ mergeHostAttrsAcrossInheritance(inheritanceChain);
13730
13735
  }
13731
13736
  /**
13732
- * Retrieves the component instance whose view contains the DOM element.
13733
- *
13734
- * For example, if `<child-comp>` is used in the template of `<app-comp>`
13735
- * (i.e. a `ViewChild` of `<app-comp>`), calling `getOwningComponent` on `<child-comp>`
13736
- * would return `<app-comp>`.
13737
- *
13738
- * @param elementOrDir DOM element, component or directive instance
13739
- * for which to retrieve the root components.
13740
- * @returns Component instance whose view owns the DOM element or null if the element is not
13741
- * part of a component view.
13737
+ * Merge the `hostAttrs` and `hostVars` from the inherited parent to the base class.
13742
13738
  *
13743
- * @publicApi
13744
- * @globalApi ng
13739
+ * @param inheritanceChain A list of `WritableDefs` starting at the top most type and listing
13740
+ * sub-types in order. For each type take the `hostAttrs` and `hostVars` and merge it with the child
13741
+ * type.
13745
13742
  */
13746
- function getOwningComponent(elementOrDir) {
13747
- const context = getLContext(elementOrDir);
13748
- let lView = context ? context.lView : null;
13749
- if (lView === null)
13750
- return null;
13751
- let parent;
13752
- while (lView[TVIEW].type === 2 /* TViewType.Embedded */ && (parent = getLViewParent(lView))) {
13753
- lView = parent;
13743
+ function mergeHostAttrsAcrossInheritance(inheritanceChain) {
13744
+ let hostVars = 0;
13745
+ let hostAttrs = null;
13746
+ // We process the inheritance order from the base to the leaves here.
13747
+ for (let i = inheritanceChain.length - 1; i >= 0; i--) {
13748
+ const def = inheritanceChain[i];
13749
+ // For each `hostVars`, we need to add the superclass amount.
13750
+ def.hostVars = (hostVars += def.hostVars);
13751
+ // for each `hostAttrs` we need to merge it with superclass.
13752
+ def.hostAttrs =
13753
+ mergeHostAttrs(def.hostAttrs, hostAttrs = mergeHostAttrs(hostAttrs, def.hostAttrs));
13754
13754
  }
13755
- return lView[FLAGS] & 256 /* LViewFlags.IsRoot */ ? null : lView[CONTEXT];
13756
13755
  }
13757
- /**
13758
- * Retrieves all root components associated with a DOM element, directive or component instance.
13759
- * Root components are those which have been bootstrapped by Angular.
13760
- *
13761
- * @param elementOrDir DOM element, component or directive instance
13762
- * for which to retrieve the root components.
13763
- * @returns Root components associated with the target object.
13764
- *
13765
- * @publicApi
13766
- * @globalApi ng
13767
- */
13768
- function getRootComponents(elementOrDir) {
13769
- const lView = readPatchedLView(elementOrDir);
13770
- return lView !== null ? [...getRootContext(lView).components] : [];
13771
- }
13772
- /**
13773
- * Retrieves an `Injector` associated with an element, component or directive instance.
13774
- *
13775
- * @param elementOrDir DOM element, component or directive instance for which to
13776
- * retrieve the injector.
13777
- * @returns Injector associated with the element, component or directive instance.
13778
- *
13779
- * @publicApi
13780
- * @globalApi ng
13781
- */
13782
- function getInjector(elementOrDir) {
13783
- const context = getLContext(elementOrDir);
13784
- const lView = context ? context.lView : null;
13785
- if (lView === null)
13786
- return Injector.NULL;
13787
- const tNode = lView[TVIEW].data[context.nodeIndex];
13788
- return new NodeInjector(tNode, lView);
13789
- }
13790
- /**
13791
- * Retrieve a set of injection tokens at a given DOM node.
13792
- *
13793
- * @param element Element for which the injection tokens should be retrieved.
13794
- */
13795
- function getInjectionTokens(element) {
13796
- const context = getLContext(element);
13797
- const lView = context ? context.lView : null;
13798
- if (lView === null)
13799
- return [];
13800
- const tView = lView[TVIEW];
13801
- const tNode = tView.data[context.nodeIndex];
13802
- const providerTokens = [];
13803
- const startIndex = tNode.providerIndexes & 1048575 /* TNodeProviderIndexes.ProvidersStartIndexMask */;
13804
- const endIndex = tNode.directiveEnd;
13805
- for (let i = startIndex; i < endIndex; i++) {
13806
- let value = tView.data[i];
13807
- if (isDirectiveDefHack(value)) {
13808
- // The fact that we sometimes store Type and sometimes DirectiveDef in this location is a
13809
- // design flaw. We should always store same type so that we can be monomorphic. The issue
13810
- // is that for Components/Directives we store the def instead the type. The correct behavior
13811
- // is that we should always be storing injectable type in this location.
13812
- value = value.type;
13813
- }
13814
- providerTokens.push(value);
13756
+ function maybeUnwrapEmpty(value) {
13757
+ if (value === EMPTY_OBJ) {
13758
+ return {};
13815
13759
  }
13816
- return providerTokens;
13817
- }
13818
- /**
13819
- * Retrieves directive instances associated with a given DOM node. Does not include
13820
- * component instances.
13821
- *
13822
- * @usageNotes
13823
- * Given the following DOM structure:
13824
- *
13825
- * ```html
13826
- * <app-root>
13827
- * <button my-button></button>
13828
- * <my-comp></my-comp>
13829
- * </app-root>
13830
- * ```
13831
- *
13832
- * Calling `getDirectives` on `<button>` will return an array with an instance of the `MyButton`
13833
- * directive that is associated with the DOM node.
13834
- *
13835
- * Calling `getDirectives` on `<my-comp>` will return an empty array.
13836
- *
13837
- * @param node DOM node for which to get the directives.
13838
- * @returns Array of directives associated with the node.
13839
- *
13840
- * @publicApi
13841
- * @globalApi ng
13842
- */
13843
- function getDirectives(node) {
13844
- // Skip text nodes because we can't have directives associated with them.
13845
- if (node instanceof Text) {
13760
+ else if (value === EMPTY_ARRAY) {
13846
13761
  return [];
13847
13762
  }
13848
- const context = getLContext(node);
13849
- const lView = context ? context.lView : null;
13850
- if (lView === null) {
13851
- return [];
13763
+ else {
13764
+ return value;
13852
13765
  }
13853
- const tView = lView[TVIEW];
13854
- const nodeIndex = context.nodeIndex;
13855
- if (!(tView === null || tView === void 0 ? void 0 : tView.data[nodeIndex])) {
13856
- return [];
13766
+ }
13767
+ function inheritViewQuery(definition, superViewQuery) {
13768
+ const prevViewQuery = definition.viewQuery;
13769
+ if (prevViewQuery) {
13770
+ definition.viewQuery = (rf, ctx) => {
13771
+ superViewQuery(rf, ctx);
13772
+ prevViewQuery(rf, ctx);
13773
+ };
13857
13774
  }
13858
- if (context.directives === undefined) {
13859
- context.directives = getDirectivesAtNodeIndex(nodeIndex, lView, false);
13775
+ else {
13776
+ definition.viewQuery = superViewQuery;
13860
13777
  }
13861
- // The `directives` in this case are a named array called `LComponentView`. Clone the
13862
- // result so we don't expose an internal data structure in the user's console.
13863
- return context.directives === null ? [] : [...context.directives];
13864
13778
  }
13865
- /**
13866
- * Returns the debug (partial) metadata for a particular directive or component instance.
13867
- * The function accepts an instance of a directive or component and returns the corresponding
13868
- * metadata.
13869
- *
13870
- * @param directiveOrComponentInstance Instance of a directive or component
13871
- * @returns metadata of the passed directive or component
13872
- *
13873
- * @publicApi
13874
- * @globalApi ng
13875
- */
13876
- function getDirectiveMetadata(directiveOrComponentInstance) {
13877
- const { constructor } = directiveOrComponentInstance;
13878
- if (!constructor) {
13879
- throw new Error('Unable to find the instance constructor');
13779
+ function inheritContentQueries(definition, superContentQueries) {
13780
+ const prevContentQueries = definition.contentQueries;
13781
+ if (prevContentQueries) {
13782
+ definition.contentQueries = (rf, ctx, directiveIndex) => {
13783
+ superContentQueries(rf, ctx, directiveIndex);
13784
+ prevContentQueries(rf, ctx, directiveIndex);
13785
+ };
13880
13786
  }
13881
- // In case a component inherits from a directive, we may have component and directive metadata
13882
- // To ensure we don't get the metadata of the directive, we want to call `getComponentDef` first.
13883
- const componentDef = getComponentDef$1(constructor);
13884
- if (componentDef) {
13885
- return {
13886
- inputs: componentDef.inputs,
13887
- outputs: componentDef.outputs,
13888
- encapsulation: componentDef.encapsulation,
13889
- changeDetection: componentDef.onPush ? ChangeDetectionStrategy.OnPush :
13890
- ChangeDetectionStrategy.Default
13787
+ else {
13788
+ definition.contentQueries = superContentQueries;
13789
+ }
13790
+ }
13791
+ function inheritHostBindings(definition, superHostBindings) {
13792
+ const prevHostBindings = definition.hostBindings;
13793
+ if (prevHostBindings) {
13794
+ definition.hostBindings = (rf, ctx) => {
13795
+ superHostBindings(rf, ctx);
13796
+ prevHostBindings(rf, ctx);
13891
13797
  };
13892
13798
  }
13893
- const directiveDef = getDirectiveDef(constructor);
13894
- if (directiveDef) {
13895
- return { inputs: directiveDef.inputs, outputs: directiveDef.outputs };
13799
+ else {
13800
+ definition.hostBindings = superHostBindings;
13896
13801
  }
13897
- return null;
13898
13802
  }
13803
+
13899
13804
  /**
13900
- * Retrieve map of local references.
13901
- *
13902
- * The references are retrieved as a map of local reference name to element or directive instance.
13805
+ * @license
13806
+ * Copyright Google LLC All Rights Reserved.
13903
13807
  *
13904
- * @param target DOM element, component or directive instance for which to retrieve
13905
- * the local references.
13808
+ * Use of this source code is governed by an MIT-style license that can be
13809
+ * found in the LICENSE file at https://angular.io/license
13906
13810
  */
13907
- function getLocalRefs(target) {
13908
- const context = getLContext(target);
13909
- if (context === null)
13910
- return {};
13911
- if (context.localRefs === undefined) {
13912
- const lView = context.lView;
13913
- if (lView === null) {
13914
- return {};
13915
- }
13916
- context.localRefs = discoverLocalRefs(lView, context.nodeIndex);
13917
- }
13918
- return context.localRefs || {};
13919
- }
13920
13811
  /**
13921
- * Retrieves the host element of a component or directive instance.
13922
- * The host element is the DOM element that matched the selector of the directive.
13923
- *
13924
- * @param componentOrDirective Component or directive instance for which the host
13925
- * element should be retrieved.
13926
- * @returns Host element of the target.
13927
- *
13928
- * @publicApi
13929
- * @globalApi ng
13812
+ * Fields which exist on either directive or component definitions, and need to be copied from
13813
+ * parent to child classes by the `ɵɵCopyDefinitionFeature`.
13930
13814
  */
13931
- function getHostElement(componentOrDirective) {
13932
- return getLContext(componentOrDirective).native;
13933
- }
13815
+ const COPY_DIRECTIVE_FIELDS = [
13816
+ // The child class should use the providers of its parent.
13817
+ 'providersResolver',
13818
+ // Not listed here are any fields which are handled by the `ɵɵInheritDefinitionFeature`, such
13819
+ // as inputs, outputs, and host binding functions.
13820
+ ];
13934
13821
  /**
13935
- * Retrieves the rendered text for a given component.
13936
- *
13937
- * This function retrieves the host element of a component and
13938
- * and then returns the `textContent` for that element. This implies
13939
- * that the text returned will include re-projected content of
13940
- * the component as well.
13822
+ * Fields which exist only on component definitions, and need to be copied from parent to child
13823
+ * classes by the `ɵɵCopyDefinitionFeature`.
13941
13824
  *
13942
- * @param component The component to return the content text for.
13825
+ * The type here allows any field of `ComponentDef` which is not also a property of `DirectiveDef`,
13826
+ * since those should go in `COPY_DIRECTIVE_FIELDS` above.
13943
13827
  */
13944
- function getRenderedText(component) {
13945
- const hostElement = getHostElement(component);
13946
- return hostElement.textContent || '';
13947
- }
13828
+ const COPY_COMPONENT_FIELDS = [
13829
+ // The child class should use the template function of its parent, including all template
13830
+ // semantics.
13831
+ 'template',
13832
+ 'decls',
13833
+ 'consts',
13834
+ 'vars',
13835
+ 'onPush',
13836
+ 'ngContentSelectors',
13837
+ // The child class should use the CSS styles of its parent, including all styling semantics.
13838
+ 'styles',
13839
+ 'encapsulation',
13840
+ // The child class should be checked by the runtime in the same way as its parent.
13841
+ 'schemas',
13842
+ ];
13948
13843
  /**
13949
- * Retrieves a list of event listeners associated with a DOM element. The list does include host
13950
- * listeners, but it does not include event listeners defined outside of the Angular context
13951
- * (e.g. through `addEventListener`).
13844
+ * Copies the fields not handled by the `ɵɵInheritDefinitionFeature` from the supertype of a
13845
+ * definition.
13952
13846
  *
13953
- * @usageNotes
13954
- * Given the following DOM structure:
13847
+ * This exists primarily to support ngcc migration of an existing View Engine pattern, where an
13848
+ * entire decorator is inherited from a parent to a child class. When ngcc detects this case, it
13849
+ * generates a skeleton definition on the child class, and applies this feature.
13955
13850
  *
13956
- * ```html
13957
- * <app-root>
13958
- * <div (click)="doSomething()"></div>
13959
- * </app-root>
13960
- * ```
13851
+ * The `ɵɵCopyDefinitionFeature` then copies any needed fields from the parent class' definition,
13852
+ * including things like the component template function.
13961
13853
  *
13962
- * Calling `getListeners` on `<div>` will return an object that looks as follows:
13854
+ * @param definition The definition of a child class which inherits from a parent class with its
13855
+ * own definition.
13963
13856
  *
13964
- * ```ts
13965
- * {
13966
- * name: 'click',
13967
- * element: <div>,
13968
- * callback: () => doSomething(),
13969
- * useCapture: false
13970
- * }
13971
- * ```
13972
- *
13973
- * @param element Element for which the DOM listeners should be retrieved.
13974
- * @returns Array of event listeners on the DOM element.
13975
- *
13976
- * @publicApi
13977
- * @globalApi ng
13857
+ * @codeGenApi
13978
13858
  */
13979
- function getListeners(element) {
13980
- ngDevMode && assertDomElement(element);
13981
- const lContext = getLContext(element);
13982
- const lView = lContext === null ? null : lContext.lView;
13983
- if (lView === null)
13984
- return [];
13985
- const tView = lView[TVIEW];
13986
- const lCleanup = lView[CLEANUP];
13987
- const tCleanup = tView.cleanup;
13988
- const listeners = [];
13989
- if (tCleanup && lCleanup) {
13990
- for (let i = 0; i < tCleanup.length;) {
13991
- const firstParam = tCleanup[i++];
13992
- const secondParam = tCleanup[i++];
13993
- if (typeof firstParam === 'string') {
13994
- const name = firstParam;
13995
- const listenerElement = unwrapRNode(lView[secondParam]);
13996
- const callback = lCleanup[tCleanup[i++]];
13997
- const useCaptureOrIndx = tCleanup[i++];
13998
- // if useCaptureOrIndx is boolean then report it as is.
13999
- // if useCaptureOrIndx is positive number then it in unsubscribe method
14000
- // if useCaptureOrIndx is negative number then it is a Subscription
14001
- const type = (typeof useCaptureOrIndx === 'boolean' || useCaptureOrIndx >= 0) ? 'dom' : 'output';
14002
- const useCapture = typeof useCaptureOrIndx === 'boolean' ? useCaptureOrIndx : false;
14003
- if (element == listenerElement) {
14004
- listeners.push({ element, name, callback, useCapture, type });
14005
- }
14006
- }
14007
- }
13859
+ function ɵɵCopyDefinitionFeature(definition) {
13860
+ let superType = getSuperType(definition.type);
13861
+ let superDef = undefined;
13862
+ if (isComponentDef(definition)) {
13863
+ // Don't use getComponentDef/getDirectiveDef. This logic relies on inheritance.
13864
+ superDef = superType.ɵcmp;
14008
13865
  }
14009
- listeners.sort(sortListeners);
14010
- return listeners;
14011
- }
14012
- function sortListeners(a, b) {
14013
- if (a.name == b.name)
14014
- return 0;
14015
- return a.name < b.name ? -1 : 1;
14016
- }
14017
- /**
14018
- * This function should not exist because it is megamorphic and only mostly correct.
14019
- *
14020
- * See call site for more info.
14021
- */
14022
- function isDirectiveDefHack(obj) {
14023
- return obj.type !== undefined && obj.template !== undefined && obj.declaredInputs !== undefined;
14024
- }
14025
- /**
14026
- * Returns the attached `DebugNode` instance for an element in the DOM.
14027
- *
14028
- * @param element DOM element which is owned by an existing component's view.
14029
- */
14030
- function getDebugNode(element) {
14031
- if (ngDevMode && !(element instanceof Node)) {
14032
- throw new Error('Expecting instance of DOM Element');
13866
+ else {
13867
+ // Don't use getComponentDef/getDirectiveDef. This logic relies on inheritance.
13868
+ superDef = superType.ɵdir;
14033
13869
  }
14034
- const lContext = getLContext(element);
14035
- const lView = lContext ? lContext.lView : null;
14036
- if (lView === null) {
14037
- return null;
13870
+ // Needed because `definition` fields are readonly.
13871
+ const defAny = definition;
13872
+ // Copy over any fields that apply to either directives or components.
13873
+ for (const field of COPY_DIRECTIVE_FIELDS) {
13874
+ defAny[field] = superDef[field];
14038
13875
  }
14039
- const nodeIndex = lContext.nodeIndex;
14040
- if (nodeIndex !== -1) {
14041
- const valueInLView = lView[nodeIndex];
14042
- // this means that value in the lView is a component with its own
14043
- // data. In this situation the TNode is not accessed at the same spot.
14044
- const tNode = isLView(valueInLView) ? valueInLView[T_HOST] : getTNode(lView[TVIEW], nodeIndex);
14045
- ngDevMode &&
14046
- assertEqual(tNode.index, nodeIndex, 'Expecting that TNode at index is same as index');
14047
- return buildDebugNode(tNode, lView);
13876
+ if (isComponentDef(superDef)) {
13877
+ // Copy over any component-specific fields.
13878
+ for (const field of COPY_COMPONENT_FIELDS) {
13879
+ defAny[field] = superDef[field];
13880
+ }
14048
13881
  }
14049
- return null;
14050
13882
  }
13883
+
14051
13884
  /**
14052
- * Retrieve the component `LView` from component/element.
14053
- *
14054
- * NOTE: `LView` is a private and should not be leaked outside.
14055
- * Don't export this method to `ng.*` on window.
13885
+ * @license
13886
+ * Copyright Google LLC All Rights Reserved.
14056
13887
  *
14057
- * @param target DOM element or component instance for which to retrieve the LView.
13888
+ * Use of this source code is governed by an MIT-style license that can be
13889
+ * found in the LICENSE file at https://angular.io/license
14058
13890
  */
14059
- function getComponentLView(target) {
14060
- const lContext = getLContext(target);
14061
- const nodeIndx = lContext.nodeIndex;
14062
- const lView = lContext.lView;
14063
- ngDevMode && assertLView(lView);
14064
- const componentLView = lView[nodeIndx];
14065
- ngDevMode && assertLView(componentLView);
14066
- return componentLView;
14067
- }
14068
- /** Asserts that a value is a DOM Element. */
14069
- function assertDomElement(value) {
14070
- if (typeof Element !== 'undefined' && !(value instanceof Element)) {
14071
- throw new Error('Expecting instance of DOM Element');
13891
+ let _symbolIterator = null;
13892
+ function getSymbolIterator() {
13893
+ if (!_symbolIterator) {
13894
+ const Symbol = _global$1['Symbol'];
13895
+ if (Symbol && Symbol.iterator) {
13896
+ _symbolIterator = Symbol.iterator;
13897
+ }
13898
+ else {
13899
+ // es6-shim specific logic
13900
+ const keys = Object.getOwnPropertyNames(Map.prototype);
13901
+ for (let i = 0; i < keys.length; ++i) {
13902
+ const key = keys[i];
13903
+ if (key !== 'entries' && key !== 'size' &&
13904
+ Map.prototype[key] === Map.prototype['entries']) {
13905
+ _symbolIterator = key;
13906
+ }
13907
+ }
13908
+ }
14072
13909
  }
13910
+ return _symbolIterator;
14073
13911
  }
14074
13912
 
14075
13913
  /**
@@ -14079,18 +13917,46 @@ function assertDomElement(value) {
14079
13917
  * Use of this source code is governed by an MIT-style license that can be
14080
13918
  * found in the LICENSE file at https://angular.io/license
14081
13919
  */
14082
- /**
14083
- * Marks a component for check (in case of OnPush components) and synchronously
14084
- * performs change detection on the application this component belongs to.
14085
- *
14086
- * @param component Component to {@link ChangeDetectorRef#markForCheck mark for check}.
14087
- *
14088
- * @publicApi
14089
- * @globalApi ng
14090
- */
14091
- function applyChanges(component) {
14092
- markDirty(component);
14093
- getRootComponents(component).forEach(rootComponent => detectChanges(rootComponent));
13920
+ function isIterable(obj) {
13921
+ return obj !== null && typeof obj === 'object' && obj[getSymbolIterator()] !== undefined;
13922
+ }
13923
+ function isListLikeIterable(obj) {
13924
+ if (!isJsObject(obj))
13925
+ return false;
13926
+ return Array.isArray(obj) ||
13927
+ (!(obj instanceof Map) && // JS Map are iterables but return entries as [k, v]
13928
+ getSymbolIterator() in obj); // JS Iterable have a Symbol.iterator prop
13929
+ }
13930
+ function areIterablesEqual(a, b, comparator) {
13931
+ const iterator1 = a[getSymbolIterator()]();
13932
+ const iterator2 = b[getSymbolIterator()]();
13933
+ while (true) {
13934
+ const item1 = iterator1.next();
13935
+ const item2 = iterator2.next();
13936
+ if (item1.done && item2.done)
13937
+ return true;
13938
+ if (item1.done || item2.done)
13939
+ return false;
13940
+ if (!comparator(item1.value, item2.value))
13941
+ return false;
13942
+ }
13943
+ }
13944
+ function iterateListLike(obj, fn) {
13945
+ if (Array.isArray(obj)) {
13946
+ for (let i = 0; i < obj.length; i++) {
13947
+ fn(obj[i]);
13948
+ }
13949
+ }
13950
+ else {
13951
+ const iterator = obj[getSymbolIterator()]();
13952
+ let item;
13953
+ while (!((item = iterator.next()).done)) {
13954
+ fn(item.value);
13955
+ }
13956
+ }
13957
+ }
13958
+ function isJsObject(o) {
13959
+ return o !== null && (typeof o === 'function' || typeof o === 'object');
14094
13960
  }
14095
13961
 
14096
13962
  /**
@@ -14100,67 +13966,20 @@ function applyChanges(component) {
14100
13966
  * Use of this source code is governed by an MIT-style license that can be
14101
13967
  * found in the LICENSE file at https://angular.io/license
14102
13968
  */
14103
- /**
14104
- * This file introduces series of globally accessible debug tools
14105
- * to allow for the Angular debugging story to function.
14106
- *
14107
- * To see this in action run the following command:
14108
- *
14109
- * bazel run //packages/core/test/bundling/todo:devserver
14110
- *
14111
- * Then load `localhost:5432` and start using the console tools.
14112
- */
14113
- /**
14114
- * This value reflects the property on the window where the dev
14115
- * tools are patched (window.ng).
14116
- * */
14117
- const GLOBAL_PUBLISH_EXPANDO_KEY = 'ng';
14118
- let _published = false;
14119
- /**
14120
- * Publishes a collection of default debug tools onto`window.ng`.
14121
- *
14122
- * These functions are available globally when Angular is in development
14123
- * mode and are automatically stripped away from prod mode is on.
14124
- */
14125
- function publishDefaultGlobalUtils() {
14126
- if (!_published) {
14127
- _published = true;
14128
- /**
14129
- * Warning: this function is *INTERNAL* and should not be relied upon in application's code.
14130
- * The contract of the function might be changed in any release and/or the function can be
14131
- * removed completely.
14132
- */
14133
- publishGlobalUtil('ɵsetProfiler', setProfiler);
14134
- publishGlobalUtil('getDirectiveMetadata', getDirectiveMetadata);
14135
- publishGlobalUtil('getComponent', getComponent$1);
14136
- publishGlobalUtil('getContext', getContext);
14137
- publishGlobalUtil('getListeners', getListeners);
14138
- publishGlobalUtil('getOwningComponent', getOwningComponent);
14139
- publishGlobalUtil('getHostElement', getHostElement);
14140
- publishGlobalUtil('getInjector', getInjector);
14141
- publishGlobalUtil('getRootComponents', getRootComponents);
14142
- publishGlobalUtil('getDirectives', getDirectives);
14143
- publishGlobalUtil('applyChanges', applyChanges);
13969
+ function devModeEqual(a, b) {
13970
+ const isListLikeIterableA = isListLikeIterable(a);
13971
+ const isListLikeIterableB = isListLikeIterable(b);
13972
+ if (isListLikeIterableA && isListLikeIterableB) {
13973
+ return areIterablesEqual(a, b, devModeEqual);
14144
13974
  }
14145
- }
14146
- /**
14147
- * Publishes the given function to `window.ng` so that it can be
14148
- * used from the browser console when an application is not in production.
14149
- */
14150
- function publishGlobalUtil(name, fn) {
14151
- if (typeof COMPILED === 'undefined' || !COMPILED) {
14152
- // Note: we can't export `ng` when using closure enhanced optimization as:
14153
- // - closure declares globals itself for minified names, which sometimes clobber our `ng` global
14154
- // - we can't declare a closure extern as the namespace `ng` is already used within Google
14155
- // for typings for AngularJS (via `goog.provide('ng....')`).
14156
- const w = _global$1;
14157
- ngDevMode && assertDefined(fn, 'function not defined');
14158
- if (w) {
14159
- let container = w[GLOBAL_PUBLISH_EXPANDO_KEY];
14160
- if (!container) {
14161
- container = w[GLOBAL_PUBLISH_EXPANDO_KEY] = {};
14162
- }
14163
- container[name] = fn;
13975
+ else {
13976
+ const isAObject = a && (typeof a === 'object' || typeof a === 'function');
13977
+ const isBObject = b && (typeof b === 'object' || typeof b === 'function');
13978
+ if (!isListLikeIterableA && isAObject && !isListLikeIterableB && isBObject) {
13979
+ return true;
13980
+ }
13981
+ else {
13982
+ return Object.is(a, b);
14164
13983
  }
14165
13984
  }
14166
13985
  }
@@ -14172,186 +13991,104 @@ function publishGlobalUtil(name, fn) {
14172
13991
  * Use of this source code is governed by an MIT-style license that can be
14173
13992
  * found in the LICENSE file at https://angular.io/license
14174
13993
  */
14175
- // TODO: A hack to not pull in the NullInjector from @angular/core.
14176
- const NULL_INJECTOR = {
14177
- get: (token, notFoundValue) => {
14178
- throwProviderNotFoundError(token, 'NullInjector');
14179
- }
14180
- };
14181
- /**
14182
- * Bootstraps a Component into an existing host element and returns an instance
14183
- * of the component.
14184
- *
14185
- * Use this function to bootstrap a component into the DOM tree. Each invocation
14186
- * of this function will create a separate tree of components, injectors and
14187
- * change detection cycles and lifetimes. To dynamically insert a new component
14188
- * into an existing tree such that it shares the same injection, change detection
14189
- * and object lifetime, use {@link ViewContainer#createComponent}.
14190
- *
14191
- * @param componentType Component to bootstrap
14192
- * @param options Optional parameters which control bootstrapping
14193
- */
14194
- function renderComponent(componentType /* Type as workaround for: Microsoft/TypeScript/issues/4881 */, opts = {}) {
14195
- ngDevMode && publishDefaultGlobalUtils();
14196
- ngDevMode && assertComponentType(componentType);
14197
- enableRenderer3();
14198
- const rendererFactory = opts.rendererFactory || domRendererFactory3;
14199
- const sanitizer = opts.sanitizer || null;
14200
- const componentDef = getComponentDef$1(componentType);
14201
- if (componentDef.type != componentType)
14202
- componentDef.type = componentType;
14203
- // The first index of the first selector is the tag name.
14204
- const componentTag = componentDef.selectors[0][0];
14205
- const hostRenderer = rendererFactory.createRenderer(null, null);
14206
- const hostRNode = locateHostElement(hostRenderer, opts.host || componentTag, componentDef.encapsulation);
14207
- const rootFlags = componentDef.onPush ? 32 /* LViewFlags.Dirty */ | 256 /* LViewFlags.IsRoot */ :
14208
- 16 /* LViewFlags.CheckAlways */ | 256 /* LViewFlags.IsRoot */;
14209
- const rootContext = createRootContext(opts.scheduler, opts.playerHandler);
14210
- const renderer = rendererFactory.createRenderer(hostRNode, componentDef);
14211
- const rootTView = createTView(0 /* TViewType.Root */, null, null, 1, 0, null, null, null, null, null);
14212
- const rootView = createLView(null, rootTView, rootContext, rootFlags, null, null, rendererFactory, renderer, null, opts.injector || null, null);
14213
- enterView(rootView);
14214
- let component;
14215
- try {
14216
- if (rendererFactory.begin)
14217
- rendererFactory.begin();
14218
- const componentView = createRootComponentView(hostRNode, componentDef, rootView, rendererFactory, renderer, sanitizer);
14219
- component = createRootComponent(componentView, componentDef, rootView, rootContext, opts.hostFeatures || null);
14220
- // create mode pass
14221
- renderView(rootTView, rootView, null);
14222
- // update mode pass
14223
- refreshView(rootTView, rootView, null, null);
14224
- }
14225
- finally {
14226
- leaveView();
14227
- if (rendererFactory.end)
14228
- rendererFactory.end();
14229
- }
14230
- return component;
13994
+ // TODO(misko): consider inlining
13995
+ /** Updates binding and returns the value. */
13996
+ function updateBinding(lView, bindingIndex, value) {
13997
+ return lView[bindingIndex] = value;
13998
+ }
13999
+ /** Gets the current binding value. */
14000
+ function getBinding(lView, bindingIndex) {
14001
+ ngDevMode && assertIndexInRange(lView, bindingIndex);
14002
+ ngDevMode &&
14003
+ assertNotSame(lView[bindingIndex], NO_CHANGE, 'Stored value should never be NO_CHANGE.');
14004
+ return lView[bindingIndex];
14231
14005
  }
14232
14006
  /**
14233
- * Creates the root component view and the root component node.
14007
+ * Updates binding if changed, then returns whether it was updated.
14234
14008
  *
14235
- * @param rNode Render host element.
14236
- * @param def ComponentDef
14237
- * @param rootView The parent view where the host node is stored
14238
- * @param rendererFactory Factory to be used for creating child renderers.
14239
- * @param hostRenderer The current renderer
14240
- * @param sanitizer The sanitizer, if provided
14009
+ * This function also checks the `CheckNoChangesMode` and throws if changes are made.
14010
+ * Some changes (Objects/iterables) during `CheckNoChangesMode` are exempt to comply with VE
14011
+ * behavior.
14241
14012
  *
14242
- * @returns Component view created
14013
+ * @param lView current `LView`
14014
+ * @param bindingIndex The binding in the `LView` to check
14015
+ * @param value New value to check against `lView[bindingIndex]`
14016
+ * @returns `true` if the bindings has changed. (Throws if binding has changed during
14017
+ * `CheckNoChangesMode`)
14243
14018
  */
14244
- function createRootComponentView(rNode, def, rootView, rendererFactory, hostRenderer, sanitizer) {
14245
- const tView = rootView[TVIEW];
14246
- const index = HEADER_OFFSET;
14247
- ngDevMode && assertIndexInRange(rootView, index);
14248
- rootView[index] = rNode;
14249
- // '#host' is added here as we don't know the real host DOM name (we don't want to read it) and at
14250
- // the same time we want to communicate the debug `TNode` that this is a special `TNode`
14251
- // representing a host element.
14252
- const tNode = getOrCreateTNode(tView, index, 2 /* TNodeType.Element */, '#host', null);
14253
- const mergedAttrs = tNode.mergedAttrs = def.hostAttrs;
14254
- if (mergedAttrs !== null) {
14255
- computeStaticStyling(tNode, mergedAttrs, true);
14256
- if (rNode !== null) {
14257
- setUpAttributes(hostRenderer, rNode, mergedAttrs);
14258
- if (tNode.classes !== null) {
14259
- writeDirectClass(hostRenderer, rNode, tNode.classes);
14260
- }
14261
- if (tNode.styles !== null) {
14262
- writeDirectStyle(hostRenderer, rNode, tNode.styles);
14019
+ function bindingUpdated(lView, bindingIndex, value) {
14020
+ ngDevMode && assertNotSame(value, NO_CHANGE, 'Incoming value should never be NO_CHANGE.');
14021
+ ngDevMode &&
14022
+ assertLessThan(bindingIndex, lView.length, `Slot should have been initialized to NO_CHANGE`);
14023
+ const oldValue = lView[bindingIndex];
14024
+ if (Object.is(oldValue, value)) {
14025
+ return false;
14026
+ }
14027
+ else {
14028
+ if (ngDevMode && isInCheckNoChangesMode()) {
14029
+ // View engine didn't report undefined values as changed on the first checkNoChanges pass
14030
+ // (before the change detection was run).
14031
+ const oldValueToCompare = oldValue !== NO_CHANGE ? oldValue : undefined;
14032
+ if (!devModeEqual(oldValueToCompare, value)) {
14033
+ const details = getExpressionChangedErrorDetails(lView, bindingIndex, oldValueToCompare, value);
14034
+ throwErrorIfNoChangesMode(oldValue === NO_CHANGE, details.oldValue, details.newValue, details.propName);
14263
14035
  }
14036
+ // There was a change, but the `devModeEqual` decided that the change is exempt from an error.
14037
+ // For this reason we exit as if no change. The early exit is needed to prevent the changed
14038
+ // value to be written into `LView` (If we would write the new value that we would not see it
14039
+ // as change on next CD.)
14040
+ return false;
14264
14041
  }
14042
+ lView[bindingIndex] = value;
14043
+ return true;
14265
14044
  }
14266
- const viewRenderer = rendererFactory.createRenderer(rNode, def);
14267
- const componentView = createLView(rootView, getOrCreateTComponentView(def), null, def.onPush ? 32 /* LViewFlags.Dirty */ : 16 /* LViewFlags.CheckAlways */, rootView[index], tNode, rendererFactory, viewRenderer, sanitizer || null, null, null);
14268
- if (tView.firstCreatePass) {
14269
- diPublicInInjector(getOrCreateNodeInjectorForNode(tNode, rootView), tView, def.type);
14270
- markAsComponentHost(tView, tNode);
14271
- initTNodeFlags(tNode, rootView.length, 1);
14272
- }
14273
- addToViewTree(rootView, componentView);
14274
- // Store component view at node index, with node as the HOST
14275
- return rootView[index] = componentView;
14276
14045
  }
14277
- /**
14278
- * Creates a root component and sets it up with features and host bindings. Shared by
14279
- * renderComponent() and ViewContainerRef.createComponent().
14280
- */
14281
- function createRootComponent(componentView, componentDef, rootLView, rootContext, hostFeatures) {
14282
- const tView = rootLView[TVIEW];
14283
- // Create directive instance with factory() and store at next index in viewData
14284
- const component = instantiateRootComponent(tView, rootLView, componentDef);
14285
- rootContext.components.push(component);
14286
- componentView[CONTEXT] = component;
14287
- if (hostFeatures !== null) {
14288
- for (const feature of hostFeatures) {
14289
- feature(component, componentDef);
14290
- }
14291
- }
14292
- // We want to generate an empty QueryList for root content queries for backwards
14293
- // compatibility with ViewEngine.
14294
- if (componentDef.contentQueries) {
14295
- const tNode = getCurrentTNode();
14296
- ngDevMode && assertDefined(tNode, 'TNode expected');
14297
- componentDef.contentQueries(1 /* RenderFlags.Create */, component, tNode.directiveStart);
14298
- }
14299
- const rootTNode = getCurrentTNode();
14300
- ngDevMode && assertDefined(rootTNode, 'tNode should have been already created');
14301
- if (tView.firstCreatePass &&
14302
- (componentDef.hostBindings !== null || componentDef.hostAttrs !== null)) {
14303
- setSelectedIndex(rootTNode.index);
14304
- const rootTView = rootLView[TVIEW];
14305
- registerHostBindingOpCodes(rootTView, rootTNode, rootLView, rootTNode.directiveStart, rootTNode.directiveEnd, componentDef);
14306
- invokeHostBindingsInCreationMode(componentDef, component);
14307
- }
14308
- return component;
14046
+ /** Updates 2 bindings if changed, then returns whether either was updated. */
14047
+ function bindingUpdated2(lView, bindingIndex, exp1, exp2) {
14048
+ const different = bindingUpdated(lView, bindingIndex, exp1);
14049
+ return bindingUpdated(lView, bindingIndex + 1, exp2) || different;
14309
14050
  }
14310
- function createRootContext(scheduler, playerHandler) {
14311
- return {
14312
- components: [],
14313
- scheduler: scheduler || defaultScheduler,
14314
- clean: CLEAN_PROMISE,
14315
- playerHandler: playerHandler || null,
14316
- flags: 0 /* RootContextFlags.Empty */
14317
- };
14051
+ /** Updates 3 bindings if changed, then returns whether any was updated. */
14052
+ function bindingUpdated3(lView, bindingIndex, exp1, exp2, exp3) {
14053
+ const different = bindingUpdated2(lView, bindingIndex, exp1, exp2);
14054
+ return bindingUpdated(lView, bindingIndex + 2, exp3) || different;
14055
+ }
14056
+ /** Updates 4 bindings if changed, then returns whether any was updated. */
14057
+ function bindingUpdated4(lView, bindingIndex, exp1, exp2, exp3, exp4) {
14058
+ const different = bindingUpdated2(lView, bindingIndex, exp1, exp2);
14059
+ return bindingUpdated2(lView, bindingIndex + 2, exp3, exp4) || different;
14318
14060
  }
14061
+
14319
14062
  /**
14320
- * Used to enable lifecycle hooks on the root component.
14321
- *
14322
- * Include this feature when calling `renderComponent` if the root component
14323
- * you are rendering has lifecycle hooks defined. Otherwise, the hooks won't
14324
- * be called properly.
14325
- *
14326
- * Example:
14063
+ * @license
14064
+ * Copyright Google LLC All Rights Reserved.
14327
14065
  *
14328
- * ```
14329
- * renderComponent(AppComponent, {hostFeatures: [LifecycleHooksFeature]});
14330
- * ```
14066
+ * Use of this source code is governed by an MIT-style license that can be
14067
+ * found in the LICENSE file at https://angular.io/license
14331
14068
  */
14332
- function LifecycleHooksFeature() {
14333
- const tNode = getCurrentTNode();
14334
- ngDevMode && assertDefined(tNode, 'TNode is required');
14335
- registerPostOrderHooks(getLView()[TVIEW], tNode);
14336
- }
14337
14069
  /**
14338
- * Wait on component until it is rendered.
14070
+ * Updates the value of or removes a bound attribute on an Element.
14339
14071
  *
14340
- * This function returns a `Promise` which is resolved when the component's
14341
- * change detection is executed. This is determined by finding the scheduler
14342
- * associated with the `component`'s render tree and waiting until the scheduler
14343
- * flushes. If nothing is scheduled, the function returns a resolved promise.
14072
+ * Used in the case of `[attr.title]="value"`
14344
14073
  *
14345
- * Example:
14346
- * ```
14347
- * await whenRendered(myComponent);
14348
- * ```
14074
+ * @param name name The name of the attribute.
14075
+ * @param value value The attribute is removed when value is `null` or `undefined`.
14076
+ * Otherwise the attribute value is set to the stringified value.
14077
+ * @param sanitizer An optional function used to sanitize the value.
14078
+ * @param namespace Optional namespace to use when setting the attribute.
14349
14079
  *
14350
- * @param component Component to wait upon
14351
- * @returns Promise which resolves when the component is rendered.
14080
+ * @codeGenApi
14352
14081
  */
14353
- function whenRendered(component) {
14354
- return getRootContext(component).clean;
14082
+ function ɵɵattribute(name, value, sanitizer, namespace) {
14083
+ const lView = getLView();
14084
+ const bindingIndex = nextBindingIndex();
14085
+ if (bindingUpdated(lView, bindingIndex, value)) {
14086
+ const tView = getTView();
14087
+ const tNode = getSelectedTNode();
14088
+ elementAttributeInternal(tNode, lView, name, value, sanitizer, namespace);
14089
+ ngDevMode && storePropertyBindingMetadata(tView.data, tNode, 'attr.' + name, bindingIndex);
14090
+ }
14091
+ return ɵɵattribute;
14355
14092
  }
14356
14093
 
14357
14094
  /**
@@ -14361,700 +14098,253 @@ function whenRendered(component) {
14361
14098
  * Use of this source code is governed by an MIT-style license that can be
14362
14099
  * found in the LICENSE file at https://angular.io/license
14363
14100
  */
14364
- function getSuperType(type) {
14365
- return Object.getPrototypeOf(type.prototype).constructor;
14366
- }
14367
14101
  /**
14368
- * Merges the definition from a super class to a sub class.
14369
- * @param definition The definition that is a SubClass of another directive of component
14102
+ * Create interpolation bindings with a variable number of expressions.
14370
14103
  *
14371
- * @codeGenApi
14372
- */
14373
- function ɵɵInheritDefinitionFeature(definition) {
14374
- let superType = getSuperType(definition.type);
14375
- let shouldInheritFields = true;
14376
- const inheritanceChain = [definition];
14377
- while (superType) {
14378
- let superDef = undefined;
14379
- if (isComponentDef(definition)) {
14380
- // Don't use getComponentDef/getDirectiveDef. This logic relies on inheritance.
14381
- superDef = superType.ɵcmp || superType.ɵdir;
14382
- }
14383
- else {
14384
- if (superType.ɵcmp) {
14385
- throw new RuntimeError(903 /* RuntimeErrorCode.INVALID_INHERITANCE */, ngDevMode &&
14386
- `Directives cannot inherit Components. Directive ${stringifyForError(definition.type)} is attempting to extend component ${stringifyForError(superType)}`);
14387
- }
14388
- // Don't use getComponentDef/getDirectiveDef. This logic relies on inheritance.
14389
- superDef = superType.ɵdir;
14390
- }
14391
- if (superDef) {
14392
- if (shouldInheritFields) {
14393
- inheritanceChain.push(superDef);
14394
- // Some fields in the definition may be empty, if there were no values to put in them that
14395
- // would've justified object creation. Unwrap them if necessary.
14396
- const writeableDef = definition;
14397
- writeableDef.inputs = maybeUnwrapEmpty(definition.inputs);
14398
- writeableDef.declaredInputs = maybeUnwrapEmpty(definition.declaredInputs);
14399
- writeableDef.outputs = maybeUnwrapEmpty(definition.outputs);
14400
- // Merge hostBindings
14401
- const superHostBindings = superDef.hostBindings;
14402
- superHostBindings && inheritHostBindings(definition, superHostBindings);
14403
- // Merge queries
14404
- const superViewQuery = superDef.viewQuery;
14405
- const superContentQueries = superDef.contentQueries;
14406
- superViewQuery && inheritViewQuery(definition, superViewQuery);
14407
- superContentQueries && inheritContentQueries(definition, superContentQueries);
14408
- // Merge inputs and outputs
14409
- fillProperties(definition.inputs, superDef.inputs);
14410
- fillProperties(definition.declaredInputs, superDef.declaredInputs);
14411
- fillProperties(definition.outputs, superDef.outputs);
14412
- // Merge animations metadata.
14413
- // If `superDef` is a Component, the `data` field is present (defaults to an empty object).
14414
- if (isComponentDef(superDef) && superDef.data.animation) {
14415
- // If super def is a Component, the `definition` is also a Component, since Directives can
14416
- // not inherit Components (we throw an error above and cannot reach this code).
14417
- const defData = definition.data;
14418
- defData.animation = (defData.animation || []).concat(superDef.data.animation);
14419
- }
14420
- }
14421
- // Run parent features
14422
- const features = superDef.features;
14423
- if (features) {
14424
- for (let i = 0; i < features.length; i++) {
14425
- const feature = features[i];
14426
- if (feature && feature.ngInherit) {
14427
- feature(definition);
14428
- }
14429
- // If `InheritDefinitionFeature` is a part of the current `superDef`, it means that this
14430
- // def already has all the necessary information inherited from its super class(es), so we
14431
- // can stop merging fields from super classes. However we need to iterate through the
14432
- // prototype chain to look for classes that might contain other "features" (like
14433
- // NgOnChanges), which we should invoke for the original `definition`. We set the
14434
- // `shouldInheritFields` flag to indicate that, essentially skipping fields inheritance
14435
- // logic and only invoking functions from the "features" list.
14436
- if (feature === ɵɵInheritDefinitionFeature) {
14437
- shouldInheritFields = false;
14438
- }
14439
- }
14440
- }
14441
- }
14442
- superType = Object.getPrototypeOf(superType);
14443
- }
14444
- mergeHostAttrsAcrossInheritance(inheritanceChain);
14445
- }
14446
- /**
14447
- * Merge the `hostAttrs` and `hostVars` from the inherited parent to the base class.
14104
+ * If there are 1 to 8 expressions `interpolation1()` to `interpolation8()` should be used instead.
14105
+ * Those are faster because there is no need to create an array of expressions and iterate over it.
14448
14106
  *
14449
- * @param inheritanceChain A list of `WritableDefs` starting at the top most type and listing
14450
- * sub-types in order. For each type take the `hostAttrs` and `hostVars` and merge it with the child
14451
- * type.
14107
+ * `values`:
14108
+ * - has static text at even indexes,
14109
+ * - has evaluated expressions at odd indexes.
14110
+ *
14111
+ * Returns the concatenated string when any of the arguments changes, `NO_CHANGE` otherwise.
14452
14112
  */
14453
- function mergeHostAttrsAcrossInheritance(inheritanceChain) {
14454
- let hostVars = 0;
14455
- let hostAttrs = null;
14456
- // We process the inheritance order from the base to the leaves here.
14457
- for (let i = inheritanceChain.length - 1; i >= 0; i--) {
14458
- const def = inheritanceChain[i];
14459
- // For each `hostVars`, we need to add the superclass amount.
14460
- def.hostVars = (hostVars += def.hostVars);
14461
- // for each `hostAttrs` we need to merge it with superclass.
14462
- def.hostAttrs =
14463
- mergeHostAttrs(def.hostAttrs, hostAttrs = mergeHostAttrs(hostAttrs, def.hostAttrs));
14464
- }
14465
- }
14466
- function maybeUnwrapEmpty(value) {
14467
- if (value === EMPTY_OBJ) {
14468
- return {};
14113
+ function interpolationV(lView, values) {
14114
+ ngDevMode && assertLessThan(2, values.length, 'should have at least 3 values');
14115
+ ngDevMode && assertEqual(values.length % 2, 1, 'should have an odd number of values');
14116
+ let isBindingUpdated = false;
14117
+ let bindingIndex = getBindingIndex();
14118
+ for (let i = 1; i < values.length; i += 2) {
14119
+ // Check if bindings (odd indexes) have changed
14120
+ isBindingUpdated = bindingUpdated(lView, bindingIndex++, values[i]) || isBindingUpdated;
14469
14121
  }
14470
- else if (value === EMPTY_ARRAY) {
14471
- return [];
14122
+ setBindingIndex(bindingIndex);
14123
+ if (!isBindingUpdated) {
14124
+ return NO_CHANGE;
14472
14125
  }
14473
- else {
14474
- return value;
14126
+ // Build the updated content
14127
+ let content = values[0];
14128
+ for (let i = 1; i < values.length; i += 2) {
14129
+ content += renderStringify(values[i]) + values[i + 1];
14475
14130
  }
14131
+ return content;
14476
14132
  }
14477
- function inheritViewQuery(definition, superViewQuery) {
14478
- const prevViewQuery = definition.viewQuery;
14479
- if (prevViewQuery) {
14480
- definition.viewQuery = (rf, ctx) => {
14481
- superViewQuery(rf, ctx);
14482
- prevViewQuery(rf, ctx);
14483
- };
14484
- }
14485
- else {
14486
- definition.viewQuery = superViewQuery;
14487
- }
14133
+ /**
14134
+ * Creates an interpolation binding with 1 expression.
14135
+ *
14136
+ * @param prefix static value used for concatenation only.
14137
+ * @param v0 value checked for change.
14138
+ * @param suffix static value used for concatenation only.
14139
+ */
14140
+ function interpolation1(lView, prefix, v0, suffix) {
14141
+ const different = bindingUpdated(lView, nextBindingIndex(), v0);
14142
+ return different ? prefix + renderStringify(v0) + suffix : NO_CHANGE;
14488
14143
  }
14489
- function inheritContentQueries(definition, superContentQueries) {
14490
- const prevContentQueries = definition.contentQueries;
14491
- if (prevContentQueries) {
14492
- definition.contentQueries = (rf, ctx, directiveIndex) => {
14493
- superContentQueries(rf, ctx, directiveIndex);
14494
- prevContentQueries(rf, ctx, directiveIndex);
14495
- };
14496
- }
14497
- else {
14498
- definition.contentQueries = superContentQueries;
14499
- }
14144
+ /**
14145
+ * Creates an interpolation binding with 2 expressions.
14146
+ */
14147
+ function interpolation2(lView, prefix, v0, i0, v1, suffix) {
14148
+ const bindingIndex = getBindingIndex();
14149
+ const different = bindingUpdated2(lView, bindingIndex, v0, v1);
14150
+ incrementBindingIndex(2);
14151
+ return different ? prefix + renderStringify(v0) + i0 + renderStringify(v1) + suffix : NO_CHANGE;
14500
14152
  }
14501
- function inheritHostBindings(definition, superHostBindings) {
14502
- const prevHostBindings = definition.hostBindings;
14503
- if (prevHostBindings) {
14504
- definition.hostBindings = (rf, ctx) => {
14505
- superHostBindings(rf, ctx);
14506
- prevHostBindings(rf, ctx);
14507
- };
14508
- }
14509
- else {
14510
- definition.hostBindings = superHostBindings;
14511
- }
14153
+ /**
14154
+ * Creates an interpolation binding with 3 expressions.
14155
+ */
14156
+ function interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix) {
14157
+ const bindingIndex = getBindingIndex();
14158
+ const different = bindingUpdated3(lView, bindingIndex, v0, v1, v2);
14159
+ incrementBindingIndex(3);
14160
+ return different ?
14161
+ prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 + renderStringify(v2) + suffix :
14162
+ NO_CHANGE;
14512
14163
  }
14513
-
14514
14164
  /**
14515
- * @license
14516
- * Copyright Google LLC All Rights Reserved.
14517
- *
14518
- * Use of this source code is governed by an MIT-style license that can be
14519
- * found in the LICENSE file at https://angular.io/license
14165
+ * Create an interpolation binding with 4 expressions.
14520
14166
  */
14167
+ function interpolation4(lView, prefix, v0, i0, v1, i1, v2, i2, v3, suffix) {
14168
+ const bindingIndex = getBindingIndex();
14169
+ const different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);
14170
+ incrementBindingIndex(4);
14171
+ return different ? prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 +
14172
+ renderStringify(v2) + i2 + renderStringify(v3) + suffix :
14173
+ NO_CHANGE;
14174
+ }
14521
14175
  /**
14522
- * Fields which exist on either directive or component definitions, and need to be copied from
14523
- * parent to child classes by the `ɵɵCopyDefinitionFeature`.
14176
+ * Creates an interpolation binding with 5 expressions.
14524
14177
  */
14525
- const COPY_DIRECTIVE_FIELDS = [
14526
- // The child class should use the providers of its parent.
14527
- 'providersResolver',
14528
- // Not listed here are any fields which are handled by the `ɵɵInheritDefinitionFeature`, such
14529
- // as inputs, outputs, and host binding functions.
14530
- ];
14178
+ function interpolation5(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix) {
14179
+ const bindingIndex = getBindingIndex();
14180
+ let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);
14181
+ different = bindingUpdated(lView, bindingIndex + 4, v4) || different;
14182
+ incrementBindingIndex(5);
14183
+ return different ? prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 +
14184
+ renderStringify(v2) + i2 + renderStringify(v3) + i3 + renderStringify(v4) + suffix :
14185
+ NO_CHANGE;
14186
+ }
14531
14187
  /**
14532
- * Fields which exist only on component definitions, and need to be copied from parent to child
14533
- * classes by the `ɵɵCopyDefinitionFeature`.
14534
- *
14535
- * The type here allows any field of `ComponentDef` which is not also a property of `DirectiveDef`,
14536
- * since those should go in `COPY_DIRECTIVE_FIELDS` above.
14188
+ * Creates an interpolation binding with 6 expressions.
14537
14189
  */
14538
- const COPY_COMPONENT_FIELDS = [
14539
- // The child class should use the template function of its parent, including all template
14540
- // semantics.
14541
- 'template',
14542
- 'decls',
14543
- 'consts',
14544
- 'vars',
14545
- 'onPush',
14546
- 'ngContentSelectors',
14547
- // The child class should use the CSS styles of its parent, including all styling semantics.
14548
- 'styles',
14549
- 'encapsulation',
14550
- // The child class should be checked by the runtime in the same way as its parent.
14551
- 'schemas',
14552
- ];
14190
+ function interpolation6(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix) {
14191
+ const bindingIndex = getBindingIndex();
14192
+ let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);
14193
+ different = bindingUpdated2(lView, bindingIndex + 4, v4, v5) || different;
14194
+ incrementBindingIndex(6);
14195
+ return different ?
14196
+ prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 + renderStringify(v2) + i2 +
14197
+ renderStringify(v3) + i3 + renderStringify(v4) + i4 + renderStringify(v5) + suffix :
14198
+ NO_CHANGE;
14199
+ }
14200
+ /**
14201
+ * Creates an interpolation binding with 7 expressions.
14202
+ */
14203
+ function interpolation7(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix) {
14204
+ const bindingIndex = getBindingIndex();
14205
+ let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);
14206
+ different = bindingUpdated3(lView, bindingIndex + 4, v4, v5, v6) || different;
14207
+ incrementBindingIndex(7);
14208
+ return different ? prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 +
14209
+ renderStringify(v2) + i2 + renderStringify(v3) + i3 + renderStringify(v4) + i4 +
14210
+ renderStringify(v5) + i5 + renderStringify(v6) + suffix :
14211
+ NO_CHANGE;
14212
+ }
14213
+ /**
14214
+ * Creates an interpolation binding with 8 expressions.
14215
+ */
14216
+ function interpolation8(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix) {
14217
+ const bindingIndex = getBindingIndex();
14218
+ let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);
14219
+ different = bindingUpdated4(lView, bindingIndex + 4, v4, v5, v6, v7) || different;
14220
+ incrementBindingIndex(8);
14221
+ return different ? prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 +
14222
+ renderStringify(v2) + i2 + renderStringify(v3) + i3 + renderStringify(v4) + i4 +
14223
+ renderStringify(v5) + i5 + renderStringify(v6) + i6 + renderStringify(v7) + suffix :
14224
+ NO_CHANGE;
14225
+ }
14226
+
14553
14227
  /**
14554
- * Copies the fields not handled by the `ɵɵInheritDefinitionFeature` from the supertype of a
14555
- * definition.
14556
14228
  *
14557
- * This exists primarily to support ngcc migration of an existing View Engine pattern, where an
14558
- * entire decorator is inherited from a parent to a child class. When ngcc detects this case, it
14559
- * generates a skeleton definition on the child class, and applies this feature.
14229
+ * Update an interpolated attribute on an element with single bound value surrounded by text.
14560
14230
  *
14561
- * The `ɵɵCopyDefinitionFeature` then copies any needed fields from the parent class' definition,
14562
- * including things like the component template function.
14231
+ * Used when the value passed to a property has 1 interpolated value in it:
14563
14232
  *
14564
- * @param definition The definition of a child class which inherits from a parent class with its
14565
- * own definition.
14233
+ * ```html
14234
+ * <div attr.title="prefix{{v0}}suffix"></div>
14235
+ * ```
14236
+ *
14237
+ * Its compiled representation is::
14238
+ *
14239
+ * ```ts
14240
+ * ɵɵattributeInterpolate1('title', 'prefix', v0, 'suffix');
14241
+ * ```
14566
14242
  *
14243
+ * @param attrName The name of the attribute to update
14244
+ * @param prefix Static value used for concatenation only.
14245
+ * @param v0 Value checked for change.
14246
+ * @param suffix Static value used for concatenation only.
14247
+ * @param sanitizer An optional sanitizer function
14248
+ * @returns itself, so that it may be chained.
14567
14249
  * @codeGenApi
14568
14250
  */
14569
- function ɵɵCopyDefinitionFeature(definition) {
14570
- let superType = getSuperType(definition.type);
14571
- let superDef = undefined;
14572
- if (isComponentDef(definition)) {
14573
- // Don't use getComponentDef/getDirectiveDef. This logic relies on inheritance.
14574
- superDef = superType.ɵcmp;
14575
- }
14576
- else {
14577
- // Don't use getComponentDef/getDirectiveDef. This logic relies on inheritance.
14578
- superDef = superType.ɵdir;
14579
- }
14580
- // Needed because `definition` fields are readonly.
14581
- const defAny = definition;
14582
- // Copy over any fields that apply to either directives or components.
14583
- for (const field of COPY_DIRECTIVE_FIELDS) {
14584
- defAny[field] = superDef[field];
14585
- }
14586
- if (isComponentDef(superDef)) {
14587
- // Copy over any component-specific fields.
14588
- for (const field of COPY_COMPONENT_FIELDS) {
14589
- defAny[field] = superDef[field];
14590
- }
14251
+ function ɵɵattributeInterpolate1(attrName, prefix, v0, suffix, sanitizer, namespace) {
14252
+ const lView = getLView();
14253
+ const interpolatedValue = interpolation1(lView, prefix, v0, suffix);
14254
+ if (interpolatedValue !== NO_CHANGE) {
14255
+ const tNode = getSelectedTNode();
14256
+ elementAttributeInternal(tNode, lView, attrName, interpolatedValue, sanitizer, namespace);
14257
+ ngDevMode &&
14258
+ storePropertyBindingMetadata(getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - 1, prefix, suffix);
14591
14259
  }
14260
+ return ɵɵattributeInterpolate1;
14592
14261
  }
14593
-
14594
14262
  /**
14595
- * @license
14596
- * Copyright Google LLC All Rights Reserved.
14597
14263
  *
14598
- * Use of this source code is governed by an MIT-style license that can be
14599
- * found in the LICENSE file at https://angular.io/license
14600
- */
14601
- let _symbolIterator = null;
14602
- function getSymbolIterator() {
14603
- if (!_symbolIterator) {
14604
- const Symbol = _global$1['Symbol'];
14605
- if (Symbol && Symbol.iterator) {
14606
- _symbolIterator = Symbol.iterator;
14607
- }
14608
- else {
14609
- // es6-shim specific logic
14610
- const keys = Object.getOwnPropertyNames(Map.prototype);
14611
- for (let i = 0; i < keys.length; ++i) {
14612
- const key = keys[i];
14613
- if (key !== 'entries' && key !== 'size' &&
14614
- Map.prototype[key] === Map.prototype['entries']) {
14615
- _symbolIterator = key;
14616
- }
14617
- }
14618
- }
14619
- }
14620
- return _symbolIterator;
14621
- }
14622
-
14623
- /**
14624
- * @license
14625
- * Copyright Google LLC All Rights Reserved.
14264
+ * Update an interpolated attribute on an element with 2 bound values surrounded by text.
14626
14265
  *
14627
- * Use of this source code is governed by an MIT-style license that can be
14628
- * found in the LICENSE file at https://angular.io/license
14629
- */
14630
- function isIterable(obj) {
14631
- return obj !== null && typeof obj === 'object' && obj[getSymbolIterator()] !== undefined;
14632
- }
14633
- function isListLikeIterable(obj) {
14634
- if (!isJsObject(obj))
14635
- return false;
14636
- return Array.isArray(obj) ||
14637
- (!(obj instanceof Map) && // JS Map are iterables but return entries as [k, v]
14638
- getSymbolIterator() in obj); // JS Iterable have a Symbol.iterator prop
14639
- }
14640
- function areIterablesEqual(a, b, comparator) {
14641
- const iterator1 = a[getSymbolIterator()]();
14642
- const iterator2 = b[getSymbolIterator()]();
14643
- while (true) {
14644
- const item1 = iterator1.next();
14645
- const item2 = iterator2.next();
14646
- if (item1.done && item2.done)
14647
- return true;
14648
- if (item1.done || item2.done)
14649
- return false;
14650
- if (!comparator(item1.value, item2.value))
14651
- return false;
14652
- }
14653
- }
14654
- function iterateListLike(obj, fn) {
14655
- if (Array.isArray(obj)) {
14656
- for (let i = 0; i < obj.length; i++) {
14657
- fn(obj[i]);
14658
- }
14659
- }
14660
- else {
14661
- const iterator = obj[getSymbolIterator()]();
14662
- let item;
14663
- while (!((item = iterator.next()).done)) {
14664
- fn(item.value);
14665
- }
14666
- }
14667
- }
14668
- function isJsObject(o) {
14669
- return o !== null && (typeof o === 'function' || typeof o === 'object');
14670
- }
14671
-
14672
- /**
14673
- * @license
14674
- * Copyright Google LLC All Rights Reserved.
14266
+ * Used when the value passed to a property has 2 interpolated values in it:
14675
14267
  *
14676
- * Use of this source code is governed by an MIT-style license that can be
14677
- * found in the LICENSE file at https://angular.io/license
14678
- */
14679
- function devModeEqual(a, b) {
14680
- const isListLikeIterableA = isListLikeIterable(a);
14681
- const isListLikeIterableB = isListLikeIterable(b);
14682
- if (isListLikeIterableA && isListLikeIterableB) {
14683
- return areIterablesEqual(a, b, devModeEqual);
14684
- }
14685
- else {
14686
- const isAObject = a && (typeof a === 'object' || typeof a === 'function');
14687
- const isBObject = b && (typeof b === 'object' || typeof b === 'function');
14688
- if (!isListLikeIterableA && isAObject && !isListLikeIterableB && isBObject) {
14689
- return true;
14690
- }
14691
- else {
14692
- return Object.is(a, b);
14693
- }
14694
- }
14695
- }
14696
-
14697
- /**
14698
- * @license
14699
- * Copyright Google LLC All Rights Reserved.
14268
+ * ```html
14269
+ * <div attr.title="prefix{{v0}}-{{v1}}suffix"></div>
14270
+ * ```
14700
14271
  *
14701
- * Use of this source code is governed by an MIT-style license that can be
14702
- * found in the LICENSE file at https://angular.io/license
14703
- */
14704
- // TODO(misko): consider inlining
14705
- /** Updates binding and returns the value. */
14706
- function updateBinding(lView, bindingIndex, value) {
14707
- return lView[bindingIndex] = value;
14708
- }
14709
- /** Gets the current binding value. */
14710
- function getBinding(lView, bindingIndex) {
14711
- ngDevMode && assertIndexInRange(lView, bindingIndex);
14712
- ngDevMode &&
14713
- assertNotSame(lView[bindingIndex], NO_CHANGE, 'Stored value should never be NO_CHANGE.');
14714
- return lView[bindingIndex];
14715
- }
14716
- /**
14717
- * Updates binding if changed, then returns whether it was updated.
14272
+ * Its compiled representation is::
14718
14273
  *
14719
- * This function also checks the `CheckNoChangesMode` and throws if changes are made.
14720
- * Some changes (Objects/iterables) during `CheckNoChangesMode` are exempt to comply with VE
14721
- * behavior.
14274
+ * ```ts
14275
+ * ɵɵattributeInterpolate2('title', 'prefix', v0, '-', v1, 'suffix');
14276
+ * ```
14722
14277
  *
14723
- * @param lView current `LView`
14724
- * @param bindingIndex The binding in the `LView` to check
14725
- * @param value New value to check against `lView[bindingIndex]`
14726
- * @returns `true` if the bindings has changed. (Throws if binding has changed during
14727
- * `CheckNoChangesMode`)
14278
+ * @param attrName The name of the attribute to update
14279
+ * @param prefix Static value used for concatenation only.
14280
+ * @param v0 Value checked for change.
14281
+ * @param i0 Static value used for concatenation only.
14282
+ * @param v1 Value checked for change.
14283
+ * @param suffix Static value used for concatenation only.
14284
+ * @param sanitizer An optional sanitizer function
14285
+ * @returns itself, so that it may be chained.
14286
+ * @codeGenApi
14728
14287
  */
14729
- function bindingUpdated(lView, bindingIndex, value) {
14730
- ngDevMode && assertNotSame(value, NO_CHANGE, 'Incoming value should never be NO_CHANGE.');
14731
- ngDevMode &&
14732
- assertLessThan(bindingIndex, lView.length, `Slot should have been initialized to NO_CHANGE`);
14733
- const oldValue = lView[bindingIndex];
14734
- if (Object.is(oldValue, value)) {
14735
- return false;
14736
- }
14737
- else {
14738
- if (ngDevMode && isInCheckNoChangesMode()) {
14739
- // View engine didn't report undefined values as changed on the first checkNoChanges pass
14740
- // (before the change detection was run).
14741
- const oldValueToCompare = oldValue !== NO_CHANGE ? oldValue : undefined;
14742
- if (!devModeEqual(oldValueToCompare, value)) {
14743
- const details = getExpressionChangedErrorDetails(lView, bindingIndex, oldValueToCompare, value);
14744
- throwErrorIfNoChangesMode(oldValue === NO_CHANGE, details.oldValue, details.newValue, details.propName);
14745
- }
14746
- // There was a change, but the `devModeEqual` decided that the change is exempt from an error.
14747
- // For this reason we exit as if no change. The early exit is needed to prevent the changed
14748
- // value to be written into `LView` (If we would write the new value that we would not see it
14749
- // as change on next CD.)
14750
- return false;
14751
- }
14752
- lView[bindingIndex] = value;
14753
- return true;
14288
+ function ɵɵattributeInterpolate2(attrName, prefix, v0, i0, v1, suffix, sanitizer, namespace) {
14289
+ const lView = getLView();
14290
+ const interpolatedValue = interpolation2(lView, prefix, v0, i0, v1, suffix);
14291
+ if (interpolatedValue !== NO_CHANGE) {
14292
+ const tNode = getSelectedTNode();
14293
+ elementAttributeInternal(tNode, lView, attrName, interpolatedValue, sanitizer, namespace);
14294
+ ngDevMode &&
14295
+ storePropertyBindingMetadata(getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - 2, prefix, i0, suffix);
14754
14296
  }
14297
+ return ɵɵattributeInterpolate2;
14755
14298
  }
14756
- /** Updates 2 bindings if changed, then returns whether either was updated. */
14757
- function bindingUpdated2(lView, bindingIndex, exp1, exp2) {
14758
- const different = bindingUpdated(lView, bindingIndex, exp1);
14759
- return bindingUpdated(lView, bindingIndex + 1, exp2) || different;
14760
- }
14761
- /** Updates 3 bindings if changed, then returns whether any was updated. */
14762
- function bindingUpdated3(lView, bindingIndex, exp1, exp2, exp3) {
14763
- const different = bindingUpdated2(lView, bindingIndex, exp1, exp2);
14764
- return bindingUpdated(lView, bindingIndex + 2, exp3) || different;
14765
- }
14766
- /** Updates 4 bindings if changed, then returns whether any was updated. */
14767
- function bindingUpdated4(lView, bindingIndex, exp1, exp2, exp3, exp4) {
14768
- const different = bindingUpdated2(lView, bindingIndex, exp1, exp2);
14769
- return bindingUpdated2(lView, bindingIndex + 2, exp3, exp4) || different;
14770
- }
14771
-
14772
14299
  /**
14773
- * @license
14774
- * Copyright Google LLC All Rights Reserved.
14775
14300
  *
14776
- * Use of this source code is governed by an MIT-style license that can be
14777
- * found in the LICENSE file at https://angular.io/license
14778
- */
14779
- /**
14780
- * Updates the value of or removes a bound attribute on an Element.
14301
+ * Update an interpolated attribute on an element with 3 bound values surrounded by text.
14781
14302
  *
14782
- * Used in the case of `[attr.title]="value"`
14303
+ * Used when the value passed to a property has 3 interpolated values in it:
14783
14304
  *
14784
- * @param name name The name of the attribute.
14785
- * @param value value The attribute is removed when value is `null` or `undefined`.
14786
- * Otherwise the attribute value is set to the stringified value.
14787
- * @param sanitizer An optional function used to sanitize the value.
14788
- * @param namespace Optional namespace to use when setting the attribute.
14305
+ * ```html
14306
+ * <div attr.title="prefix{{v0}}-{{v1}}-{{v2}}suffix"></div>
14307
+ * ```
14308
+ *
14309
+ * Its compiled representation is::
14310
+ *
14311
+ * ```ts
14312
+ * ɵɵattributeInterpolate3(
14313
+ * 'title', 'prefix', v0, '-', v1, '-', v2, 'suffix');
14314
+ * ```
14789
14315
  *
14316
+ * @param attrName The name of the attribute to update
14317
+ * @param prefix Static value used for concatenation only.
14318
+ * @param v0 Value checked for change.
14319
+ * @param i0 Static value used for concatenation only.
14320
+ * @param v1 Value checked for change.
14321
+ * @param i1 Static value used for concatenation only.
14322
+ * @param v2 Value checked for change.
14323
+ * @param suffix Static value used for concatenation only.
14324
+ * @param sanitizer An optional sanitizer function
14325
+ * @returns itself, so that it may be chained.
14790
14326
  * @codeGenApi
14791
14327
  */
14792
- function ɵɵattribute(name, value, sanitizer, namespace) {
14328
+ function ɵɵattributeInterpolate3(attrName, prefix, v0, i0, v1, i1, v2, suffix, sanitizer, namespace) {
14793
14329
  const lView = getLView();
14794
- const bindingIndex = nextBindingIndex();
14795
- if (bindingUpdated(lView, bindingIndex, value)) {
14796
- const tView = getTView();
14330
+ const interpolatedValue = interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix);
14331
+ if (interpolatedValue !== NO_CHANGE) {
14797
14332
  const tNode = getSelectedTNode();
14798
- elementAttributeInternal(tNode, lView, name, value, sanitizer, namespace);
14799
- ngDevMode && storePropertyBindingMetadata(tView.data, tNode, 'attr.' + name, bindingIndex);
14333
+ elementAttributeInternal(tNode, lView, attrName, interpolatedValue, sanitizer, namespace);
14334
+ ngDevMode &&
14335
+ storePropertyBindingMetadata(getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - 3, prefix, i0, i1, suffix);
14800
14336
  }
14801
- return ɵɵattribute;
14337
+ return ɵɵattributeInterpolate3;
14802
14338
  }
14803
-
14804
14339
  /**
14805
- * @license
14806
- * Copyright Google LLC All Rights Reserved.
14807
14340
  *
14808
- * Use of this source code is governed by an MIT-style license that can be
14809
- * found in the LICENSE file at https://angular.io/license
14810
- */
14811
- /**
14812
- * Create interpolation bindings with a variable number of expressions.
14341
+ * Update an interpolated attribute on an element with 4 bound values surrounded by text.
14813
14342
  *
14814
- * If there are 1 to 8 expressions `interpolation1()` to `interpolation8()` should be used instead.
14815
- * Those are faster because there is no need to create an array of expressions and iterate over it.
14343
+ * Used when the value passed to a property has 4 interpolated values in it:
14816
14344
  *
14817
- * `values`:
14818
- * - has static text at even indexes,
14819
- * - has evaluated expressions at odd indexes.
14820
- *
14821
- * Returns the concatenated string when any of the arguments changes, `NO_CHANGE` otherwise.
14822
- */
14823
- function interpolationV(lView, values) {
14824
- ngDevMode && assertLessThan(2, values.length, 'should have at least 3 values');
14825
- ngDevMode && assertEqual(values.length % 2, 1, 'should have an odd number of values');
14826
- let isBindingUpdated = false;
14827
- let bindingIndex = getBindingIndex();
14828
- for (let i = 1; i < values.length; i += 2) {
14829
- // Check if bindings (odd indexes) have changed
14830
- isBindingUpdated = bindingUpdated(lView, bindingIndex++, values[i]) || isBindingUpdated;
14831
- }
14832
- setBindingIndex(bindingIndex);
14833
- if (!isBindingUpdated) {
14834
- return NO_CHANGE;
14835
- }
14836
- // Build the updated content
14837
- let content = values[0];
14838
- for (let i = 1; i < values.length; i += 2) {
14839
- content += renderStringify(values[i]) + values[i + 1];
14840
- }
14841
- return content;
14842
- }
14843
- /**
14844
- * Creates an interpolation binding with 1 expression.
14845
- *
14846
- * @param prefix static value used for concatenation only.
14847
- * @param v0 value checked for change.
14848
- * @param suffix static value used for concatenation only.
14849
- */
14850
- function interpolation1(lView, prefix, v0, suffix) {
14851
- const different = bindingUpdated(lView, nextBindingIndex(), v0);
14852
- return different ? prefix + renderStringify(v0) + suffix : NO_CHANGE;
14853
- }
14854
- /**
14855
- * Creates an interpolation binding with 2 expressions.
14856
- */
14857
- function interpolation2(lView, prefix, v0, i0, v1, suffix) {
14858
- const bindingIndex = getBindingIndex();
14859
- const different = bindingUpdated2(lView, bindingIndex, v0, v1);
14860
- incrementBindingIndex(2);
14861
- return different ? prefix + renderStringify(v0) + i0 + renderStringify(v1) + suffix : NO_CHANGE;
14862
- }
14863
- /**
14864
- * Creates an interpolation binding with 3 expressions.
14865
- */
14866
- function interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix) {
14867
- const bindingIndex = getBindingIndex();
14868
- const different = bindingUpdated3(lView, bindingIndex, v0, v1, v2);
14869
- incrementBindingIndex(3);
14870
- return different ?
14871
- prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 + renderStringify(v2) + suffix :
14872
- NO_CHANGE;
14873
- }
14874
- /**
14875
- * Create an interpolation binding with 4 expressions.
14876
- */
14877
- function interpolation4(lView, prefix, v0, i0, v1, i1, v2, i2, v3, suffix) {
14878
- const bindingIndex = getBindingIndex();
14879
- const different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);
14880
- incrementBindingIndex(4);
14881
- return different ? prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 +
14882
- renderStringify(v2) + i2 + renderStringify(v3) + suffix :
14883
- NO_CHANGE;
14884
- }
14885
- /**
14886
- * Creates an interpolation binding with 5 expressions.
14887
- */
14888
- function interpolation5(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix) {
14889
- const bindingIndex = getBindingIndex();
14890
- let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);
14891
- different = bindingUpdated(lView, bindingIndex + 4, v4) || different;
14892
- incrementBindingIndex(5);
14893
- return different ? prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 +
14894
- renderStringify(v2) + i2 + renderStringify(v3) + i3 + renderStringify(v4) + suffix :
14895
- NO_CHANGE;
14896
- }
14897
- /**
14898
- * Creates an interpolation binding with 6 expressions.
14899
- */
14900
- function interpolation6(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix) {
14901
- const bindingIndex = getBindingIndex();
14902
- let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);
14903
- different = bindingUpdated2(lView, bindingIndex + 4, v4, v5) || different;
14904
- incrementBindingIndex(6);
14905
- return different ?
14906
- prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 + renderStringify(v2) + i2 +
14907
- renderStringify(v3) + i3 + renderStringify(v4) + i4 + renderStringify(v5) + suffix :
14908
- NO_CHANGE;
14909
- }
14910
- /**
14911
- * Creates an interpolation binding with 7 expressions.
14912
- */
14913
- function interpolation7(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix) {
14914
- const bindingIndex = getBindingIndex();
14915
- let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);
14916
- different = bindingUpdated3(lView, bindingIndex + 4, v4, v5, v6) || different;
14917
- incrementBindingIndex(7);
14918
- return different ? prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 +
14919
- renderStringify(v2) + i2 + renderStringify(v3) + i3 + renderStringify(v4) + i4 +
14920
- renderStringify(v5) + i5 + renderStringify(v6) + suffix :
14921
- NO_CHANGE;
14922
- }
14923
- /**
14924
- * Creates an interpolation binding with 8 expressions.
14925
- */
14926
- function interpolation8(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix) {
14927
- const bindingIndex = getBindingIndex();
14928
- let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);
14929
- different = bindingUpdated4(lView, bindingIndex + 4, v4, v5, v6, v7) || different;
14930
- incrementBindingIndex(8);
14931
- return different ? prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 +
14932
- renderStringify(v2) + i2 + renderStringify(v3) + i3 + renderStringify(v4) + i4 +
14933
- renderStringify(v5) + i5 + renderStringify(v6) + i6 + renderStringify(v7) + suffix :
14934
- NO_CHANGE;
14935
- }
14936
-
14937
- /**
14938
- *
14939
- * Update an interpolated attribute on an element with single bound value surrounded by text.
14940
- *
14941
- * Used when the value passed to a property has 1 interpolated value in it:
14942
- *
14943
- * ```html
14944
- * <div attr.title="prefix{{v0}}suffix"></div>
14945
- * ```
14946
- *
14947
- * Its compiled representation is::
14948
- *
14949
- * ```ts
14950
- * ɵɵattributeInterpolate1('title', 'prefix', v0, 'suffix');
14951
- * ```
14952
- *
14953
- * @param attrName The name of the attribute to update
14954
- * @param prefix Static value used for concatenation only.
14955
- * @param v0 Value checked for change.
14956
- * @param suffix Static value used for concatenation only.
14957
- * @param sanitizer An optional sanitizer function
14958
- * @returns itself, so that it may be chained.
14959
- * @codeGenApi
14960
- */
14961
- function ɵɵattributeInterpolate1(attrName, prefix, v0, suffix, sanitizer, namespace) {
14962
- const lView = getLView();
14963
- const interpolatedValue = interpolation1(lView, prefix, v0, suffix);
14964
- if (interpolatedValue !== NO_CHANGE) {
14965
- const tNode = getSelectedTNode();
14966
- elementAttributeInternal(tNode, lView, attrName, interpolatedValue, sanitizer, namespace);
14967
- ngDevMode &&
14968
- storePropertyBindingMetadata(getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - 1, prefix, suffix);
14969
- }
14970
- return ɵɵattributeInterpolate1;
14971
- }
14972
- /**
14973
- *
14974
- * Update an interpolated attribute on an element with 2 bound values surrounded by text.
14975
- *
14976
- * Used when the value passed to a property has 2 interpolated values in it:
14977
- *
14978
- * ```html
14979
- * <div attr.title="prefix{{v0}}-{{v1}}suffix"></div>
14980
- * ```
14981
- *
14982
- * Its compiled representation is::
14983
- *
14984
- * ```ts
14985
- * ɵɵattributeInterpolate2('title', 'prefix', v0, '-', v1, 'suffix');
14986
- * ```
14987
- *
14988
- * @param attrName The name of the attribute to update
14989
- * @param prefix Static value used for concatenation only.
14990
- * @param v0 Value checked for change.
14991
- * @param i0 Static value used for concatenation only.
14992
- * @param v1 Value checked for change.
14993
- * @param suffix Static value used for concatenation only.
14994
- * @param sanitizer An optional sanitizer function
14995
- * @returns itself, so that it may be chained.
14996
- * @codeGenApi
14997
- */
14998
- function ɵɵattributeInterpolate2(attrName, prefix, v0, i0, v1, suffix, sanitizer, namespace) {
14999
- const lView = getLView();
15000
- const interpolatedValue = interpolation2(lView, prefix, v0, i0, v1, suffix);
15001
- if (interpolatedValue !== NO_CHANGE) {
15002
- const tNode = getSelectedTNode();
15003
- elementAttributeInternal(tNode, lView, attrName, interpolatedValue, sanitizer, namespace);
15004
- ngDevMode &&
15005
- storePropertyBindingMetadata(getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - 2, prefix, i0, suffix);
15006
- }
15007
- return ɵɵattributeInterpolate2;
15008
- }
15009
- /**
15010
- *
15011
- * Update an interpolated attribute on an element with 3 bound values surrounded by text.
15012
- *
15013
- * Used when the value passed to a property has 3 interpolated values in it:
15014
- *
15015
- * ```html
15016
- * <div attr.title="prefix{{v0}}-{{v1}}-{{v2}}suffix"></div>
15017
- * ```
15018
- *
15019
- * Its compiled representation is::
15020
- *
15021
- * ```ts
15022
- * ɵɵattributeInterpolate3(
15023
- * 'title', 'prefix', v0, '-', v1, '-', v2, 'suffix');
15024
- * ```
15025
- *
15026
- * @param attrName The name of the attribute to update
15027
- * @param prefix Static value used for concatenation only.
15028
- * @param v0 Value checked for change.
15029
- * @param i0 Static value used for concatenation only.
15030
- * @param v1 Value checked for change.
15031
- * @param i1 Static value used for concatenation only.
15032
- * @param v2 Value checked for change.
15033
- * @param suffix Static value used for concatenation only.
15034
- * @param sanitizer An optional sanitizer function
15035
- * @returns itself, so that it may be chained.
15036
- * @codeGenApi
15037
- */
15038
- function ɵɵattributeInterpolate3(attrName, prefix, v0, i0, v1, i1, v2, suffix, sanitizer, namespace) {
15039
- const lView = getLView();
15040
- const interpolatedValue = interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix);
15041
- if (interpolatedValue !== NO_CHANGE) {
15042
- const tNode = getSelectedTNode();
15043
- elementAttributeInternal(tNode, lView, attrName, interpolatedValue, sanitizer, namespace);
15044
- ngDevMode &&
15045
- storePropertyBindingMetadata(getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - 3, prefix, i0, i1, suffix);
15046
- }
15047
- return ɵɵattributeInterpolate3;
15048
- }
15049
- /**
15050
- *
15051
- * Update an interpolated attribute on an element with 4 bound values surrounded by text.
15052
- *
15053
- * Used when the value passed to a property has 4 interpolated values in it:
15054
- *
15055
- * ```html
15056
- * <div attr.title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}suffix"></div>
15057
- * ```
14345
+ * ```html
14346
+ * <div attr.title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}suffix"></div>
14347
+ * ```
15058
14348
  *
15059
14349
  * Its compiled representation is::
15060
14350
  *
@@ -15326,30 +14616,81 @@ function ɵɵattributeInterpolateV(attrName, values, sanitizer, namespace) {
15326
14616
  * Use of this source code is governed by an MIT-style license that can be
15327
14617
  * found in the LICENSE file at https://angular.io/license
15328
14618
  */
15329
- function templateFirstCreatePass(index, tView, lView, templateFn, decls, vars, tagName, attrsIndex, localRefsIndex) {
15330
- ngDevMode && assertFirstCreatePass(tView);
15331
- ngDevMode && ngDevMode.firstCreatePass++;
15332
- const tViewConsts = tView.consts;
15333
- // TODO(pk): refactor getOrCreateTNode to have the "create" only version
15334
- const tNode = getOrCreateTNode(tView, index, 4 /* TNodeType.Container */, tagName || null, getConstant(tViewConsts, attrsIndex));
15335
- resolveDirectives(tView, lView, tNode, getConstant(tViewConsts, localRefsIndex));
15336
- registerPostOrderHooks(tView, tNode);
15337
- const embeddedTView = tNode.tViews = createTView(2 /* TViewType.Embedded */, tNode, templateFn, decls, vars, tView.directiveRegistry, tView.pipeRegistry, null, tView.schemas, tViewConsts);
15338
- if (tView.queries !== null) {
15339
- tView.queries.template(tView, tNode);
15340
- embeddedTView.queries = tView.queries.embeddedTView(tNode);
15341
- }
15342
- return tNode;
15343
- }
15344
14619
  /**
15345
- * Creates an LContainer for an ng-template (dynamically-inserted view), e.g.
14620
+ * Synchronously perform change detection on a component (and possibly its sub-components).
15346
14621
  *
15347
- * <ng-template #foo>
15348
- * <div></div>
15349
- * </ng-template>
14622
+ * This function triggers change detection in a synchronous way on a component.
15350
14623
  *
15351
- * @param index The index of the container in the data array
15352
- * @param templateFn Inline template
14624
+ * @param component The component which the change detection should be performed on.
14625
+ */
14626
+ function detectChanges(component) {
14627
+ const view = getComponentViewByInstance(component);
14628
+ detectChangesInternal(view[TVIEW], view, component);
14629
+ }
14630
+ /**
14631
+ * Marks the component as dirty (needing change detection). Marking a component dirty will
14632
+ * schedule a change detection on it at some point in the future.
14633
+ *
14634
+ * Marking an already dirty component as dirty won't do anything. Only one outstanding change
14635
+ * detection can be scheduled per component tree.
14636
+ *
14637
+ * @param component Component to mark as dirty.
14638
+ */
14639
+ function markDirty(component) {
14640
+ ngDevMode && assertDefined(component, 'component');
14641
+ const rootView = markViewDirty(getComponentViewByInstance(component));
14642
+ ngDevMode && assertDefined(rootView[CONTEXT], 'rootContext should be defined');
14643
+ scheduleTick(rootView[CONTEXT], 1 /* RootContextFlags.DetectChanges */);
14644
+ }
14645
+ /**
14646
+ * Used to perform change detection on the whole application.
14647
+ *
14648
+ * This is equivalent to `detectChanges`, but invoked on root component. Additionally, `tick`
14649
+ * executes lifecycle hooks and conditionally checks components based on their
14650
+ * `ChangeDetectionStrategy` and dirtiness.
14651
+ *
14652
+ * The preferred way to trigger change detection is to call `markDirty`. `markDirty` internally
14653
+ * schedules `tick` using a scheduler in order to coalesce multiple `markDirty` calls into a
14654
+ * single change detection run. By default, the scheduler is `requestAnimationFrame`, but can
14655
+ * be changed when calling `renderComponent` and providing the `scheduler` option.
14656
+ */
14657
+ function tick(component) {
14658
+ const rootView = getRootView(component);
14659
+ const rootContext = rootView[CONTEXT];
14660
+ tickRootContext(rootContext);
14661
+ }
14662
+
14663
+ /**
14664
+ * @license
14665
+ * Copyright Google LLC All Rights Reserved.
14666
+ *
14667
+ * Use of this source code is governed by an MIT-style license that can be
14668
+ * found in the LICENSE file at https://angular.io/license
14669
+ */
14670
+ function templateFirstCreatePass(index, tView, lView, templateFn, decls, vars, tagName, attrsIndex, localRefsIndex) {
14671
+ ngDevMode && assertFirstCreatePass(tView);
14672
+ ngDevMode && ngDevMode.firstCreatePass++;
14673
+ const tViewConsts = tView.consts;
14674
+ // TODO(pk): refactor getOrCreateTNode to have the "create" only version
14675
+ const tNode = getOrCreateTNode(tView, index, 4 /* TNodeType.Container */, tagName || null, getConstant(tViewConsts, attrsIndex));
14676
+ resolveDirectives(tView, lView, tNode, getConstant(tViewConsts, localRefsIndex));
14677
+ registerPostOrderHooks(tView, tNode);
14678
+ const embeddedTView = tNode.tViews = createTView(2 /* TViewType.Embedded */, tNode, templateFn, decls, vars, tView.directiveRegistry, tView.pipeRegistry, null, tView.schemas, tViewConsts);
14679
+ if (tView.queries !== null) {
14680
+ tView.queries.template(tView, tNode);
14681
+ embeddedTView.queries = tView.queries.embeddedTView(tNode);
14682
+ }
14683
+ return tNode;
14684
+ }
14685
+ /**
14686
+ * Creates an LContainer for an ng-template (dynamically-inserted view), e.g.
14687
+ *
14688
+ * <ng-template #foo>
14689
+ * <div></div>
14690
+ * </ng-template>
14691
+ *
14692
+ * @param index The index of the container in the data array
14693
+ * @param templateFn Inline template
15353
14694
  * @param decls The number of nodes, local refs, and pipes for this template
15354
14695
  * @param vars The number of bindings for this template
15355
14696
  * @param tagName The name of the container element, if applicable
@@ -15863,51 +15204,42 @@ function listenerInternal(tView, lView, renderer, tNode, eventName, listenerFn,
15863
15204
  tNode.index;
15864
15205
  // In order to match current behavior, native DOM event listeners must be added for all
15865
15206
  // events (including outputs).
15866
- if (isProceduralRenderer(renderer)) {
15867
- // There might be cases where multiple directives on the same element try to register an event
15868
- // handler function for the same event. In this situation we want to avoid registration of
15869
- // several native listeners as each registration would be intercepted by NgZone and
15870
- // trigger change detection. This would mean that a single user action would result in several
15871
- // change detections being invoked. To avoid this situation we want to have only one call to
15872
- // native handler registration (for the same element and same type of event).
15873
- //
15874
- // In order to have just one native event handler in presence of multiple handler functions,
15875
- // we just register a first handler function as a native event listener and then chain
15876
- // (coalesce) other handler functions on top of the first native handler function.
15877
- let existingListener = null;
15878
- // Please note that the coalescing described here doesn't happen for events specifying an
15879
- // alternative target (ex. (document:click)) - this is to keep backward compatibility with the
15880
- // view engine.
15881
- // Also, we don't have to search for existing listeners is there are no directives
15882
- // matching on a given node as we can't register multiple event handlers for the same event in
15883
- // a template (this would mean having duplicate attributes).
15884
- if (!eventTargetResolver && isTNodeDirectiveHost) {
15885
- existingListener = findExistingListener(tView, lView, eventName, tNode.index);
15886
- }
15887
- if (existingListener !== null) {
15888
- // Attach a new listener to coalesced listeners list, maintaining the order in which
15889
- // listeners are registered. For performance reasons, we keep a reference to the last
15890
- // listener in that list (in `__ngLastListenerFn__` field), so we can avoid going through
15891
- // the entire set each time we need to add a new listener.
15892
- const lastListenerFn = existingListener.__ngLastListenerFn__ || existingListener;
15893
- lastListenerFn.__ngNextListenerFn__ = listenerFn;
15894
- existingListener.__ngLastListenerFn__ = listenerFn;
15895
- processOutputs = false;
15896
- }
15897
- else {
15898
- listenerFn = wrapListener(tNode, lView, context, listenerFn, false /** preventDefault */);
15899
- const cleanupFn = renderer.listen(target, eventName, listenerFn);
15900
- ngDevMode && ngDevMode.rendererAddEventListener++;
15901
- lCleanup.push(listenerFn, cleanupFn);
15902
- tCleanup && tCleanup.push(eventName, idxOrTargetGetter, lCleanupIndex, lCleanupIndex + 1);
15903
- }
15207
+ // There might be cases where multiple directives on the same element try to register an event
15208
+ // handler function for the same event. In this situation we want to avoid registration of
15209
+ // several native listeners as each registration would be intercepted by NgZone and
15210
+ // trigger change detection. This would mean that a single user action would result in several
15211
+ // change detections being invoked. To avoid this situation we want to have only one call to
15212
+ // native handler registration (for the same element and same type of event).
15213
+ //
15214
+ // In order to have just one native event handler in presence of multiple handler functions,
15215
+ // we just register a first handler function as a native event listener and then chain
15216
+ // (coalesce) other handler functions on top of the first native handler function.
15217
+ let existingListener = null;
15218
+ // Please note that the coalescing described here doesn't happen for events specifying an
15219
+ // alternative target (ex. (document:click)) - this is to keep backward compatibility with the
15220
+ // view engine.
15221
+ // Also, we don't have to search for existing listeners is there are no directives
15222
+ // matching on a given node as we can't register multiple event handlers for the same event in
15223
+ // a template (this would mean having duplicate attributes).
15224
+ if (!eventTargetResolver && isTNodeDirectiveHost) {
15225
+ existingListener = findExistingListener(tView, lView, eventName, tNode.index);
15226
+ }
15227
+ if (existingListener !== null) {
15228
+ // Attach a new listener to coalesced listeners list, maintaining the order in which
15229
+ // listeners are registered. For performance reasons, we keep a reference to the last
15230
+ // listener in that list (in `__ngLastListenerFn__` field), so we can avoid going through
15231
+ // the entire set each time we need to add a new listener.
15232
+ const lastListenerFn = existingListener.__ngLastListenerFn__ || existingListener;
15233
+ lastListenerFn.__ngNextListenerFn__ = listenerFn;
15234
+ existingListener.__ngLastListenerFn__ = listenerFn;
15235
+ processOutputs = false;
15904
15236
  }
15905
15237
  else {
15906
- listenerFn = wrapListener(tNode, lView, context, listenerFn, true /** preventDefault */);
15907
- target.addEventListener(eventName, listenerFn, useCapture);
15238
+ listenerFn = wrapListener(tNode, lView, context, listenerFn, false /** preventDefault */);
15239
+ const cleanupFn = renderer.listen(target, eventName, listenerFn);
15908
15240
  ngDevMode && ngDevMode.rendererAddEventListener++;
15909
- lCleanup.push(listenerFn);
15910
- tCleanup && tCleanup.push(eventName, idxOrTargetGetter, lCleanupIndex, useCapture);
15241
+ lCleanup.push(listenerFn, cleanupFn);
15242
+ tCleanup && tCleanup.push(eventName, idxOrTargetGetter, lCleanupIndex, lCleanupIndex + 1);
15911
15243
  }
15912
15244
  }
15913
15245
  else {
@@ -17981,7 +17313,7 @@ function findStylingValue(tData, tNode, lView, prop, index, isClassBased) {
17981
17313
  valueAtLViewIndex = isStylingMap ? EMPTY_ARRAY : undefined;
17982
17314
  }
17983
17315
  let currentValue = isStylingMap ? keyValueArrayGet(valueAtLViewIndex, prop) :
17984
- key === prop ? valueAtLViewIndex : undefined;
17316
+ (key === prop ? valueAtLViewIndex : undefined);
17985
17317
  if (containsStatics && !isStylingValuePresent(currentValue)) {
17986
17318
  currentValue = keyValueArrayGet(rawKey, prop);
17987
17319
  }
@@ -21834,7 +21166,7 @@ function noComponentFactoryError(component) {
21834
21166
  return error;
21835
21167
  }
21836
21168
  const ERROR_COMPONENT = 'ngComponent';
21837
- function getComponent(error) {
21169
+ function getComponent$1(error) {
21838
21170
  return error[ERROR_COMPONENT];
21839
21171
  }
21840
21172
  class _NullComponentFactoryResolver {
@@ -22018,14 +21350,6 @@ class Renderer2 {
22018
21350
  * @nocollapse
22019
21351
  */
22020
21352
  Renderer2.__NG_ELEMENT_ID__ = () => injectRenderer2();
22021
- /** Returns a Renderer2 (or throws when application was bootstrapped with Renderer3) */
22022
- function getOrCreateRenderer2(lView) {
22023
- const renderer = lView[RENDERER];
22024
- if (ngDevMode && !isProceduralRenderer(renderer)) {
22025
- throw new Error('Cannot inject Renderer2 when the application uses Renderer3!');
22026
- }
22027
- return renderer;
22028
- }
22029
21353
  /** Injects a Renderer2 for the current component. */
22030
21354
  function injectRenderer2() {
22031
21355
  // We need the Renderer to be based on the component that it's being injected into, however since
@@ -22033,7 +21357,7 @@ function injectRenderer2() {
22033
21357
  const lView = getLView();
22034
21358
  const tNode = getCurrentTNode();
22035
21359
  const nodeAtIndex = getComponentLViewByIndex(tNode.index, lView);
22036
- return getOrCreateRenderer2(isLView(nodeAtIndex) ? nodeAtIndex : lView);
21360
+ return (isLView(nodeAtIndex) ? nodeAtIndex : lView)[RENDERER];
22037
21361
  }
22038
21362
 
22039
21363
  /**
@@ -22080,7 +21404,7 @@ class Version {
22080
21404
  /**
22081
21405
  * @publicApi
22082
21406
  */
22083
- const VERSION = new Version('14.1.0-next.3');
21407
+ const VERSION = new Version('14.1.0-next.4');
22084
21408
 
22085
21409
  /**
22086
21410
  * @license
@@ -22544,7 +21868,13 @@ class ComponentFactory extends ComponentFactory$1 {
22544
21868
  realEnvironmentInjector;
22545
21869
  }
22546
21870
  const rootViewInjector = realEnvironmentInjector ? new ChainedInjector(injector, realEnvironmentInjector) : injector;
22547
- const rendererFactory = rootViewInjector.get(RendererFactory2, domRendererFactory3);
21871
+ const rendererFactory = rootViewInjector.get(RendererFactory2, null);
21872
+ if (rendererFactory === null) {
21873
+ throw new RuntimeError(407 /* RuntimeErrorCode.RENDERER_NOT_FOUND */, ngDevMode &&
21874
+ 'Angular was not able to inject a renderer (RendererFactory2). ' +
21875
+ 'Likely this is due to a broken DI hierarchy. ' +
21876
+ 'Make sure that any injector used to create this component has a correct parent.');
21877
+ }
22548
21878
  const sanitizer = rootViewInjector.get(Sanitizer, null);
22549
21879
  const hostRenderer = rendererFactory.createRenderer(null, this.componentDef);
22550
21880
  // Determine a tag name used for creating host elements when this component is created
@@ -22640,6 +21970,23 @@ class ComponentRef extends ComponentRef$1 {
22640
21970
  this.hostView = this.changeDetectorRef = new RootViewRef(_rootLView);
22641
21971
  this.componentType = componentType;
22642
21972
  }
21973
+ setInput(name, value) {
21974
+ const inputData = this._tNode.inputs;
21975
+ let dataValue;
21976
+ if (inputData !== null && (dataValue = inputData[name])) {
21977
+ const lView = this._rootLView;
21978
+ setInputsForProperty(lView[TVIEW], lView, dataValue, name, value);
21979
+ markDirtyIfOnPush(lView, this._tNode.index);
21980
+ }
21981
+ else {
21982
+ if (ngDevMode) {
21983
+ const cmpNameForError = stringifyForError(this.componentType);
21984
+ let message = `Can't set value of the '${name}' input on the '${cmpNameForError}' component. `;
21985
+ message += `Make sure that the '${name}' property is annotated with @Input() or a mapped @Input('${name}') exists.`;
21986
+ reportUnknownPropertyError(message);
21987
+ }
21988
+ }
21989
+ }
22643
21990
  get injector() {
22644
21991
  return new NodeInjector(this._tNode, this._rootLView);
22645
21992
  }
@@ -22705,6 +22052,9 @@ class NgModuleRef extends NgModuleRef$1 {
22705
22052
  }
22706
22053
  return this._r3Injector.get(token, notFoundValue, injectFlags);
22707
22054
  }
22055
+ runInContext(fn) {
22056
+ return this.injector.runInContext(fn);
22057
+ }
22708
22058
  destroy() {
22709
22059
  ngDevMode && assertDefined(this.destroyCbs, 'NgModule already destroyed');
22710
22060
  const injector = this._r3Injector;
@@ -22716,118 +22066,528 @@ class NgModuleRef extends NgModuleRef$1 {
22716
22066
  ngDevMode && assertDefined(this.destroyCbs, 'NgModule already destroyed');
22717
22067
  this.destroyCbs.push(callback);
22718
22068
  }
22719
- }
22720
- class NgModuleFactory extends NgModuleFactory$1 {
22721
- constructor(moduleType) {
22722
- super();
22723
- this.moduleType = moduleType;
22069
+ }
22070
+ class NgModuleFactory extends NgModuleFactory$1 {
22071
+ constructor(moduleType) {
22072
+ super();
22073
+ this.moduleType = moduleType;
22074
+ }
22075
+ create(parentInjector) {
22076
+ return new NgModuleRef(this.moduleType, parentInjector);
22077
+ }
22078
+ }
22079
+ class EnvironmentNgModuleRefAdapter extends NgModuleRef$1 {
22080
+ constructor(providers, parent, source) {
22081
+ super();
22082
+ this.componentFactoryResolver = new ComponentFactoryResolver(this);
22083
+ this.instance = null;
22084
+ const injector = new R3Injector([
22085
+ ...providers,
22086
+ { provide: NgModuleRef$1, useValue: this },
22087
+ { provide: ComponentFactoryResolver$1, useValue: this.componentFactoryResolver },
22088
+ ], parent || getNullInjector(), source, new Set(['environment']));
22089
+ this.injector = injector;
22090
+ injector.resolveInjectorInitializers();
22091
+ }
22092
+ destroy() {
22093
+ this.injector.destroy();
22094
+ }
22095
+ onDestroy(callback) {
22096
+ this.injector.onDestroy(callback);
22097
+ }
22098
+ }
22099
+ /**
22100
+ * Create a new environment injector.
22101
+ *
22102
+ * Learn more about environment injectors in
22103
+ * [this guide](guide/standalone-components#environment-injectors).
22104
+ *
22105
+ * @param providers An array of providers.
22106
+ * @param parent A parent environment injector.
22107
+ * @param debugName An optional name for this injector instance, which will be used in error
22108
+ * messages.
22109
+ *
22110
+ * @publicApi
22111
+ * @developerPreview
22112
+ */
22113
+ function createEnvironmentInjector(providers, parent, debugName = null) {
22114
+ const adapter = new EnvironmentNgModuleRefAdapter(providers, parent, debugName);
22115
+ return adapter.injector;
22116
+ }
22117
+
22118
+ /**
22119
+ * @license
22120
+ * Copyright Google LLC All Rights Reserved.
22121
+ *
22122
+ * Use of this source code is governed by an MIT-style license that can be
22123
+ * found in the LICENSE file at https://angular.io/license
22124
+ */
22125
+ /**
22126
+ * A service used by the framework to create instances of standalone injectors. Those injectors are
22127
+ * created on demand in case of dynamic component instantiation and contain ambient providers
22128
+ * collected from the imports graph rooted at a given standalone component.
22129
+ */
22130
+ class StandaloneService {
22131
+ constructor(_injector) {
22132
+ this._injector = _injector;
22133
+ this.cachedInjectors = new Map();
22134
+ }
22135
+ getOrCreateStandaloneInjector(componentDef) {
22136
+ if (!componentDef.standalone) {
22137
+ return null;
22138
+ }
22139
+ if (!this.cachedInjectors.has(componentDef.id)) {
22140
+ const providers = internalImportProvidersFrom(false, componentDef.type);
22141
+ const standaloneInjector = providers.length > 0 ?
22142
+ createEnvironmentInjector([providers], this._injector, `Standalone[${componentDef.type.name}]`) :
22143
+ null;
22144
+ this.cachedInjectors.set(componentDef.id, standaloneInjector);
22145
+ }
22146
+ return this.cachedInjectors.get(componentDef.id);
22147
+ }
22148
+ ngOnDestroy() {
22149
+ try {
22150
+ for (const injector of this.cachedInjectors.values()) {
22151
+ if (injector !== null) {
22152
+ injector.destroy();
22153
+ }
22154
+ }
22155
+ }
22156
+ finally {
22157
+ this.cachedInjectors.clear();
22158
+ }
22159
+ }
22160
+ }
22161
+ /** @nocollapse */
22162
+ StandaloneService.ɵprov = ɵɵdefineInjectable({
22163
+ token: StandaloneService,
22164
+ providedIn: 'environment',
22165
+ factory: () => new StandaloneService(ɵɵinject(EnvironmentInjector)),
22166
+ });
22167
+ /**
22168
+ * A feature that acts as a setup code for the {@link StandaloneService}.
22169
+ *
22170
+ * The most important responsaibility of this feature is to expose the "getStandaloneInjector"
22171
+ * function (an entry points to a standalone injector creation) on a component definition object. We
22172
+ * go through the features infrastructure to make sure that the standalone injector creation logic
22173
+ * is tree-shakable and not included in applications that don't use standalone components.
22174
+ *
22175
+ * @codeGenApi
22176
+ */
22177
+ function ɵɵStandaloneFeature(definition) {
22178
+ definition.getStandaloneInjector = (parentInjector) => {
22179
+ return parentInjector.get(StandaloneService).getOrCreateStandaloneInjector(definition);
22180
+ };
22181
+ }
22182
+
22183
+ /**
22184
+ * @license
22185
+ * Copyright Google LLC All Rights Reserved.
22186
+ *
22187
+ * Use of this source code is governed by an MIT-style license that can be
22188
+ * found in the LICENSE file at https://angular.io/license
22189
+ */
22190
+ /**
22191
+ * Retrieves the component instance associated with a given DOM element.
22192
+ *
22193
+ * @usageNotes
22194
+ * Given the following DOM structure:
22195
+ *
22196
+ * ```html
22197
+ * <app-root>
22198
+ * <div>
22199
+ * <child-comp></child-comp>
22200
+ * </div>
22201
+ * </app-root>
22202
+ * ```
22203
+ *
22204
+ * Calling `getComponent` on `<child-comp>` will return the instance of `ChildComponent`
22205
+ * associated with this DOM element.
22206
+ *
22207
+ * Calling the function on `<app-root>` will return the `MyApp` instance.
22208
+ *
22209
+ *
22210
+ * @param element DOM element from which the component should be retrieved.
22211
+ * @returns Component instance associated with the element or `null` if there
22212
+ * is no component associated with it.
22213
+ *
22214
+ * @publicApi
22215
+ * @globalApi ng
22216
+ */
22217
+ function getComponent(element) {
22218
+ ngDevMode && assertDomElement(element);
22219
+ const context = getLContext(element);
22220
+ if (context === null)
22221
+ return null;
22222
+ if (context.component === undefined) {
22223
+ const lView = context.lView;
22224
+ if (lView === null) {
22225
+ return null;
22226
+ }
22227
+ context.component = getComponentAtNodeIndex(context.nodeIndex, lView);
22228
+ }
22229
+ return context.component;
22230
+ }
22231
+ /**
22232
+ * If inside an embedded view (e.g. `*ngIf` or `*ngFor`), retrieves the context of the embedded
22233
+ * view that the element is part of. Otherwise retrieves the instance of the component whose view
22234
+ * owns the element (in this case, the result is the same as calling `getOwningComponent`).
22235
+ *
22236
+ * @param element Element for which to get the surrounding component instance.
22237
+ * @returns Instance of the component that is around the element or null if the element isn't
22238
+ * inside any component.
22239
+ *
22240
+ * @publicApi
22241
+ * @globalApi ng
22242
+ */
22243
+ function getContext(element) {
22244
+ assertDomElement(element);
22245
+ const context = getLContext(element);
22246
+ const lView = context ? context.lView : null;
22247
+ return lView === null ? null : lView[CONTEXT];
22248
+ }
22249
+ /**
22250
+ * Retrieves the component instance whose view contains the DOM element.
22251
+ *
22252
+ * For example, if `<child-comp>` is used in the template of `<app-comp>`
22253
+ * (i.e. a `ViewChild` of `<app-comp>`), calling `getOwningComponent` on `<child-comp>`
22254
+ * would return `<app-comp>`.
22255
+ *
22256
+ * @param elementOrDir DOM element, component or directive instance
22257
+ * for which to retrieve the root components.
22258
+ * @returns Component instance whose view owns the DOM element or null if the element is not
22259
+ * part of a component view.
22260
+ *
22261
+ * @publicApi
22262
+ * @globalApi ng
22263
+ */
22264
+ function getOwningComponent(elementOrDir) {
22265
+ const context = getLContext(elementOrDir);
22266
+ let lView = context ? context.lView : null;
22267
+ if (lView === null)
22268
+ return null;
22269
+ let parent;
22270
+ while (lView[TVIEW].type === 2 /* TViewType.Embedded */ && (parent = getLViewParent(lView))) {
22271
+ lView = parent;
22272
+ }
22273
+ return lView[FLAGS] & 256 /* LViewFlags.IsRoot */ ? null : lView[CONTEXT];
22274
+ }
22275
+ /**
22276
+ * Retrieves all root components associated with a DOM element, directive or component instance.
22277
+ * Root components are those which have been bootstrapped by Angular.
22278
+ *
22279
+ * @param elementOrDir DOM element, component or directive instance
22280
+ * for which to retrieve the root components.
22281
+ * @returns Root components associated with the target object.
22282
+ *
22283
+ * @publicApi
22284
+ * @globalApi ng
22285
+ */
22286
+ function getRootComponents(elementOrDir) {
22287
+ const lView = readPatchedLView(elementOrDir);
22288
+ return lView !== null ? [...getRootContext(lView).components] : [];
22289
+ }
22290
+ /**
22291
+ * Retrieves an `Injector` associated with an element, component or directive instance.
22292
+ *
22293
+ * @param elementOrDir DOM element, component or directive instance for which to
22294
+ * retrieve the injector.
22295
+ * @returns Injector associated with the element, component or directive instance.
22296
+ *
22297
+ * @publicApi
22298
+ * @globalApi ng
22299
+ */
22300
+ function getInjector(elementOrDir) {
22301
+ const context = getLContext(elementOrDir);
22302
+ const lView = context ? context.lView : null;
22303
+ if (lView === null)
22304
+ return Injector.NULL;
22305
+ const tNode = lView[TVIEW].data[context.nodeIndex];
22306
+ return new NodeInjector(tNode, lView);
22307
+ }
22308
+ /**
22309
+ * Retrieve a set of injection tokens at a given DOM node.
22310
+ *
22311
+ * @param element Element for which the injection tokens should be retrieved.
22312
+ */
22313
+ function getInjectionTokens(element) {
22314
+ const context = getLContext(element);
22315
+ const lView = context ? context.lView : null;
22316
+ if (lView === null)
22317
+ return [];
22318
+ const tView = lView[TVIEW];
22319
+ const tNode = tView.data[context.nodeIndex];
22320
+ const providerTokens = [];
22321
+ const startIndex = tNode.providerIndexes & 1048575 /* TNodeProviderIndexes.ProvidersStartIndexMask */;
22322
+ const endIndex = tNode.directiveEnd;
22323
+ for (let i = startIndex; i < endIndex; i++) {
22324
+ let value = tView.data[i];
22325
+ if (isDirectiveDefHack(value)) {
22326
+ // The fact that we sometimes store Type and sometimes DirectiveDef in this location is a
22327
+ // design flaw. We should always store same type so that we can be monomorphic. The issue
22328
+ // is that for Components/Directives we store the def instead the type. The correct behavior
22329
+ // is that we should always be storing injectable type in this location.
22330
+ value = value.type;
22331
+ }
22332
+ providerTokens.push(value);
22333
+ }
22334
+ return providerTokens;
22335
+ }
22336
+ /**
22337
+ * Retrieves directive instances associated with a given DOM node. Does not include
22338
+ * component instances.
22339
+ *
22340
+ * @usageNotes
22341
+ * Given the following DOM structure:
22342
+ *
22343
+ * ```html
22344
+ * <app-root>
22345
+ * <button my-button></button>
22346
+ * <my-comp></my-comp>
22347
+ * </app-root>
22348
+ * ```
22349
+ *
22350
+ * Calling `getDirectives` on `<button>` will return an array with an instance of the `MyButton`
22351
+ * directive that is associated with the DOM node.
22352
+ *
22353
+ * Calling `getDirectives` on `<my-comp>` will return an empty array.
22354
+ *
22355
+ * @param node DOM node for which to get the directives.
22356
+ * @returns Array of directives associated with the node.
22357
+ *
22358
+ * @publicApi
22359
+ * @globalApi ng
22360
+ */
22361
+ function getDirectives(node) {
22362
+ // Skip text nodes because we can't have directives associated with them.
22363
+ if (node instanceof Text) {
22364
+ return [];
22365
+ }
22366
+ const context = getLContext(node);
22367
+ const lView = context ? context.lView : null;
22368
+ if (lView === null) {
22369
+ return [];
22370
+ }
22371
+ const tView = lView[TVIEW];
22372
+ const nodeIndex = context.nodeIndex;
22373
+ if (!(tView === null || tView === void 0 ? void 0 : tView.data[nodeIndex])) {
22374
+ return [];
22375
+ }
22376
+ if (context.directives === undefined) {
22377
+ context.directives = getDirectivesAtNodeIndex(nodeIndex, lView, false);
22378
+ }
22379
+ // The `directives` in this case are a named array called `LComponentView`. Clone the
22380
+ // result so we don't expose an internal data structure in the user's console.
22381
+ return context.directives === null ? [] : [...context.directives];
22382
+ }
22383
+ /**
22384
+ * Returns the debug (partial) metadata for a particular directive or component instance.
22385
+ * The function accepts an instance of a directive or component and returns the corresponding
22386
+ * metadata.
22387
+ *
22388
+ * @param directiveOrComponentInstance Instance of a directive or component
22389
+ * @returns metadata of the passed directive or component
22390
+ *
22391
+ * @publicApi
22392
+ * @globalApi ng
22393
+ */
22394
+ function getDirectiveMetadata(directiveOrComponentInstance) {
22395
+ const { constructor } = directiveOrComponentInstance;
22396
+ if (!constructor) {
22397
+ throw new Error('Unable to find the instance constructor');
22398
+ }
22399
+ // In case a component inherits from a directive, we may have component and directive metadata
22400
+ // To ensure we don't get the metadata of the directive, we want to call `getComponentDef` first.
22401
+ const componentDef = getComponentDef$1(constructor);
22402
+ if (componentDef) {
22403
+ return {
22404
+ inputs: componentDef.inputs,
22405
+ outputs: componentDef.outputs,
22406
+ encapsulation: componentDef.encapsulation,
22407
+ changeDetection: componentDef.onPush ? ChangeDetectionStrategy.OnPush :
22408
+ ChangeDetectionStrategy.Default
22409
+ };
22724
22410
  }
22725
- create(parentInjector) {
22726
- return new NgModuleRef(this.moduleType, parentInjector);
22411
+ const directiveDef = getDirectiveDef(constructor);
22412
+ if (directiveDef) {
22413
+ return { inputs: directiveDef.inputs, outputs: directiveDef.outputs };
22727
22414
  }
22415
+ return null;
22728
22416
  }
22729
- class EnvironmentNgModuleRefAdapter extends NgModuleRef$1 {
22730
- constructor(providers, parent, source) {
22731
- super();
22732
- this.componentFactoryResolver = new ComponentFactoryResolver(this);
22733
- this.instance = null;
22734
- const injector = new R3Injector([
22735
- ...providers,
22736
- { provide: NgModuleRef$1, useValue: this },
22737
- { provide: ComponentFactoryResolver$1, useValue: this.componentFactoryResolver },
22738
- ], parent || getNullInjector(), source, new Set(['environment']));
22739
- this.injector = injector;
22740
- injector.resolveInjectorInitializers();
22741
- }
22742
- destroy() {
22743
- this.injector.destroy();
22744
- }
22745
- onDestroy(callback) {
22746
- this.injector.onDestroy(callback);
22417
+ /**
22418
+ * Retrieve map of local references.
22419
+ *
22420
+ * The references are retrieved as a map of local reference name to element or directive instance.
22421
+ *
22422
+ * @param target DOM element, component or directive instance for which to retrieve
22423
+ * the local references.
22424
+ */
22425
+ function getLocalRefs(target) {
22426
+ const context = getLContext(target);
22427
+ if (context === null)
22428
+ return {};
22429
+ if (context.localRefs === undefined) {
22430
+ const lView = context.lView;
22431
+ if (lView === null) {
22432
+ return {};
22433
+ }
22434
+ context.localRefs = discoverLocalRefs(lView, context.nodeIndex);
22747
22435
  }
22436
+ return context.localRefs || {};
22748
22437
  }
22749
22438
  /**
22750
- * Create a new environment injector.
22751
- *
22752
- * Learn more about environment injectors in
22753
- * [this guide](guide/standalone-components#environment-injectors).
22439
+ * Retrieves the host element of a component or directive instance.
22440
+ * The host element is the DOM element that matched the selector of the directive.
22754
22441
  *
22755
- * @param providers An array of providers.
22756
- * @param parent A parent environment injector.
22757
- * @param debugName An optional name for this injector instance, which will be used in error
22758
- * messages.
22442
+ * @param componentOrDirective Component or directive instance for which the host
22443
+ * element should be retrieved.
22444
+ * @returns Host element of the target.
22759
22445
  *
22760
22446
  * @publicApi
22761
- * @developerPreview
22447
+ * @globalApi ng
22762
22448
  */
22763
- function createEnvironmentInjector(providers, parent, debugName = null) {
22764
- const adapter = new EnvironmentNgModuleRefAdapter(providers, parent, debugName);
22765
- return adapter.injector;
22449
+ function getHostElement(componentOrDirective) {
22450
+ return getLContext(componentOrDirective).native;
22766
22451
  }
22767
-
22768
22452
  /**
22769
- * @license
22770
- * Copyright Google LLC All Rights Reserved.
22453
+ * Retrieves the rendered text for a given component.
22771
22454
  *
22772
- * Use of this source code is governed by an MIT-style license that can be
22773
- * found in the LICENSE file at https://angular.io/license
22455
+ * This function retrieves the host element of a component and
22456
+ * and then returns the `textContent` for that element. This implies
22457
+ * that the text returned will include re-projected content of
22458
+ * the component as well.
22459
+ *
22460
+ * @param component The component to return the content text for.
22774
22461
  */
22462
+ function getRenderedText(component) {
22463
+ const hostElement = getHostElement(component);
22464
+ return hostElement.textContent || '';
22465
+ }
22775
22466
  /**
22776
- * A service used by the framework to create instances of standalone injectors. Those injectors are
22777
- * created on demand in case of dynamic component instantiation and contain ambient providers
22778
- * collected from the imports graph rooted at a given standalone component.
22467
+ * Retrieves a list of event listeners associated with a DOM element. The list does include host
22468
+ * listeners, but it does not include event listeners defined outside of the Angular context
22469
+ * (e.g. through `addEventListener`).
22470
+ *
22471
+ * @usageNotes
22472
+ * Given the following DOM structure:
22473
+ *
22474
+ * ```html
22475
+ * <app-root>
22476
+ * <div (click)="doSomething()"></div>
22477
+ * </app-root>
22478
+ * ```
22479
+ *
22480
+ * Calling `getListeners` on `<div>` will return an object that looks as follows:
22481
+ *
22482
+ * ```ts
22483
+ * {
22484
+ * name: 'click',
22485
+ * element: <div>,
22486
+ * callback: () => doSomething(),
22487
+ * useCapture: false
22488
+ * }
22489
+ * ```
22490
+ *
22491
+ * @param element Element for which the DOM listeners should be retrieved.
22492
+ * @returns Array of event listeners on the DOM element.
22493
+ *
22494
+ * @publicApi
22495
+ * @globalApi ng
22779
22496
  */
22780
- class StandaloneService {
22781
- constructor(_injector) {
22782
- this._injector = _injector;
22783
- this.cachedInjectors = new Map();
22784
- }
22785
- getOrCreateStandaloneInjector(componentDef) {
22786
- if (!componentDef.standalone) {
22787
- return null;
22788
- }
22789
- if (!this.cachedInjectors.has(componentDef.id)) {
22790
- const providers = internalImportProvidersFrom(false, componentDef.type);
22791
- const standaloneInjector = providers.length > 0 ?
22792
- createEnvironmentInjector([providers], this._injector, `Standalone[${componentDef.type.name}]`) :
22793
- null;
22794
- this.cachedInjectors.set(componentDef.id, standaloneInjector);
22795
- }
22796
- return this.cachedInjectors.get(componentDef.id);
22797
- }
22798
- ngOnDestroy() {
22799
- try {
22800
- for (const injector of this.cachedInjectors.values()) {
22801
- if (injector !== null) {
22802
- injector.destroy();
22497
+ function getListeners(element) {
22498
+ ngDevMode && assertDomElement(element);
22499
+ const lContext = getLContext(element);
22500
+ const lView = lContext === null ? null : lContext.lView;
22501
+ if (lView === null)
22502
+ return [];
22503
+ const tView = lView[TVIEW];
22504
+ const lCleanup = lView[CLEANUP];
22505
+ const tCleanup = tView.cleanup;
22506
+ const listeners = [];
22507
+ if (tCleanup && lCleanup) {
22508
+ for (let i = 0; i < tCleanup.length;) {
22509
+ const firstParam = tCleanup[i++];
22510
+ const secondParam = tCleanup[i++];
22511
+ if (typeof firstParam === 'string') {
22512
+ const name = firstParam;
22513
+ const listenerElement = unwrapRNode(lView[secondParam]);
22514
+ const callback = lCleanup[tCleanup[i++]];
22515
+ const useCaptureOrIndx = tCleanup[i++];
22516
+ // if useCaptureOrIndx is boolean then report it as is.
22517
+ // if useCaptureOrIndx is positive number then it in unsubscribe method
22518
+ // if useCaptureOrIndx is negative number then it is a Subscription
22519
+ const type = (typeof useCaptureOrIndx === 'boolean' || useCaptureOrIndx >= 0) ? 'dom' : 'output';
22520
+ const useCapture = typeof useCaptureOrIndx === 'boolean' ? useCaptureOrIndx : false;
22521
+ if (element == listenerElement) {
22522
+ listeners.push({ element, name, callback, useCapture, type });
22803
22523
  }
22804
22524
  }
22805
22525
  }
22806
- finally {
22807
- this.cachedInjectors.clear();
22808
- }
22809
22526
  }
22527
+ listeners.sort(sortListeners);
22528
+ return listeners;
22529
+ }
22530
+ function sortListeners(a, b) {
22531
+ if (a.name == b.name)
22532
+ return 0;
22533
+ return a.name < b.name ? -1 : 1;
22810
22534
  }
22811
- /** @nocollapse */
22812
- StandaloneService.ɵprov = ɵɵdefineInjectable({
22813
- token: StandaloneService,
22814
- providedIn: 'environment',
22815
- factory: () => new StandaloneService(ɵɵinject(EnvironmentInjector)),
22816
- });
22817
22535
  /**
22818
- * A feature that acts as a setup code for the {@link StandaloneService}.
22536
+ * This function should not exist because it is megamorphic and only mostly correct.
22819
22537
  *
22820
- * The most important responsaibility of this feature is to expose the "getStandaloneInjector"
22821
- * function (an entry points to a standalone injector creation) on a component definition object. We
22822
- * go through the features infrastructure to make sure that the standalone injector creation logic
22823
- * is tree-shakable and not included in applications that don't use standalone components.
22538
+ * See call site for more info.
22539
+ */
22540
+ function isDirectiveDefHack(obj) {
22541
+ return obj.type !== undefined && obj.template !== undefined && obj.declaredInputs !== undefined;
22542
+ }
22543
+ /**
22544
+ * Returns the attached `DebugNode` instance for an element in the DOM.
22824
22545
  *
22825
- * @codeGenApi
22546
+ * @param element DOM element which is owned by an existing component's view.
22826
22547
  */
22827
- function ɵɵStandaloneFeature(definition) {
22828
- definition.getStandaloneInjector = (parentInjector) => {
22829
- return parentInjector.get(StandaloneService).getOrCreateStandaloneInjector(definition);
22830
- };
22548
+ function getDebugNode(element) {
22549
+ if (ngDevMode && !(element instanceof Node)) {
22550
+ throw new Error('Expecting instance of DOM Element');
22551
+ }
22552
+ const lContext = getLContext(element);
22553
+ const lView = lContext ? lContext.lView : null;
22554
+ if (lView === null) {
22555
+ return null;
22556
+ }
22557
+ const nodeIndex = lContext.nodeIndex;
22558
+ if (nodeIndex !== -1) {
22559
+ const valueInLView = lView[nodeIndex];
22560
+ // this means that value in the lView is a component with its own
22561
+ // data. In this situation the TNode is not accessed at the same spot.
22562
+ const tNode = isLView(valueInLView) ? valueInLView[T_HOST] : getTNode(lView[TVIEW], nodeIndex);
22563
+ ngDevMode &&
22564
+ assertEqual(tNode.index, nodeIndex, 'Expecting that TNode at index is same as index');
22565
+ return buildDebugNode(tNode, lView);
22566
+ }
22567
+ return null;
22568
+ }
22569
+ /**
22570
+ * Retrieve the component `LView` from component/element.
22571
+ *
22572
+ * NOTE: `LView` is a private and should not be leaked outside.
22573
+ * Don't export this method to `ng.*` on window.
22574
+ *
22575
+ * @param target DOM element or component instance for which to retrieve the LView.
22576
+ */
22577
+ function getComponentLView(target) {
22578
+ const lContext = getLContext(target);
22579
+ const nodeIndx = lContext.nodeIndex;
22580
+ const lView = lContext.lView;
22581
+ ngDevMode && assertLView(lView);
22582
+ const componentLView = lView[nodeIndx];
22583
+ ngDevMode && assertLView(componentLView);
22584
+ return componentLView;
22585
+ }
22586
+ /** Asserts that a value is a DOM Element. */
22587
+ function assertDomElement(value) {
22588
+ if (typeof Element !== 'undefined' && !(value instanceof Element)) {
22589
+ throw new Error('Expecting instance of DOM Element');
22590
+ }
22831
22591
  }
22832
22592
 
22833
22593
  /**
@@ -24048,7 +23808,7 @@ const unusedValueExportToPlacateAjd = 1;
24048
23808
  * Use of this source code is governed by an MIT-style license that can be
24049
23809
  * found in the LICENSE file at https://angular.io/license
24050
23810
  */
24051
- const unusedValueToPlacateAjd = unusedValueExportToPlacateAjd$1 + unusedValueExportToPlacateAjd$5 + unusedValueExportToPlacateAjd$4 + unusedValueExportToPlacateAjd;
23811
+ const unusedValueToPlacateAjd = unusedValueExportToPlacateAjd$1 + unusedValueExportToPlacateAjd$6 + unusedValueExportToPlacateAjd$5 + unusedValueExportToPlacateAjd;
24052
23812
  class LQuery_ {
24053
23813
  constructor(queryList) {
24054
23814
  this.queryList = queryList;