@angular/core 11.0.4 → 11.0.8

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.
package/fesm2015/core.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Angular v11.0.4
2
+ * @license Angular v11.0.8
3
3
  * (c) 2010-2020 Google LLC. https://angular.io/
4
4
  * License: MIT
5
5
  */
@@ -2439,8 +2439,9 @@ function callHooks(currentView, arr, initPhase, currentNodeIndex) {
2439
2439
  (currentView[PREORDER_HOOK_FLAGS] & 65535 /* IndexOfTheNextPreOrderHookMaskMask */) :
2440
2440
  0;
2441
2441
  const nodeIndexLimit = currentNodeIndex != null ? currentNodeIndex : -1;
2442
+ const max = arr.length - 1; // Stop the loop at length - 1, because we look for the hook at i + 1
2442
2443
  let lastNodeIndexFound = 0;
2443
- for (let i = startIndex; i < arr.length; i++) {
2444
+ for (let i = startIndex; i < max; i++) {
2444
2445
  const hook = arr[i + 1];
2445
2446
  if (typeof hook === 'number') {
2446
2447
  lastNodeIndexFound = arr[i];
@@ -2477,8 +2478,7 @@ function callHook(currentView, initPhase, arr, i) {
2477
2478
  const directive = currentView[directiveIndex];
2478
2479
  if (isInitHook) {
2479
2480
  const indexWithintInitPhase = currentView[FLAGS] >> 11 /* IndexWithinInitPhaseShift */;
2480
- // The init phase state must be always checked here as it may have been recursively
2481
- // updated
2481
+ // The init phase state must be always checked here as it may have been recursively updated.
2482
2482
  if (indexWithintInitPhase <
2483
2483
  (currentView[PREORDER_HOOK_FLAGS] >> 16 /* NumberOfInitHooksCalledShift */) &&
2484
2484
  (currentView[FLAGS] & 3 /* InitPhaseStateMask */) === initPhase) {
@@ -4977,6 +4977,9 @@ function injectArgs(types) {
4977
4977
  else if (meta instanceof Self || meta.ngMetadataName === 'Self' || meta === Self) {
4978
4978
  flags |= InjectFlags.Self;
4979
4979
  }
4980
+ else if (meta instanceof Host || meta.ngMetadataName === 'Host' || meta === Host) {
4981
+ flags |= InjectFlags.Host;
4982
+ }
4980
4983
  else if (meta instanceof Inject || meta === Inject) {
4981
4984
  type = meta.token;
4982
4985
  }
@@ -5271,13 +5274,17 @@ function bypassSanitizationTrustResourceUrl(trustedResourceUrl) {
5271
5274
  * Fallback: InertDocument strategy
5272
5275
  */
5273
5276
  function getInertBodyHelper(defaultDoc) {
5274
- return isDOMParserAvailable() ? new DOMParserHelper() : new InertDocumentHelper(defaultDoc);
5277
+ const inertDocumentHelper = new InertDocumentHelper(defaultDoc);
5278
+ return isDOMParserAvailable() ? new DOMParserHelper(inertDocumentHelper) : inertDocumentHelper;
5275
5279
  }
5276
5280
  /**
5277
5281
  * Uses DOMParser to create and fill an inert body element.
5278
5282
  * This is the default strategy used in browsers that support it.
5279
5283
  */
5280
5284
  class DOMParserHelper {
5285
+ constructor(inertDocumentHelper) {
5286
+ this.inertDocumentHelper = inertDocumentHelper;
5287
+ }
5281
5288
  getInertBodyElement(html) {
5282
5289
  // We add these extra elements to ensure that the rest of the content is parsed as expected
5283
5290
  // e.g. leading whitespace is maintained and tags like `<meta>` do not get hoisted to the
@@ -5288,6 +5295,12 @@ class DOMParserHelper {
5288
5295
  const body = new window.DOMParser()
5289
5296
  .parseFromString(trustedHTMLFromString(html), 'text/html')
5290
5297
  .body;
5298
+ if (body === null) {
5299
+ // In some browsers (e.g. Mozilla/5.0 iPad AppleWebKit Mobile) the `body` property only
5300
+ // becomes available in the following tick of the JS engine. In that case we fall back to
5301
+ // the `inertDocumentHelper` instead.
5302
+ return this.inertDocumentHelper.getInertBodyElement(html);
5303
+ }
5291
5304
  body.removeChild(body.firstChild);
5292
5305
  return body;
5293
5306
  }
@@ -6065,6 +6078,42 @@ const NO_ERRORS_SCHEMA = {
6065
6078
  name: 'no-errors-schema'
6066
6079
  };
6067
6080
 
6081
+ /**
6082
+ * @license
6083
+ * Copyright Google LLC All Rights Reserved.
6084
+ *
6085
+ * Use of this source code is governed by an MIT-style license that can be
6086
+ * found in the LICENSE file at https://angular.io/license
6087
+ */
6088
+ const END_COMMENT = /-->/g;
6089
+ const END_COMMENT_ESCAPED = '-\u200B-\u200B>';
6090
+ /**
6091
+ * Escape the content of the strings so that it can be safely inserted into a comment node.
6092
+ *
6093
+ * The issue is that HTML does not specify any way to escape comment end text inside the comment.
6094
+ * `<!-- The way you close a comment is with "-->". -->`. Above the `"-->"` is meant to be text not
6095
+ * an end to the comment. This can be created programmatically through DOM APIs.
6096
+ *
6097
+ * ```
6098
+ * div.innerHTML = div.innerHTML
6099
+ * ```
6100
+ *
6101
+ * One would expect that the above code would be safe to do, but it turns out that because comment
6102
+ * text is not escaped, the comment may contain text which will prematurely close the comment
6103
+ * opening up the application for XSS attack. (In SSR we programmatically create comment nodes which
6104
+ * may contain such text and expect them to be safe.)
6105
+ *
6106
+ * This function escapes the comment text by looking for the closing char sequence `-->` and replace
6107
+ * it with `-_-_>` where the `_` is a zero width space `\u200B`. The result is that if a comment
6108
+ * contains `-->` text it will render normally but it will not cause the HTML parser to close the
6109
+ * comment.
6110
+ *
6111
+ * @param value text to make safe for comment node by escaping the comment close character sequence
6112
+ */
6113
+ function escapeCommentText(value) {
6114
+ return value.replace(END_COMMENT, END_COMMENT_ESCAPED);
6115
+ }
6116
+
6068
6117
  /**
6069
6118
  * @license
6070
6119
  * Copyright Google LLC All Rights Reserved.
@@ -6749,7 +6798,7 @@ function createCommentNode(renderer, value) {
6749
6798
  ngDevMode && ngDevMode.rendererCreateComment++;
6750
6799
  // isProceduralRenderer check is not needed because both `Renderer2` and `Renderer3` have the same
6751
6800
  // method name.
6752
- return renderer.createComment(value);
6801
+ return renderer.createComment(escapeCommentText(value));
6753
6802
  }
6754
6803
  /**
6755
6804
  * Creates a native element from a tag name, using a renderer.
@@ -7085,12 +7134,12 @@ function processCleanups(tView, lView) {
7085
7134
  tCleanup[i].call(context);
7086
7135
  }
7087
7136
  }
7088
- if (lCleanup !== null) {
7089
- for (let i = lastLCleanupIndex + 1; i < lCleanup.length; i++) {
7090
- const instanceCleanupFn = lCleanup[i];
7091
- ngDevMode && assertFunction(instanceCleanupFn, 'Expecting instance cleanup function.');
7092
- instanceCleanupFn();
7093
- }
7137
+ }
7138
+ if (lCleanup !== null) {
7139
+ for (let i = lastLCleanupIndex + 1; i < lCleanup.length; i++) {
7140
+ const instanceCleanupFn = lCleanup[i];
7141
+ ngDevMode && assertFunction(instanceCleanupFn, 'Expecting instance cleanup function.');
7142
+ instanceCleanupFn();
7094
7143
  }
7095
7144
  lView[CLEANUP] = null;
7096
7145
  }
@@ -9491,19 +9540,19 @@ function locateHostElement(renderer, elementOrSelector, encapsulation) {
9491
9540
  * is `null` and the function is store in `LView` (rather than it `TView`).
9492
9541
  */
9493
9542
  function storeCleanupWithContext(tView, lView, context, cleanupFn) {
9494
- const lCleanup = getLCleanup(lView);
9543
+ const lCleanup = getOrCreateLViewCleanup(lView);
9495
9544
  if (context === null) {
9496
9545
  // If context is null that this is instance specific callback. These callbacks can only be
9497
9546
  // inserted after template shared instances. For this reason in ngDevMode we freeze the TView.
9498
9547
  if (ngDevMode) {
9499
- Object.freeze(getTViewCleanup(tView));
9548
+ Object.freeze(getOrCreateTViewCleanup(tView));
9500
9549
  }
9501
9550
  lCleanup.push(cleanupFn);
9502
9551
  }
9503
9552
  else {
9504
9553
  lCleanup.push(context);
9505
9554
  if (tView.firstCreatePass) {
9506
- getTViewCleanup(tView).push(cleanupFn, lCleanup.length - 1);
9555
+ getOrCreateTViewCleanup(tView).push(cleanupFn, lCleanup.length - 1);
9507
9556
  }
9508
9557
  }
9509
9558
  }
@@ -9735,7 +9784,7 @@ function setNgReflectProperty(lView, element, type, attrName, value) {
9735
9784
  }
9736
9785
  }
9737
9786
  else {
9738
- const textContent = `bindings=${JSON.stringify({ [attrName]: debugValue }, null, 2)}`;
9787
+ const textContent = escapeCommentText(`bindings=${JSON.stringify({ [attrName]: debugValue }, null, 2)}`);
9739
9788
  if (isProceduralRenderer(renderer)) {
9740
9789
  renderer.setValue(element, textContent);
9741
9790
  }
@@ -10581,11 +10630,11 @@ function storePropertyBindingMetadata(tData, tNode, propertyName, bindingIndex,
10581
10630
  }
10582
10631
  }
10583
10632
  const CLEAN_PROMISE = _CLEAN_PROMISE;
10584
- function getLCleanup(view) {
10633
+ function getOrCreateLViewCleanup(view) {
10585
10634
  // top level variables should not be exported for performance reasons (PERF_NOTES.md)
10586
10635
  return view[CLEANUP] || (view[CLEANUP] = ngDevMode ? new LCleanup() : []);
10587
10636
  }
10588
- function getTViewCleanup(tView) {
10637
+ function getOrCreateTViewCleanup(tView) {
10589
10638
  return tView.cleanup || (tView.cleanup = ngDevMode ? new TCleanup() : []);
10590
10639
  }
10591
10640
  /**
@@ -14843,11 +14892,11 @@ function findExistingListener(tView, lView, eventName, tNodeIdx) {
14843
14892
  function listenerInternal(tView, lView, renderer, tNode, eventName, listenerFn, useCapture = false, eventTargetResolver) {
14844
14893
  const isTNodeDirectiveHost = isDirectiveHost(tNode);
14845
14894
  const firstCreatePass = tView.firstCreatePass;
14846
- const tCleanup = firstCreatePass && getTViewCleanup(tView);
14895
+ const tCleanup = firstCreatePass && getOrCreateTViewCleanup(tView);
14847
14896
  // When the ɵɵlistener instruction was generated and is executed we know that there is either a
14848
14897
  // native listener or a directive output on this element. As such we we know that we will have to
14849
14898
  // register a listener and store its cleanup function on LView.
14850
- const lCleanup = getLCleanup(lView);
14899
+ const lCleanup = getOrCreateLViewCleanup(lView);
14851
14900
  ngDevMode && assertTNodeType(tNode, 3 /* AnyRNode */ | 12 /* AnyContainer */);
14852
14901
  let processOutputs = true;
14853
14902
  // add native event listener - applicable to elements only
@@ -21112,7 +21161,7 @@ class Version {
21112
21161
  /**
21113
21162
  * @publicApi
21114
21163
  */
21115
- const VERSION = new Version('11.0.4');
21164
+ const VERSION = new Version('11.0.8');
21116
21165
 
21117
21166
  /**
21118
21167
  * @license
@@ -22272,7 +22321,7 @@ class ViewRef {
22272
22321
  this._lView = _lView;
22273
22322
  this._cdRefInjectingView = _cdRefInjectingView;
22274
22323
  this._appRef = null;
22275
- this._viewContainerRef = null;
22324
+ this._attachedToViewContainer = false;
22276
22325
  }
22277
22326
  get rootNodes() {
22278
22327
  const lView = this._lView;
@@ -22289,12 +22338,19 @@ class ViewRef {
22289
22338
  if (this._appRef) {
22290
22339
  this._appRef.detachView(this);
22291
22340
  }
22292
- else if (this._viewContainerRef) {
22293
- const index = this._viewContainerRef.indexOf(this);
22294
- if (index > -1) {
22295
- this._viewContainerRef.detach(index);
22341
+ else if (this._attachedToViewContainer) {
22342
+ const parent = this._lView[PARENT];
22343
+ if (isLContainer(parent)) {
22344
+ const viewRefs = parent[VIEW_REFS];
22345
+ const index = viewRefs ? viewRefs.indexOf(this) : -1;
22346
+ if (index > -1) {
22347
+ ngDevMode &&
22348
+ assertEqual(index, parent.indexOf(this._lView) - CONTAINER_HEADER_OFFSET, 'An attached view should be in the same position within its container as its ViewRef in the VIEW_REFS array.');
22349
+ detachView(parent, index);
22350
+ removeFromArray(viewRefs, index);
22351
+ }
22296
22352
  }
22297
- this._viewContainerRef = null;
22353
+ this._attachedToViewContainer = false;
22298
22354
  }
22299
22355
  destroyLView(this._lView[TVIEW], this._lView);
22300
22356
  }
@@ -22486,18 +22542,18 @@ class ViewRef {
22486
22542
  checkNoChanges() {
22487
22543
  checkNoChangesInternal(this._lView[TVIEW], this._lView, this.context);
22488
22544
  }
22489
- attachToViewContainerRef(vcRef) {
22545
+ attachToViewContainerRef() {
22490
22546
  if (this._appRef) {
22491
22547
  throw new Error('This view is already attached directly to the ApplicationRef!');
22492
22548
  }
22493
- this._viewContainerRef = vcRef;
22549
+ this._attachedToViewContainer = true;
22494
22550
  }
22495
22551
  detachFromAppRef() {
22496
22552
  this._appRef = null;
22497
22553
  renderDetachView(this._lView[TVIEW], this._lView);
22498
22554
  }
22499
22555
  attachToAppRef(appRef) {
22500
- if (this._viewContainerRef) {
22556
+ if (this._attachedToViewContainer) {
22501
22557
  throw new Error('This view is already attached to a ViewContainer!');
22502
22558
  }
22503
22559
  this._appRef = appRef;
@@ -22878,7 +22934,7 @@ const R3ViewContainerRef = class ViewContainerRef extends VE_ViewContainerRef {
22878
22934
  if (parentRNode !== null) {
22879
22935
  addViewToContainer(tView, lContainer[T_HOST], renderer, lView, parentRNode, beforeNode);
22880
22936
  }
22881
- viewRef.attachToViewContainerRef(this);
22937
+ viewRef.attachToViewContainerRef();
22882
22938
  addToArray(getOrCreateViewRefs(lContainer), adjustedIdx, viewRef);
22883
22939
  return viewRef;
22884
22940
  }
@@ -28601,6 +28657,11 @@ function enableProdMode() {
28601
28657
  if (_runModeLocked) {
28602
28658
  throw new Error('Cannot enable prod mode after platform setup.');
28603
28659
  }
28660
+ // The below check is there so when ngDevMode is set via terser
28661
+ // `global['ngDevMode'] = false;` is also dropped.
28662
+ if (typeof ngDevMode === undefined || !!ngDevMode) {
28663
+ _global['ngDevMode'] = false;
28664
+ }
28604
28665
  _devMode = false;
28605
28666
  }
28606
28667
 
@@ -28699,7 +28760,7 @@ function createPlatform(injector) {
28699
28760
  }
28700
28761
  /**
28701
28762
  * Creates a factory for a platform. Can be used to provide or override `Providers` specific to
28702
- * your applciation's runtime needs, such as `PLATFORM_INITIALIZER` and `PLATFORM_ID`.
28763
+ * your application's runtime needs, such as `PLATFORM_INITIALIZER` and `PLATFORM_ID`.
28703
28764
  * @param parentPlatformFactory Another platform factory to modify. Allows you to compose factories
28704
28765
  * to build up configurations that might be required by different libraries or parts of the
28705
28766
  * application.
@@ -32101,7 +32162,7 @@ function debugCheckAndUpdateNode(view, nodeDef, argStyle, givenValues) {
32101
32162
  const el = asElementData(view, elDef.nodeIndex).renderElement;
32102
32163
  if (!elDef.element.name) {
32103
32164
  // a comment.
32104
- view.renderer.setValue(el, `bindings=${JSON.stringify(bindingValues, null, 2)}`);
32165
+ view.renderer.setValue(el, escapeCommentText(`bindings=${JSON.stringify(bindingValues, null, 2)}`));
32105
32166
  }
32106
32167
  else {
32107
32168
  // a regular element.
@@ -32351,7 +32412,7 @@ class DebugRenderer2 {
32351
32412
  return el;
32352
32413
  }
32353
32414
  createComment(value) {
32354
- const comment = this.delegate.createComment(value);
32415
+ const comment = this.delegate.createComment(escapeCommentText(value));
32355
32416
  const debugCtx = this.createDebugContext(comment);
32356
32417
  if (debugCtx) {
32357
32418
  indexDebugNode(new DebugNode__PRE_R3__(comment, null, debugCtx));