@angular/core 14.0.0-rc.2 → 14.0.1
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/esm2020/src/di/injector_compatibility.mjs +57 -15
- package/esm2020/src/di/interface/provider.mjs +1 -1
- package/esm2020/src/di/provider_collection.mjs +32 -2
- package/esm2020/src/di/r3_injector.mjs +3 -1
- package/esm2020/src/error_handler.mjs +4 -7
- package/esm2020/src/errors.mjs +6 -3
- package/esm2020/src/metadata/directives.mjs +1 -1
- package/esm2020/src/render3/component.mjs +9 -9
- package/esm2020/src/render3/definition.mjs +6 -6
- package/esm2020/src/render3/features/standalone_feature.mjs +4 -4
- package/esm2020/src/render3/instructions/all.mjs +2 -2
- package/esm2020/src/render3/instructions/element.mjs +4 -79
- package/esm2020/src/render3/instructions/element_validation.mjs +264 -0
- package/esm2020/src/render3/instructions/shared.mjs +7 -113
- package/esm2020/src/render3/interfaces/definition.mjs +1 -1
- package/esm2020/src/render3/jit/module.mjs +2 -2
- package/esm2020/src/render3/ng_module_ref.mjs +2 -1
- package/esm2020/src/render3/pipe.mjs +20 -6
- package/esm2020/src/render3/state.mjs +1 -3
- package/esm2020/src/util/errors.mjs +1 -8
- package/esm2020/src/version.mjs +1 -1
- package/esm2020/testing/src/logger.mjs +3 -3
- package/esm2020/testing/src/ng_zone_mock.mjs +3 -3
- package/esm2020/testing/src/test_bed.mjs +5 -2
- package/fesm2015/core.mjs +630 -471
- package/fesm2015/core.mjs.map +1 -1
- package/fesm2015/testing.mjs +696 -534
- package/fesm2015/testing.mjs.map +1 -1
- package/fesm2020/core.mjs +626 -468
- package/fesm2020/core.mjs.map +1 -1
- package/fesm2020/testing.mjs +701 -540
- package/fesm2020/testing.mjs.map +1 -1
- package/index.d.ts +80 -33
- package/package.json +1 -1
- package/testing/index.d.ts +5 -2
package/fesm2020/testing.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Angular v14.0.
|
|
2
|
+
* @license Angular v14.0.1
|
|
3
3
|
* (c) 2010-2022 Google LLC. https://angular.io/
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
@@ -1842,9 +1842,12 @@ function formatRuntimeError(code, message) {
|
|
|
1842
1842
|
// Error code might be a negative number, which is a special marker that instructs the logic to
|
|
1843
1843
|
// generate a link to the error details page on angular.io.
|
|
1844
1844
|
const fullCode = `NG0${Math.abs(code)}`;
|
|
1845
|
-
let errorMessage = `${fullCode}${message ? ': ' + message : ''}`;
|
|
1845
|
+
let errorMessage = `${fullCode}${message ? ': ' + message.trim() : ''}`;
|
|
1846
1846
|
if (ngDevMode && code < 0) {
|
|
1847
|
-
|
|
1847
|
+
const addPeriodSeparator = !errorMessage.match(/[.,;!?]$/);
|
|
1848
|
+
const separator = addPeriodSeparator ? '.' : '';
|
|
1849
|
+
errorMessage =
|
|
1850
|
+
`${errorMessage}${separator} Find more at ${ERROR_DETAILS_PAGE_BASE_URL}/${fullCode}`;
|
|
1848
1851
|
}
|
|
1849
1852
|
return errorMessage;
|
|
1850
1853
|
}
|
|
@@ -2043,9 +2046,9 @@ function setCurrentInjector(injector) {
|
|
|
2043
2046
|
function injectInjectorOnly(token, flags = InjectFlags.Default) {
|
|
2044
2047
|
if (_currentInjector === undefined) {
|
|
2045
2048
|
const errorMessage = (typeof ngDevMode === 'undefined' || ngDevMode) ?
|
|
2046
|
-
`inject() must be called from an injection context` :
|
|
2049
|
+
`inject() must be called from an injection context (a constructor, a factory function or a field initializer)` :
|
|
2047
2050
|
'';
|
|
2048
|
-
throw new RuntimeError(203 /* RuntimeErrorCode.MISSING_INJECTION_CONTEXT */, errorMessage);
|
|
2051
|
+
throw new RuntimeError(-203 /* RuntimeErrorCode.MISSING_INJECTION_CONTEXT */, errorMessage);
|
|
2049
2052
|
}
|
|
2050
2053
|
else if (_currentInjector === null) {
|
|
2051
2054
|
return injectRootLimpMode(token, undefined, flags);
|
|
@@ -2080,29 +2083,71 @@ Please check that 1) the type for the parameter at index ${index} is correct and
|
|
|
2080
2083
|
}
|
|
2081
2084
|
/**
|
|
2082
2085
|
* Injects a token from the currently active injector.
|
|
2083
|
-
*
|
|
2084
|
-
*
|
|
2085
|
-
* `
|
|
2086
|
-
*
|
|
2087
|
-
*
|
|
2088
|
-
*
|
|
2089
|
-
*
|
|
2090
|
-
*
|
|
2091
|
-
* @param token
|
|
2086
|
+
* `inject` is only supported during instantiation of a dependency by the DI system. It can be used
|
|
2087
|
+
* during:
|
|
2088
|
+
* - Construction (via the `constructor`) of a class being instantiated by the DI system, such
|
|
2089
|
+
* as an `@Injectable` or `@Component`.
|
|
2090
|
+
* - In the initializer for fields of such classes.
|
|
2091
|
+
* - In the factory function specified for `useFactory` of a `Provider` or an `@Injectable`.
|
|
2092
|
+
* - In the `factory` function specified for an `InjectionToken`.
|
|
2093
|
+
*
|
|
2094
|
+
* @param token A token that represents a dependency that should be injected.
|
|
2092
2095
|
* @param flags Optional flags that control how injection is executed.
|
|
2093
2096
|
* The flags correspond to injection strategies that can be specified with
|
|
2094
2097
|
* parameter decorators `@Host`, `@Self`, `@SkipSef`, and `@Optional`.
|
|
2095
|
-
* @returns the injected value if
|
|
2098
|
+
* @returns the injected value if operation is successful, `null` otherwise.
|
|
2099
|
+
* @throws if called outside of a supported context.
|
|
2096
2100
|
*
|
|
2097
2101
|
* @usageNotes
|
|
2102
|
+
* In practice the `inject()` calls are allowed in a constructor, a constructor parameter and a
|
|
2103
|
+
* field initializer:
|
|
2098
2104
|
*
|
|
2099
|
-
*
|
|
2105
|
+
* ```typescript
|
|
2106
|
+
* @Injectable({providedIn: 'root'})
|
|
2107
|
+
* export class Car {
|
|
2108
|
+
* radio: Radio|undefined;
|
|
2109
|
+
* // OK: field initializer
|
|
2110
|
+
* spareTyre = inject(Tyre);
|
|
2100
2111
|
*
|
|
2101
|
-
* {
|
|
2112
|
+
* constructor() {
|
|
2113
|
+
* // OK: constructor body
|
|
2114
|
+
* this.radio = inject(Radio);
|
|
2115
|
+
* }
|
|
2116
|
+
* }
|
|
2117
|
+
* ```
|
|
2118
|
+
*
|
|
2119
|
+
* It is also legal to call `inject` from a provider's factory:
|
|
2120
|
+
*
|
|
2121
|
+
* ```typescript
|
|
2122
|
+
* providers: [
|
|
2123
|
+
* {provide: Car, useFactory: () => {
|
|
2124
|
+
* // OK: a class factory
|
|
2125
|
+
* const engine = inject(Engine);
|
|
2126
|
+
* return new Car(engine);
|
|
2127
|
+
* }}
|
|
2128
|
+
* ]
|
|
2129
|
+
* ```
|
|
2130
|
+
*
|
|
2131
|
+
* Calls to the `inject()` function outside of the class creation context will result in error. Most
|
|
2132
|
+
* notably, calls to `inject()` are disallowed after a class instance was created, in methods
|
|
2133
|
+
* (including lifecycle hooks):
|
|
2134
|
+
*
|
|
2135
|
+
* ```typescript
|
|
2136
|
+
* @Component({ ... })
|
|
2137
|
+
* export class CarComponent {
|
|
2138
|
+
* ngOnInit() {
|
|
2139
|
+
* // ERROR: too late, the component instance was already created
|
|
2140
|
+
* const engine = inject(Engine);
|
|
2141
|
+
* engine.start();
|
|
2142
|
+
* }
|
|
2143
|
+
* }
|
|
2144
|
+
* ```
|
|
2102
2145
|
*
|
|
2103
2146
|
* @publicApi
|
|
2104
2147
|
*/
|
|
2105
|
-
|
|
2148
|
+
function inject$1(token, flags = InjectFlags.Default) {
|
|
2149
|
+
return ɵɵinject(token, flags);
|
|
2150
|
+
}
|
|
2106
2151
|
function injectArgs(types) {
|
|
2107
2152
|
const args = [];
|
|
2108
2153
|
for (let i = 0; i < types.length; i++) {
|
|
@@ -2428,7 +2473,8 @@ const NG_ELEMENT_ID = getClosureSafeProperty({ __NG_ELEMENT_ID__: getClosureSafe
|
|
|
2428
2473
|
* Use of this source code is governed by an MIT-style license that can be
|
|
2429
2474
|
* found in the LICENSE file at https://angular.io/license
|
|
2430
2475
|
*/
|
|
2431
|
-
|
|
2476
|
+
/** Counter used to generate unique IDs for component definitions. */
|
|
2477
|
+
let componentDefCount = 0;
|
|
2432
2478
|
/**
|
|
2433
2479
|
* Create a component definition object.
|
|
2434
2480
|
*
|
|
@@ -2481,7 +2527,7 @@ function ɵɵdefineComponent(componentDefinition) {
|
|
|
2481
2527
|
features: componentDefinition.features || null,
|
|
2482
2528
|
data: componentDefinition.data || {},
|
|
2483
2529
|
encapsulation: componentDefinition.encapsulation || ViewEncapsulation.Emulated,
|
|
2484
|
-
id:
|
|
2530
|
+
id: `c${componentDefCount++}`,
|
|
2485
2531
|
styles: componentDefinition.styles || EMPTY_ARRAY,
|
|
2486
2532
|
_: null,
|
|
2487
2533
|
setInput: null,
|
|
@@ -2490,7 +2536,6 @@ function ɵɵdefineComponent(componentDefinition) {
|
|
|
2490
2536
|
};
|
|
2491
2537
|
const dependencies = componentDefinition.dependencies;
|
|
2492
2538
|
const feature = componentDefinition.features;
|
|
2493
|
-
def.id += _renderCompCount++;
|
|
2494
2539
|
def.inputs = invertObject(componentDefinition.inputs, declaredInputs),
|
|
2495
2540
|
def.outputs = invertObject(componentDefinition.outputs),
|
|
2496
2541
|
feature && feature.forEach((fn) => fn(def));
|
|
@@ -2518,8 +2563,8 @@ function ɵɵdefineComponent(componentDefinition) {
|
|
|
2518
2563
|
*/
|
|
2519
2564
|
function ɵɵsetComponentScope(type, directives, pipes) {
|
|
2520
2565
|
const def = type.ɵcmp;
|
|
2521
|
-
def.directiveDefs = () => directives.map(extractDirectiveDef);
|
|
2522
|
-
def.pipeDefs = () => pipes.map(getPipeDef$1);
|
|
2566
|
+
def.directiveDefs = () => (typeof directives === 'function' ? directives() : directives).map(extractDirectiveDef);
|
|
2567
|
+
def.pipeDefs = () => (typeof pipes === 'function' ? pipes() : pipes).map(getPipeDef$1);
|
|
2523
2568
|
}
|
|
2524
2569
|
function extractDirectiveDef(type) {
|
|
2525
2570
|
return getComponentDef$1(type) || getDirectiveDef(type);
|
|
@@ -3504,7 +3549,6 @@ function getLView() {
|
|
|
3504
3549
|
function getTView() {
|
|
3505
3550
|
return instructionState.lFrame.tView;
|
|
3506
3551
|
}
|
|
3507
|
-
// TODO(crisbeto): revert the @noinline once Closure issue is resolved.
|
|
3508
3552
|
/**
|
|
3509
3553
|
* Restores `contextViewData` to the given OpaqueViewState instance.
|
|
3510
3554
|
*
|
|
@@ -3516,7 +3560,6 @@ function getTView() {
|
|
|
3516
3560
|
* @returns Context of the restored OpaqueViewState instance.
|
|
3517
3561
|
*
|
|
3518
3562
|
* @codeGenApi
|
|
3519
|
-
* @noinline Disable inlining due to issue with Closure in listeners inside embedded views.
|
|
3520
3563
|
*/
|
|
3521
3564
|
function ɵɵrestoreView(viewToRestore) {
|
|
3522
3565
|
instructionState.lFrame.contextLView = viewToRestore;
|
|
@@ -6581,6 +6624,155 @@ function getSanitizer() {
|
|
|
6581
6624
|
return lView && lView[SANITIZER];
|
|
6582
6625
|
}
|
|
6583
6626
|
|
|
6627
|
+
/**
|
|
6628
|
+
* @license
|
|
6629
|
+
* Copyright Google LLC All Rights Reserved.
|
|
6630
|
+
*
|
|
6631
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
6632
|
+
* found in the LICENSE file at https://angular.io/license
|
|
6633
|
+
*/
|
|
6634
|
+
const ERROR_ORIGINAL_ERROR = 'ngOriginalError';
|
|
6635
|
+
function wrappedError(message, originalError) {
|
|
6636
|
+
const msg = `${message} caused by: ${originalError instanceof Error ? originalError.message : originalError}`;
|
|
6637
|
+
const error = Error(msg);
|
|
6638
|
+
error[ERROR_ORIGINAL_ERROR] = originalError;
|
|
6639
|
+
return error;
|
|
6640
|
+
}
|
|
6641
|
+
function getOriginalError(error) {
|
|
6642
|
+
return error[ERROR_ORIGINAL_ERROR];
|
|
6643
|
+
}
|
|
6644
|
+
|
|
6645
|
+
/**
|
|
6646
|
+
* @license
|
|
6647
|
+
* Copyright Google LLC All Rights Reserved.
|
|
6648
|
+
*
|
|
6649
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
6650
|
+
* found in the LICENSE file at https://angular.io/license
|
|
6651
|
+
*/
|
|
6652
|
+
/**
|
|
6653
|
+
* Provides a hook for centralized exception handling.
|
|
6654
|
+
*
|
|
6655
|
+
* The default implementation of `ErrorHandler` prints error messages to the `console`. To
|
|
6656
|
+
* intercept error handling, write a custom exception handler that replaces this default as
|
|
6657
|
+
* appropriate for your app.
|
|
6658
|
+
*
|
|
6659
|
+
* @usageNotes
|
|
6660
|
+
* ### Example
|
|
6661
|
+
*
|
|
6662
|
+
* ```
|
|
6663
|
+
* class MyErrorHandler implements ErrorHandler {
|
|
6664
|
+
* handleError(error) {
|
|
6665
|
+
* // do something with the exception
|
|
6666
|
+
* }
|
|
6667
|
+
* }
|
|
6668
|
+
*
|
|
6669
|
+
* @NgModule({
|
|
6670
|
+
* providers: [{provide: ErrorHandler, useClass: MyErrorHandler}]
|
|
6671
|
+
* })
|
|
6672
|
+
* class MyModule {}
|
|
6673
|
+
* ```
|
|
6674
|
+
*
|
|
6675
|
+
* @publicApi
|
|
6676
|
+
*/
|
|
6677
|
+
class ErrorHandler {
|
|
6678
|
+
constructor() {
|
|
6679
|
+
/**
|
|
6680
|
+
* @internal
|
|
6681
|
+
*/
|
|
6682
|
+
this._console = console;
|
|
6683
|
+
}
|
|
6684
|
+
handleError(error) {
|
|
6685
|
+
const originalError = this._findOriginalError(error);
|
|
6686
|
+
this._console.error('ERROR', error);
|
|
6687
|
+
if (originalError) {
|
|
6688
|
+
this._console.error('ORIGINAL ERROR', originalError);
|
|
6689
|
+
}
|
|
6690
|
+
}
|
|
6691
|
+
/** @internal */
|
|
6692
|
+
_findOriginalError(error) {
|
|
6693
|
+
let e = error && getOriginalError(error);
|
|
6694
|
+
while (e && getOriginalError(e)) {
|
|
6695
|
+
e = getOriginalError(e);
|
|
6696
|
+
}
|
|
6697
|
+
return e || null;
|
|
6698
|
+
}
|
|
6699
|
+
}
|
|
6700
|
+
|
|
6701
|
+
/**
|
|
6702
|
+
* @license
|
|
6703
|
+
* Copyright Google LLC All Rights Reserved.
|
|
6704
|
+
*
|
|
6705
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
6706
|
+
* found in the LICENSE file at https://angular.io/license
|
|
6707
|
+
*/
|
|
6708
|
+
/**
|
|
6709
|
+
* Disallowed strings in the comment.
|
|
6710
|
+
*
|
|
6711
|
+
* see: https://html.spec.whatwg.org/multipage/syntax.html#comments
|
|
6712
|
+
*/
|
|
6713
|
+
const COMMENT_DISALLOWED = /^>|^->|<!--|-->|--!>|<!-$/g;
|
|
6714
|
+
/**
|
|
6715
|
+
* Delimiter in the disallowed strings which needs to be wrapped with zero with character.
|
|
6716
|
+
*/
|
|
6717
|
+
const COMMENT_DELIMITER = /(<|>)/;
|
|
6718
|
+
const COMMENT_DELIMITER_ESCAPED = '\u200B$1\u200B';
|
|
6719
|
+
/**
|
|
6720
|
+
* Escape the content of comment strings so that it can be safely inserted into a comment node.
|
|
6721
|
+
*
|
|
6722
|
+
* The issue is that HTML does not specify any way to escape comment end text inside the comment.
|
|
6723
|
+
* Consider: `<!-- The way you close a comment is with ">", and "->" at the beginning or by "-->" or
|
|
6724
|
+
* "--!>" at the end. -->`. Above the `"-->"` is meant to be text not an end to the comment. This
|
|
6725
|
+
* can be created programmatically through DOM APIs. (`<!--` are also disallowed.)
|
|
6726
|
+
*
|
|
6727
|
+
* see: https://html.spec.whatwg.org/multipage/syntax.html#comments
|
|
6728
|
+
*
|
|
6729
|
+
* ```
|
|
6730
|
+
* div.innerHTML = div.innerHTML
|
|
6731
|
+
* ```
|
|
6732
|
+
*
|
|
6733
|
+
* One would expect that the above code would be safe to do, but it turns out that because comment
|
|
6734
|
+
* text is not escaped, the comment may contain text which will prematurely close the comment
|
|
6735
|
+
* opening up the application for XSS attack. (In SSR we programmatically create comment nodes which
|
|
6736
|
+
* may contain such text and expect them to be safe.)
|
|
6737
|
+
*
|
|
6738
|
+
* This function escapes the comment text by looking for comment delimiters (`<` and `>`) and
|
|
6739
|
+
* surrounding them with `_>_` where the `_` is a zero width space `\u200B`. The result is that if a
|
|
6740
|
+
* comment contains any of the comment start/end delimiters (such as `<!--`, `-->` or `--!>`) the
|
|
6741
|
+
* text it will render normally but it will not cause the HTML parser to close/open the comment.
|
|
6742
|
+
*
|
|
6743
|
+
* @param value text to make safe for comment node by escaping the comment open/close character
|
|
6744
|
+
* sequence.
|
|
6745
|
+
*/
|
|
6746
|
+
function escapeCommentText(value) {
|
|
6747
|
+
return value.replace(COMMENT_DISALLOWED, (text) => text.replace(COMMENT_DELIMITER, COMMENT_DELIMITER_ESCAPED));
|
|
6748
|
+
}
|
|
6749
|
+
|
|
6750
|
+
/**
|
|
6751
|
+
* @license
|
|
6752
|
+
* Copyright Google LLC All Rights Reserved.
|
|
6753
|
+
*
|
|
6754
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
6755
|
+
* found in the LICENSE file at https://angular.io/license
|
|
6756
|
+
*/
|
|
6757
|
+
function normalizeDebugBindingName(name) {
|
|
6758
|
+
// Attribute names with `$` (eg `x-y$`) are valid per spec, but unsupported by some browsers
|
|
6759
|
+
name = camelCaseToDashCase(name.replace(/[$@]/g, '_'));
|
|
6760
|
+
return `ng-reflect-${name}`;
|
|
6761
|
+
}
|
|
6762
|
+
const CAMEL_CASE_REGEXP = /([A-Z])/g;
|
|
6763
|
+
function camelCaseToDashCase(input) {
|
|
6764
|
+
return input.replace(CAMEL_CASE_REGEXP, (...m) => '-' + m[1].toLowerCase());
|
|
6765
|
+
}
|
|
6766
|
+
function normalizeDebugBindingValue(value) {
|
|
6767
|
+
try {
|
|
6768
|
+
// Limit the size of the value as otherwise the DOM just gets polluted.
|
|
6769
|
+
return value != null ? value.toString().slice(0, 30) : value;
|
|
6770
|
+
}
|
|
6771
|
+
catch (e) {
|
|
6772
|
+
return '[ERROR] Exception while trying to serialize the value';
|
|
6773
|
+
}
|
|
6774
|
+
}
|
|
6775
|
+
|
|
6584
6776
|
/**
|
|
6585
6777
|
* @license
|
|
6586
6778
|
* Copyright Google LLC All Rights Reserved.
|
|
@@ -6965,276 +7157,86 @@ function discoverLocalRefs(lView, nodeIndex) {
|
|
|
6965
7157
|
* Use of this source code is governed by an MIT-style license that can be
|
|
6966
7158
|
* found in the LICENSE file at https://angular.io/license
|
|
6967
7159
|
*/
|
|
6968
|
-
|
|
6969
|
-
|
|
6970
|
-
|
|
6971
|
-
|
|
6972
|
-
|
|
6973
|
-
|
|
6974
|
-
|
|
7160
|
+
/** Verifies that a given type is a Standalone Component. */
|
|
7161
|
+
function assertStandaloneComponentType(type) {
|
|
7162
|
+
const componentDef = getComponentDef$1(type);
|
|
7163
|
+
if (!componentDef) {
|
|
7164
|
+
throw new RuntimeError(906 /* RuntimeErrorCode.MISSING_GENERATED_DEF */, `The ${stringifyForError(type)} is not an Angular component, ` +
|
|
7165
|
+
`make sure it has the \`@Component\` decorator.`);
|
|
7166
|
+
}
|
|
7167
|
+
if (!componentDef.standalone) {
|
|
7168
|
+
throw new RuntimeError(907 /* RuntimeErrorCode.TYPE_IS_NOT_STANDALONE */, `The ${stringifyForError(type)} component is not marked as standalone, ` +
|
|
7169
|
+
`but Angular expects to have a standalone component here. ` +
|
|
7170
|
+
`Please make sure the ${stringifyForError(type)} component has ` +
|
|
7171
|
+
`the \`standalone: true\` flag in the decorator.`);
|
|
7172
|
+
}
|
|
6975
7173
|
}
|
|
6976
|
-
|
|
6977
|
-
|
|
7174
|
+
/** Called when there are multiple component selectors that match a given node */
|
|
7175
|
+
function throwMultipleComponentError(tNode, first, second) {
|
|
7176
|
+
throw new RuntimeError(-300 /* RuntimeErrorCode.MULTIPLE_COMPONENTS_MATCH */, `Multiple components match node with tagname ${tNode.value}: ` +
|
|
7177
|
+
`${stringifyForError(first)} and ` +
|
|
7178
|
+
`${stringifyForError(second)}`);
|
|
7179
|
+
}
|
|
7180
|
+
/** Throws an ExpressionChangedAfterChecked error if checkNoChanges mode is on. */
|
|
7181
|
+
function throwErrorIfNoChangesMode(creationMode, oldValue, currValue, propName) {
|
|
7182
|
+
const field = propName ? ` for '${propName}'` : '';
|
|
7183
|
+
let msg = `ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value${field}: '${oldValue}'. Current value: '${currValue}'.`;
|
|
7184
|
+
if (creationMode) {
|
|
7185
|
+
msg +=
|
|
7186
|
+
` It seems like the view has been created after its parent and its children have been dirty checked.` +
|
|
7187
|
+
` Has it been created in a change detection hook?`;
|
|
7188
|
+
}
|
|
7189
|
+
throw new RuntimeError(-100 /* RuntimeErrorCode.EXPRESSION_CHANGED_AFTER_CHECKED */, msg);
|
|
6978
7190
|
}
|
|
6979
|
-
function
|
|
6980
|
-
|
|
7191
|
+
function constructDetailsForInterpolation(lView, rootIndex, expressionIndex, meta, changedValue) {
|
|
7192
|
+
const [propName, prefix, ...chunks] = meta.split(INTERPOLATION_DELIMITER);
|
|
7193
|
+
let oldValue = prefix, newValue = prefix;
|
|
7194
|
+
for (let i = 0; i < chunks.length; i++) {
|
|
7195
|
+
const slotIdx = rootIndex + i;
|
|
7196
|
+
oldValue += `${lView[slotIdx]}${chunks[i]}`;
|
|
7197
|
+
newValue += `${slotIdx === expressionIndex ? changedValue : lView[slotIdx]}${chunks[i]}`;
|
|
7198
|
+
}
|
|
7199
|
+
return { propName, oldValue, newValue };
|
|
6981
7200
|
}
|
|
6982
|
-
|
|
6983
|
-
|
|
6984
|
-
|
|
6985
|
-
|
|
6986
|
-
|
|
6987
|
-
*
|
|
6988
|
-
*
|
|
6989
|
-
|
|
6990
|
-
|
|
6991
|
-
|
|
6992
|
-
|
|
6993
|
-
|
|
6994
|
-
|
|
6995
|
-
|
|
6996
|
-
|
|
6997
|
-
|
|
6998
|
-
|
|
6999
|
-
|
|
7000
|
-
|
|
7001
|
-
|
|
7002
|
-
|
|
7003
|
-
|
|
7004
|
-
|
|
7005
|
-
|
|
7006
|
-
|
|
7007
|
-
|
|
7008
|
-
|
|
7009
|
-
|
|
7010
|
-
|
|
7011
|
-
|
|
7012
|
-
|
|
7013
|
-
|
|
7014
|
-
|
|
7015
|
-
|
|
7016
|
-
|
|
7017
|
-
|
|
7018
|
-
|
|
7019
|
-
|
|
7020
|
-
|
|
7021
|
-
* @internal
|
|
7022
|
-
*/
|
|
7023
|
-
this._console = console;
|
|
7024
|
-
}
|
|
7025
|
-
handleError(error) {
|
|
7026
|
-
const originalError = this._findOriginalError(error);
|
|
7027
|
-
// Note: Browser consoles show the place from where console.error was called.
|
|
7028
|
-
// We can use this to give users additional information about the error.
|
|
7029
|
-
const errorLogger = getErrorLogger(error);
|
|
7030
|
-
errorLogger(this._console, `ERROR`, error);
|
|
7031
|
-
if (originalError) {
|
|
7032
|
-
errorLogger(this._console, `ORIGINAL ERROR`, originalError);
|
|
7033
|
-
}
|
|
7034
|
-
}
|
|
7035
|
-
/** @internal */
|
|
7036
|
-
_findOriginalError(error) {
|
|
7037
|
-
let e = error && getOriginalError(error);
|
|
7038
|
-
while (e && getOriginalError(e)) {
|
|
7039
|
-
e = getOriginalError(e);
|
|
7040
|
-
}
|
|
7041
|
-
return e || null;
|
|
7042
|
-
}
|
|
7043
|
-
}
|
|
7044
|
-
|
|
7045
|
-
/**
|
|
7046
|
-
* @license
|
|
7047
|
-
* Copyright Google LLC All Rights Reserved.
|
|
7048
|
-
*
|
|
7049
|
-
* Use of this source code is governed by an MIT-style license that can be
|
|
7050
|
-
* found in the LICENSE file at https://angular.io/license
|
|
7051
|
-
*/
|
|
7052
|
-
/**
|
|
7053
|
-
* Defines a schema that allows an NgModule to contain the following:
|
|
7054
|
-
* - Non-Angular elements named with dash case (`-`).
|
|
7055
|
-
* - Element properties named with dash case (`-`).
|
|
7056
|
-
* Dash case is the naming convention for custom elements.
|
|
7057
|
-
*
|
|
7058
|
-
* @publicApi
|
|
7059
|
-
*/
|
|
7060
|
-
const CUSTOM_ELEMENTS_SCHEMA = {
|
|
7061
|
-
name: 'custom-elements'
|
|
7062
|
-
};
|
|
7063
|
-
/**
|
|
7064
|
-
* Defines a schema that allows any property on any element.
|
|
7065
|
-
*
|
|
7066
|
-
* This schema allows you to ignore the errors related to any unknown elements or properties in a
|
|
7067
|
-
* template. The usage of this schema is generally discouraged because it prevents useful validation
|
|
7068
|
-
* and may hide real errors in your template. Consider using the `CUSTOM_ELEMENTS_SCHEMA` instead.
|
|
7069
|
-
*
|
|
7070
|
-
* @publicApi
|
|
7071
|
-
*/
|
|
7072
|
-
const NO_ERRORS_SCHEMA = {
|
|
7073
|
-
name: 'no-errors-schema'
|
|
7074
|
-
};
|
|
7075
|
-
|
|
7076
|
-
/**
|
|
7077
|
-
* @license
|
|
7078
|
-
* Copyright Google LLC All Rights Reserved.
|
|
7079
|
-
*
|
|
7080
|
-
* Use of this source code is governed by an MIT-style license that can be
|
|
7081
|
-
* found in the LICENSE file at https://angular.io/license
|
|
7082
|
-
*/
|
|
7083
|
-
/**
|
|
7084
|
-
* Disallowed strings in the comment.
|
|
7085
|
-
*
|
|
7086
|
-
* see: https://html.spec.whatwg.org/multipage/syntax.html#comments
|
|
7087
|
-
*/
|
|
7088
|
-
const COMMENT_DISALLOWED = /^>|^->|<!--|-->|--!>|<!-$/g;
|
|
7089
|
-
/**
|
|
7090
|
-
* Delimiter in the disallowed strings which needs to be wrapped with zero with character.
|
|
7091
|
-
*/
|
|
7092
|
-
const COMMENT_DELIMITER = /(<|>)/;
|
|
7093
|
-
const COMMENT_DELIMITER_ESCAPED = '\u200B$1\u200B';
|
|
7094
|
-
/**
|
|
7095
|
-
* Escape the content of comment strings so that it can be safely inserted into a comment node.
|
|
7096
|
-
*
|
|
7097
|
-
* The issue is that HTML does not specify any way to escape comment end text inside the comment.
|
|
7098
|
-
* Consider: `<!-- The way you close a comment is with ">", and "->" at the beginning or by "-->" or
|
|
7099
|
-
* "--!>" at the end. -->`. Above the `"-->"` is meant to be text not an end to the comment. This
|
|
7100
|
-
* can be created programmatically through DOM APIs. (`<!--` are also disallowed.)
|
|
7101
|
-
*
|
|
7102
|
-
* see: https://html.spec.whatwg.org/multipage/syntax.html#comments
|
|
7103
|
-
*
|
|
7104
|
-
* ```
|
|
7105
|
-
* div.innerHTML = div.innerHTML
|
|
7106
|
-
* ```
|
|
7107
|
-
*
|
|
7108
|
-
* One would expect that the above code would be safe to do, but it turns out that because comment
|
|
7109
|
-
* text is not escaped, the comment may contain text which will prematurely close the comment
|
|
7110
|
-
* opening up the application for XSS attack. (In SSR we programmatically create comment nodes which
|
|
7111
|
-
* may contain such text and expect them to be safe.)
|
|
7112
|
-
*
|
|
7113
|
-
* This function escapes the comment text by looking for comment delimiters (`<` and `>`) and
|
|
7114
|
-
* surrounding them with `_>_` where the `_` is a zero width space `\u200B`. The result is that if a
|
|
7115
|
-
* comment contains any of the comment start/end delimiters (such as `<!--`, `-->` or `--!>`) the
|
|
7116
|
-
* text it will render normally but it will not cause the HTML parser to close/open the comment.
|
|
7117
|
-
*
|
|
7118
|
-
* @param value text to make safe for comment node by escaping the comment open/close character
|
|
7119
|
-
* sequence.
|
|
7120
|
-
*/
|
|
7121
|
-
function escapeCommentText(value) {
|
|
7122
|
-
return value.replace(COMMENT_DISALLOWED, (text) => text.replace(COMMENT_DELIMITER, COMMENT_DELIMITER_ESCAPED));
|
|
7123
|
-
}
|
|
7124
|
-
|
|
7125
|
-
/**
|
|
7126
|
-
* @license
|
|
7127
|
-
* Copyright Google LLC All Rights Reserved.
|
|
7128
|
-
*
|
|
7129
|
-
* Use of this source code is governed by an MIT-style license that can be
|
|
7130
|
-
* found in the LICENSE file at https://angular.io/license
|
|
7131
|
-
*/
|
|
7132
|
-
function normalizeDebugBindingName(name) {
|
|
7133
|
-
// Attribute names with `$` (eg `x-y$`) are valid per spec, but unsupported by some browsers
|
|
7134
|
-
name = camelCaseToDashCase(name.replace(/[$@]/g, '_'));
|
|
7135
|
-
return `ng-reflect-${name}`;
|
|
7136
|
-
}
|
|
7137
|
-
const CAMEL_CASE_REGEXP = /([A-Z])/g;
|
|
7138
|
-
function camelCaseToDashCase(input) {
|
|
7139
|
-
return input.replace(CAMEL_CASE_REGEXP, (...m) => '-' + m[1].toLowerCase());
|
|
7140
|
-
}
|
|
7141
|
-
function normalizeDebugBindingValue(value) {
|
|
7142
|
-
try {
|
|
7143
|
-
// Limit the size of the value as otherwise the DOM just gets polluted.
|
|
7144
|
-
return value != null ? value.toString().slice(0, 30) : value;
|
|
7145
|
-
}
|
|
7146
|
-
catch (e) {
|
|
7147
|
-
return '[ERROR] Exception while trying to serialize the value';
|
|
7148
|
-
}
|
|
7149
|
-
}
|
|
7150
|
-
|
|
7151
|
-
/**
|
|
7152
|
-
* @license
|
|
7153
|
-
* Copyright Google LLC All Rights Reserved.
|
|
7154
|
-
*
|
|
7155
|
-
* Use of this source code is governed by an MIT-style license that can be
|
|
7156
|
-
* found in the LICENSE file at https://angular.io/license
|
|
7157
|
-
*/
|
|
7158
|
-
/** Verifies that a given type is a Standalone Component. */
|
|
7159
|
-
function assertStandaloneComponentType(type) {
|
|
7160
|
-
const componentDef = getComponentDef$1(type);
|
|
7161
|
-
if (!componentDef) {
|
|
7162
|
-
throw new RuntimeError(906 /* RuntimeErrorCode.MISSING_GENERATED_DEF */, `The ${stringifyForError(type)} is not an Angular component, ` +
|
|
7163
|
-
`make sure it has the \`@Component\` decorator.`);
|
|
7164
|
-
}
|
|
7165
|
-
if (!componentDef.standalone) {
|
|
7166
|
-
throw new RuntimeError(907 /* RuntimeErrorCode.TYPE_IS_NOT_STANDALONE */, `The ${stringifyForError(type)} component is not marked as standalone, ` +
|
|
7167
|
-
`but Angular expects to have a standalone component here. ` +
|
|
7168
|
-
`Please make sure the ${stringifyForError(type)} component has ` +
|
|
7169
|
-
`the \`standalone: true\` flag in the decorator.`);
|
|
7170
|
-
}
|
|
7171
|
-
}
|
|
7172
|
-
/** Called when there are multiple component selectors that match a given node */
|
|
7173
|
-
function throwMultipleComponentError(tNode, first, second) {
|
|
7174
|
-
throw new RuntimeError(-300 /* RuntimeErrorCode.MULTIPLE_COMPONENTS_MATCH */, `Multiple components match node with tagname ${tNode.value}: ` +
|
|
7175
|
-
`${stringifyForError(first)} and ` +
|
|
7176
|
-
`${stringifyForError(second)}`);
|
|
7177
|
-
}
|
|
7178
|
-
/** Throws an ExpressionChangedAfterChecked error if checkNoChanges mode is on. */
|
|
7179
|
-
function throwErrorIfNoChangesMode(creationMode, oldValue, currValue, propName) {
|
|
7180
|
-
const field = propName ? ` for '${propName}'` : '';
|
|
7181
|
-
let msg = `ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value${field}: '${oldValue}'. Current value: '${currValue}'.`;
|
|
7182
|
-
if (creationMode) {
|
|
7183
|
-
msg +=
|
|
7184
|
-
` It seems like the view has been created after its parent and its children have been dirty checked.` +
|
|
7185
|
-
` Has it been created in a change detection hook?`;
|
|
7186
|
-
}
|
|
7187
|
-
throw new RuntimeError(-100 /* RuntimeErrorCode.EXPRESSION_CHANGED_AFTER_CHECKED */, msg);
|
|
7188
|
-
}
|
|
7189
|
-
function constructDetailsForInterpolation(lView, rootIndex, expressionIndex, meta, changedValue) {
|
|
7190
|
-
const [propName, prefix, ...chunks] = meta.split(INTERPOLATION_DELIMITER);
|
|
7191
|
-
let oldValue = prefix, newValue = prefix;
|
|
7192
|
-
for (let i = 0; i < chunks.length; i++) {
|
|
7193
|
-
const slotIdx = rootIndex + i;
|
|
7194
|
-
oldValue += `${lView[slotIdx]}${chunks[i]}`;
|
|
7195
|
-
newValue += `${slotIdx === expressionIndex ? changedValue : lView[slotIdx]}${chunks[i]}`;
|
|
7196
|
-
}
|
|
7197
|
-
return { propName, oldValue, newValue };
|
|
7198
|
-
}
|
|
7199
|
-
/**
|
|
7200
|
-
* Constructs an object that contains details for the ExpressionChangedAfterItHasBeenCheckedError:
|
|
7201
|
-
* - property name (for property bindings or interpolations)
|
|
7202
|
-
* - old and new values, enriched using information from metadata
|
|
7203
|
-
*
|
|
7204
|
-
* More information on the metadata storage format can be found in `storePropertyBindingMetadata`
|
|
7205
|
-
* function description.
|
|
7206
|
-
*/
|
|
7207
|
-
function getExpressionChangedErrorDetails(lView, bindingIndex, oldValue, newValue) {
|
|
7208
|
-
const tData = lView[TVIEW].data;
|
|
7209
|
-
const metadata = tData[bindingIndex];
|
|
7210
|
-
if (typeof metadata === 'string') {
|
|
7211
|
-
// metadata for property interpolation
|
|
7212
|
-
if (metadata.indexOf(INTERPOLATION_DELIMITER) > -1) {
|
|
7213
|
-
return constructDetailsForInterpolation(lView, bindingIndex, bindingIndex, metadata, newValue);
|
|
7214
|
-
}
|
|
7215
|
-
// metadata for property binding
|
|
7216
|
-
return { propName: metadata, oldValue, newValue };
|
|
7217
|
-
}
|
|
7218
|
-
// metadata is not available for this expression, check if this expression is a part of the
|
|
7219
|
-
// property interpolation by going from the current binding index left and look for a string that
|
|
7220
|
-
// contains INTERPOLATION_DELIMITER, the layout in tView.data for this case will look like this:
|
|
7221
|
-
// [..., 'id�Prefix � and � suffix', null, null, null, ...]
|
|
7222
|
-
if (metadata === null) {
|
|
7223
|
-
let idx = bindingIndex - 1;
|
|
7224
|
-
while (typeof tData[idx] !== 'string' && tData[idx + 1] === null) {
|
|
7225
|
-
idx--;
|
|
7226
|
-
}
|
|
7227
|
-
const meta = tData[idx];
|
|
7228
|
-
if (typeof meta === 'string') {
|
|
7229
|
-
const matches = meta.match(new RegExp(INTERPOLATION_DELIMITER, 'g'));
|
|
7230
|
-
// first interpolation delimiter separates property name from interpolation parts (in case of
|
|
7231
|
-
// property interpolations), so we subtract one from total number of found delimiters
|
|
7232
|
-
if (matches && (matches.length - 1) > bindingIndex - idx) {
|
|
7233
|
-
return constructDetailsForInterpolation(lView, idx, bindingIndex, meta, newValue);
|
|
7234
|
-
}
|
|
7235
|
-
}
|
|
7236
|
-
}
|
|
7237
|
-
return { propName: undefined, oldValue, newValue };
|
|
7201
|
+
/**
|
|
7202
|
+
* Constructs an object that contains details for the ExpressionChangedAfterItHasBeenCheckedError:
|
|
7203
|
+
* - property name (for property bindings or interpolations)
|
|
7204
|
+
* - old and new values, enriched using information from metadata
|
|
7205
|
+
*
|
|
7206
|
+
* More information on the metadata storage format can be found in `storePropertyBindingMetadata`
|
|
7207
|
+
* function description.
|
|
7208
|
+
*/
|
|
7209
|
+
function getExpressionChangedErrorDetails(lView, bindingIndex, oldValue, newValue) {
|
|
7210
|
+
const tData = lView[TVIEW].data;
|
|
7211
|
+
const metadata = tData[bindingIndex];
|
|
7212
|
+
if (typeof metadata === 'string') {
|
|
7213
|
+
// metadata for property interpolation
|
|
7214
|
+
if (metadata.indexOf(INTERPOLATION_DELIMITER) > -1) {
|
|
7215
|
+
return constructDetailsForInterpolation(lView, bindingIndex, bindingIndex, metadata, newValue);
|
|
7216
|
+
}
|
|
7217
|
+
// metadata for property binding
|
|
7218
|
+
return { propName: metadata, oldValue, newValue };
|
|
7219
|
+
}
|
|
7220
|
+
// metadata is not available for this expression, check if this expression is a part of the
|
|
7221
|
+
// property interpolation by going from the current binding index left and look for a string that
|
|
7222
|
+
// contains INTERPOLATION_DELIMITER, the layout in tView.data for this case will look like this:
|
|
7223
|
+
// [..., 'id�Prefix � and � suffix', null, null, null, ...]
|
|
7224
|
+
if (metadata === null) {
|
|
7225
|
+
let idx = bindingIndex - 1;
|
|
7226
|
+
while (typeof tData[idx] !== 'string' && tData[idx + 1] === null) {
|
|
7227
|
+
idx--;
|
|
7228
|
+
}
|
|
7229
|
+
const meta = tData[idx];
|
|
7230
|
+
if (typeof meta === 'string') {
|
|
7231
|
+
const matches = meta.match(new RegExp(INTERPOLATION_DELIMITER, 'g'));
|
|
7232
|
+
// first interpolation delimiter separates property name from interpolation parts (in case of
|
|
7233
|
+
// property interpolations), so we subtract one from total number of found delimiters
|
|
7234
|
+
if (matches && (matches.length - 1) > bindingIndex - idx) {
|
|
7235
|
+
return constructDetailsForInterpolation(lView, idx, bindingIndex, meta, newValue);
|
|
7236
|
+
}
|
|
7237
|
+
}
|
|
7238
|
+
}
|
|
7239
|
+
return { propName: undefined, oldValue, newValue };
|
|
7238
7240
|
}
|
|
7239
7241
|
|
|
7240
7242
|
/**
|
|
@@ -9131,8 +9133,38 @@ const INJECTOR_DEF_TYPES = new InjectionToken('INJECTOR_DEF_TYPES');
|
|
|
9131
9133
|
* another environment injector (such as a route injector). They should not be used in component
|
|
9132
9134
|
* providers.
|
|
9133
9135
|
*
|
|
9134
|
-
*
|
|
9136
|
+
* More information about standalone components can be found in [this
|
|
9137
|
+
* guide](guide/standalone-components).
|
|
9138
|
+
*
|
|
9139
|
+
* @usageNotes
|
|
9140
|
+
* The results of the `importProvidersFrom` call can be used in the `bootstrapApplication` call:
|
|
9141
|
+
*
|
|
9142
|
+
* ```typescript
|
|
9143
|
+
* await bootstrapApplication(RootComponent, {
|
|
9144
|
+
* providers: [
|
|
9145
|
+
* importProvidersFrom(NgModuleOne, NgModuleTwo)
|
|
9146
|
+
* ]
|
|
9147
|
+
* });
|
|
9148
|
+
* ```
|
|
9149
|
+
*
|
|
9150
|
+
* You can also use the `importProvidersFrom` results in the `providers` field of a route, when a
|
|
9151
|
+
* standalone component is used:
|
|
9152
|
+
*
|
|
9153
|
+
* ```typescript
|
|
9154
|
+
* export const ROUTES: Route[] = [
|
|
9155
|
+
* {
|
|
9156
|
+
* path: 'foo',
|
|
9157
|
+
* providers: [
|
|
9158
|
+
* importProvidersFrom(NgModuleOne, NgModuleTwo)
|
|
9159
|
+
* ],
|
|
9160
|
+
* component: YourStandaloneComponent
|
|
9161
|
+
* }
|
|
9162
|
+
* ];
|
|
9163
|
+
* ```
|
|
9164
|
+
*
|
|
9165
|
+
* @returns Collected providers from the specified list of types.
|
|
9135
9166
|
* @publicApi
|
|
9167
|
+
* @developerPreview
|
|
9136
9168
|
*/
|
|
9137
9169
|
function importProvidersFrom(...sources) {
|
|
9138
9170
|
return { ɵproviders: internalImportProvidersFrom(true, sources) };
|
|
@@ -9410,6 +9442,8 @@ function getNullInjector() {
|
|
|
9410
9442
|
/**
|
|
9411
9443
|
* An `Injector` that's part of the environment injector hierarchy, which exists outside of the
|
|
9412
9444
|
* component tree.
|
|
9445
|
+
*
|
|
9446
|
+
* @developerPreview
|
|
9413
9447
|
*/
|
|
9414
9448
|
class EnvironmentInjector {
|
|
9415
9449
|
}
|
|
@@ -10627,66 +10661,355 @@ class ReflectiveInjector_ {
|
|
|
10627
10661
|
toString() {
|
|
10628
10662
|
return this.displayName;
|
|
10629
10663
|
}
|
|
10630
|
-
}
|
|
10631
|
-
ReflectiveInjector_.INJECTOR_KEY = ( /* @__PURE__ */ReflectiveKey.get(Injector));
|
|
10632
|
-
function _mapProviders(injector, fn) {
|
|
10633
|
-
const res = [];
|
|
10634
|
-
for (let i = 0; i < injector._providers.length; ++i) {
|
|
10635
|
-
res[i] = fn(injector.getProviderAtIndex(i));
|
|
10664
|
+
}
|
|
10665
|
+
ReflectiveInjector_.INJECTOR_KEY = ( /* @__PURE__ */ReflectiveKey.get(Injector));
|
|
10666
|
+
function _mapProviders(injector, fn) {
|
|
10667
|
+
const res = [];
|
|
10668
|
+
for (let i = 0; i < injector._providers.length; ++i) {
|
|
10669
|
+
res[i] = fn(injector.getProviderAtIndex(i));
|
|
10670
|
+
}
|
|
10671
|
+
return res;
|
|
10672
|
+
}
|
|
10673
|
+
|
|
10674
|
+
/**
|
|
10675
|
+
* @license
|
|
10676
|
+
* Copyright Google LLC All Rights Reserved.
|
|
10677
|
+
*
|
|
10678
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
10679
|
+
* found in the LICENSE file at https://angular.io/license
|
|
10680
|
+
*/
|
|
10681
|
+
|
|
10682
|
+
/**
|
|
10683
|
+
* @license
|
|
10684
|
+
* Copyright Google LLC All Rights Reserved.
|
|
10685
|
+
*
|
|
10686
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
10687
|
+
* found in the LICENSE file at https://angular.io/license
|
|
10688
|
+
*/
|
|
10689
|
+
|
|
10690
|
+
/**
|
|
10691
|
+
* @license
|
|
10692
|
+
* Copyright Google LLC All Rights Reserved.
|
|
10693
|
+
*
|
|
10694
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
10695
|
+
* found in the LICENSE file at https://angular.io/license
|
|
10696
|
+
*/
|
|
10697
|
+
function ɵɵdirectiveInject(token, flags = InjectFlags.Default) {
|
|
10698
|
+
const lView = getLView();
|
|
10699
|
+
// Fall back to inject() if view hasn't been created. This situation can happen in tests
|
|
10700
|
+
// if inject utilities are used before bootstrapping.
|
|
10701
|
+
if (lView === null) {
|
|
10702
|
+
// Verify that we will not get into infinite loop.
|
|
10703
|
+
ngDevMode && assertInjectImplementationNotEqual(ɵɵdirectiveInject);
|
|
10704
|
+
return ɵɵinject(token, flags);
|
|
10705
|
+
}
|
|
10706
|
+
const tNode = getCurrentTNode();
|
|
10707
|
+
return getOrCreateInjectable(tNode, lView, resolveForwardRef(token), flags);
|
|
10708
|
+
}
|
|
10709
|
+
/**
|
|
10710
|
+
* Throws an error indicating that a factory function could not be generated by the compiler for a
|
|
10711
|
+
* particular class.
|
|
10712
|
+
*
|
|
10713
|
+
* This instruction allows the actual error message to be optimized away when ngDevMode is turned
|
|
10714
|
+
* off, saving bytes of generated code while still providing a good experience in dev mode.
|
|
10715
|
+
*
|
|
10716
|
+
* The name of the class is not mentioned here, but will be in the generated factory function name
|
|
10717
|
+
* and thus in the stack trace.
|
|
10718
|
+
*
|
|
10719
|
+
* @codeGenApi
|
|
10720
|
+
*/
|
|
10721
|
+
function ɵɵinvalidFactory() {
|
|
10722
|
+
const msg = ngDevMode ? `This constructor was not compatible with Dependency Injection.` : 'invalid';
|
|
10723
|
+
throw new Error(msg);
|
|
10724
|
+
}
|
|
10725
|
+
|
|
10726
|
+
/**
|
|
10727
|
+
* @license
|
|
10728
|
+
* Copyright Google LLC All Rights Reserved.
|
|
10729
|
+
*
|
|
10730
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
10731
|
+
* found in the LICENSE file at https://angular.io/license
|
|
10732
|
+
*/
|
|
10733
|
+
/**
|
|
10734
|
+
* Defines a schema that allows an NgModule to contain the following:
|
|
10735
|
+
* - Non-Angular elements named with dash case (`-`).
|
|
10736
|
+
* - Element properties named with dash case (`-`).
|
|
10737
|
+
* Dash case is the naming convention for custom elements.
|
|
10738
|
+
*
|
|
10739
|
+
* @publicApi
|
|
10740
|
+
*/
|
|
10741
|
+
const CUSTOM_ELEMENTS_SCHEMA = {
|
|
10742
|
+
name: 'custom-elements'
|
|
10743
|
+
};
|
|
10744
|
+
/**
|
|
10745
|
+
* Defines a schema that allows any property on any element.
|
|
10746
|
+
*
|
|
10747
|
+
* This schema allows you to ignore the errors related to any unknown elements or properties in a
|
|
10748
|
+
* template. The usage of this schema is generally discouraged because it prevents useful validation
|
|
10749
|
+
* and may hide real errors in your template. Consider using the `CUSTOM_ELEMENTS_SCHEMA` instead.
|
|
10750
|
+
*
|
|
10751
|
+
* @publicApi
|
|
10752
|
+
*/
|
|
10753
|
+
const NO_ERRORS_SCHEMA = {
|
|
10754
|
+
name: 'no-errors-schema'
|
|
10755
|
+
};
|
|
10756
|
+
|
|
10757
|
+
/**
|
|
10758
|
+
* @license
|
|
10759
|
+
* Copyright Google LLC All Rights Reserved.
|
|
10760
|
+
*
|
|
10761
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
10762
|
+
* found in the LICENSE file at https://angular.io/license
|
|
10763
|
+
*/
|
|
10764
|
+
let shouldThrowErrorOnUnknownElement = false;
|
|
10765
|
+
/**
|
|
10766
|
+
* Sets a strict mode for JIT-compiled components to throw an error on unknown elements,
|
|
10767
|
+
* instead of just logging the error.
|
|
10768
|
+
* (for AOT-compiled ones this check happens at build time).
|
|
10769
|
+
*/
|
|
10770
|
+
function ɵsetUnknownElementStrictMode(shouldThrow) {
|
|
10771
|
+
shouldThrowErrorOnUnknownElement = shouldThrow;
|
|
10772
|
+
}
|
|
10773
|
+
/**
|
|
10774
|
+
* Gets the current value of the strict mode.
|
|
10775
|
+
*/
|
|
10776
|
+
function ɵgetUnknownElementStrictMode() {
|
|
10777
|
+
return shouldThrowErrorOnUnknownElement;
|
|
10778
|
+
}
|
|
10779
|
+
let shouldThrowErrorOnUnknownProperty = false;
|
|
10780
|
+
/**
|
|
10781
|
+
* Sets a strict mode for JIT-compiled components to throw an error on unknown properties,
|
|
10782
|
+
* instead of just logging the error.
|
|
10783
|
+
* (for AOT-compiled ones this check happens at build time).
|
|
10784
|
+
*/
|
|
10785
|
+
function ɵsetUnknownPropertyStrictMode(shouldThrow) {
|
|
10786
|
+
shouldThrowErrorOnUnknownProperty = shouldThrow;
|
|
10787
|
+
}
|
|
10788
|
+
/**
|
|
10789
|
+
* Gets the current value of the strict mode.
|
|
10790
|
+
*/
|
|
10791
|
+
function ɵgetUnknownPropertyStrictMode() {
|
|
10792
|
+
return shouldThrowErrorOnUnknownProperty;
|
|
10793
|
+
}
|
|
10794
|
+
/**
|
|
10795
|
+
* Validates that the element is known at runtime and produces
|
|
10796
|
+
* an error if it's not the case.
|
|
10797
|
+
* This check is relevant for JIT-compiled components (for AOT-compiled
|
|
10798
|
+
* ones this check happens at build time).
|
|
10799
|
+
*
|
|
10800
|
+
* The element is considered known if either:
|
|
10801
|
+
* - it's a known HTML element
|
|
10802
|
+
* - it's a known custom element
|
|
10803
|
+
* - the element matches any directive
|
|
10804
|
+
* - the element is allowed by one of the schemas
|
|
10805
|
+
*
|
|
10806
|
+
* @param element Element to validate
|
|
10807
|
+
* @param lView An `LView` that represents a current component that is being rendered
|
|
10808
|
+
* @param tagName Name of the tag to check
|
|
10809
|
+
* @param schemas Array of schemas
|
|
10810
|
+
* @param hasDirectives Boolean indicating that the element matches any directive
|
|
10811
|
+
*/
|
|
10812
|
+
function validateElementIsKnown(element, lView, tagName, schemas, hasDirectives) {
|
|
10813
|
+
// If `schemas` is set to `null`, that's an indication that this Component was compiled in AOT
|
|
10814
|
+
// mode where this check happens at compile time. In JIT mode, `schemas` is always present and
|
|
10815
|
+
// defined as an array (as an empty array in case `schemas` field is not defined) and we should
|
|
10816
|
+
// execute the check below.
|
|
10817
|
+
if (schemas === null)
|
|
10818
|
+
return;
|
|
10819
|
+
// If the element matches any directive, it's considered as valid.
|
|
10820
|
+
if (!hasDirectives && tagName !== null) {
|
|
10821
|
+
// The element is unknown if it's an instance of HTMLUnknownElement, or it isn't registered
|
|
10822
|
+
// as a custom element. Note that unknown elements with a dash in their name won't be instances
|
|
10823
|
+
// of HTMLUnknownElement in browsers that support web components.
|
|
10824
|
+
const isUnknown =
|
|
10825
|
+
// Note that we can't check for `typeof HTMLUnknownElement === 'function'`,
|
|
10826
|
+
// because while most browsers return 'function', IE returns 'object'.
|
|
10827
|
+
(typeof HTMLUnknownElement !== 'undefined' && HTMLUnknownElement &&
|
|
10828
|
+
element instanceof HTMLUnknownElement) ||
|
|
10829
|
+
(typeof customElements !== 'undefined' && tagName.indexOf('-') > -1 &&
|
|
10830
|
+
!customElements.get(tagName));
|
|
10831
|
+
if (isUnknown && !matchingSchemas(schemas, tagName)) {
|
|
10832
|
+
const isHostStandalone = isHostComponentStandalone(lView);
|
|
10833
|
+
const templateLocation = getTemplateLocationDetails(lView);
|
|
10834
|
+
const schemas = `'${isHostStandalone ? '@Component' : '@NgModule'}.schemas'`;
|
|
10835
|
+
let message = `'${tagName}' is not a known element${templateLocation}:\n`;
|
|
10836
|
+
message += `1. If '${tagName}' is an Angular component, then verify that it is ${isHostStandalone ? 'included in the \'@Component.imports\' of this component' :
|
|
10837
|
+
'a part of an @NgModule where this component is declared'}.\n`;
|
|
10838
|
+
if (tagName && tagName.indexOf('-') > -1) {
|
|
10839
|
+
message +=
|
|
10840
|
+
`2. If '${tagName}' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the ${schemas} of this component to suppress this message.`;
|
|
10841
|
+
}
|
|
10842
|
+
else {
|
|
10843
|
+
message +=
|
|
10844
|
+
`2. To allow any element add 'NO_ERRORS_SCHEMA' to the ${schemas} of this component.`;
|
|
10845
|
+
}
|
|
10846
|
+
if (shouldThrowErrorOnUnknownElement) {
|
|
10847
|
+
throw new RuntimeError(304 /* RuntimeErrorCode.UNKNOWN_ELEMENT */, message);
|
|
10848
|
+
}
|
|
10849
|
+
else {
|
|
10850
|
+
console.error(formatRuntimeError(304 /* RuntimeErrorCode.UNKNOWN_ELEMENT */, message));
|
|
10851
|
+
}
|
|
10852
|
+
}
|
|
10853
|
+
}
|
|
10854
|
+
}
|
|
10855
|
+
/**
|
|
10856
|
+
* Validates that the property of the element is known at runtime and returns
|
|
10857
|
+
* false if it's not the case.
|
|
10858
|
+
* This check is relevant for JIT-compiled components (for AOT-compiled
|
|
10859
|
+
* ones this check happens at build time).
|
|
10860
|
+
*
|
|
10861
|
+
* The property is considered known if either:
|
|
10862
|
+
* - it's a known property of the element
|
|
10863
|
+
* - the element is allowed by one of the schemas
|
|
10864
|
+
* - the property is used for animations
|
|
10865
|
+
*
|
|
10866
|
+
* @param element Element to validate
|
|
10867
|
+
* @param propName Name of the property to check
|
|
10868
|
+
* @param tagName Name of the tag hosting the property
|
|
10869
|
+
* @param schemas Array of schemas
|
|
10870
|
+
*/
|
|
10871
|
+
function isPropertyValid(element, propName, tagName, schemas) {
|
|
10872
|
+
// If `schemas` is set to `null`, that's an indication that this Component was compiled in AOT
|
|
10873
|
+
// mode where this check happens at compile time. In JIT mode, `schemas` is always present and
|
|
10874
|
+
// defined as an array (as an empty array in case `schemas` field is not defined) and we should
|
|
10875
|
+
// execute the check below.
|
|
10876
|
+
if (schemas === null)
|
|
10877
|
+
return true;
|
|
10878
|
+
// The property is considered valid if the element matches the schema, it exists on the element,
|
|
10879
|
+
// or it is synthetic, and we are in a browser context (web worker nodes should be skipped).
|
|
10880
|
+
if (matchingSchemas(schemas, tagName) || propName in element || isAnimationProp(propName)) {
|
|
10881
|
+
return true;
|
|
10882
|
+
}
|
|
10883
|
+
// Note: `typeof Node` returns 'function' in most browsers, but on IE it is 'object' so we
|
|
10884
|
+
// need to account for both here, while being careful with `typeof null` also returning 'object'.
|
|
10885
|
+
return typeof Node === 'undefined' || Node === null || !(element instanceof Node);
|
|
10886
|
+
}
|
|
10887
|
+
/**
|
|
10888
|
+
* Logs or throws an error that a property is not supported on an element.
|
|
10889
|
+
*
|
|
10890
|
+
* @param propName Name of the invalid property
|
|
10891
|
+
* @param tagName Name of the tag hosting the property
|
|
10892
|
+
* @param nodeType Type of the node hosting the property
|
|
10893
|
+
* @param lView An `LView` that represents a current component
|
|
10894
|
+
*/
|
|
10895
|
+
function handleUnknownPropertyError(propName, tagName, nodeType, lView) {
|
|
10896
|
+
// Special-case a situation when a structural directive is applied to
|
|
10897
|
+
// an `<ng-template>` element, for example: `<ng-template *ngIf="true">`.
|
|
10898
|
+
// In this case the compiler generates the `ɵɵtemplate` instruction with
|
|
10899
|
+
// the `null` as the tagName. The directive matching logic at runtime relies
|
|
10900
|
+
// on this effect (see `isInlineTemplate`), thus using the 'ng-template' as
|
|
10901
|
+
// a default value of the `tNode.value` is not feasible at this moment.
|
|
10902
|
+
if (!tagName && nodeType === 4 /* TNodeType.Container */) {
|
|
10903
|
+
tagName = 'ng-template';
|
|
10904
|
+
}
|
|
10905
|
+
const isHostStandalone = isHostComponentStandalone(lView);
|
|
10906
|
+
const templateLocation = getTemplateLocationDetails(lView);
|
|
10907
|
+
let message = `Can't bind to '${propName}' since it isn't a known property of '${tagName}'${templateLocation}.`;
|
|
10908
|
+
const schemas = `'${isHostStandalone ? '@Component' : '@NgModule'}.schemas'`;
|
|
10909
|
+
const importLocation = isHostStandalone ?
|
|
10910
|
+
'included in the \'@Component.imports\' of this component' :
|
|
10911
|
+
'a part of an @NgModule where this component is declared';
|
|
10912
|
+
if (KNOWN_CONTROL_FLOW_DIRECTIVES.has(propName)) {
|
|
10913
|
+
// Most likely this is a control flow directive (such as `*ngIf`) used in
|
|
10914
|
+
// a template, but the `CommonModule` is not imported.
|
|
10915
|
+
message += `\nIf the '${propName}' is an Angular control flow directive, ` +
|
|
10916
|
+
`please make sure that the 'CommonModule' is ${importLocation}.`;
|
|
10917
|
+
}
|
|
10918
|
+
else {
|
|
10919
|
+
// May be an Angular component, which is not imported/declared?
|
|
10920
|
+
message += `\n1. If '${tagName}' is an Angular component and it has the ` +
|
|
10921
|
+
`'${propName}' input, then verify that it is ${importLocation}.`;
|
|
10922
|
+
// May be a Web Component?
|
|
10923
|
+
if (tagName && tagName.indexOf('-') > -1) {
|
|
10924
|
+
message += `\n2. If '${tagName}' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' ` +
|
|
10925
|
+
`to the ${schemas} of this component to suppress this message.`;
|
|
10926
|
+
message += `\n3. To allow any property add 'NO_ERRORS_SCHEMA' to ` +
|
|
10927
|
+
`the ${schemas} of this component.`;
|
|
10928
|
+
}
|
|
10929
|
+
else {
|
|
10930
|
+
// If it's expected, the error can be suppressed by the `NO_ERRORS_SCHEMA` schema.
|
|
10931
|
+
message += `\n2. To allow any property add 'NO_ERRORS_SCHEMA' to ` +
|
|
10932
|
+
`the ${schemas} of this component.`;
|
|
10933
|
+
}
|
|
10934
|
+
}
|
|
10935
|
+
if (shouldThrowErrorOnUnknownProperty) {
|
|
10936
|
+
throw new RuntimeError(303 /* RuntimeErrorCode.UNKNOWN_BINDING */, message);
|
|
10937
|
+
}
|
|
10938
|
+
else {
|
|
10939
|
+
console.error(formatRuntimeError(303 /* RuntimeErrorCode.UNKNOWN_BINDING */, message));
|
|
10636
10940
|
}
|
|
10637
|
-
return res;
|
|
10638
10941
|
}
|
|
10639
|
-
|
|
10640
10942
|
/**
|
|
10641
|
-
*
|
|
10642
|
-
*
|
|
10943
|
+
* WARNING: this is a **dev-mode only** function (thus should always be guarded by the `ngDevMode`)
|
|
10944
|
+
* and must **not** be used in production bundles. The function makes megamorphic reads, which might
|
|
10945
|
+
* be too slow for production mode and also it relies on the constructor function being available.
|
|
10643
10946
|
*
|
|
10644
|
-
*
|
|
10645
|
-
* found in the LICENSE file at https://angular.io/license
|
|
10646
|
-
*/
|
|
10647
|
-
|
|
10648
|
-
/**
|
|
10649
|
-
* @license
|
|
10650
|
-
* Copyright Google LLC All Rights Reserved.
|
|
10947
|
+
* Gets a reference to the host component def (where a current component is declared).
|
|
10651
10948
|
*
|
|
10652
|
-
*
|
|
10653
|
-
* found in the LICENSE file at https://angular.io/license
|
|
10949
|
+
* @param lView An `LView` that represents a current component that is being rendered.
|
|
10654
10950
|
*/
|
|
10655
|
-
|
|
10951
|
+
function getDeclarationComponentDef(lView) {
|
|
10952
|
+
!ngDevMode && throwError('Must never be called in production mode');
|
|
10953
|
+
const declarationLView = lView[DECLARATION_COMPONENT_VIEW];
|
|
10954
|
+
const context = declarationLView[CONTEXT];
|
|
10955
|
+
// Unable to obtain a context.
|
|
10956
|
+
if (!context)
|
|
10957
|
+
return null;
|
|
10958
|
+
return context.constructor ? getComponentDef$1(context.constructor) : null;
|
|
10959
|
+
}
|
|
10656
10960
|
/**
|
|
10657
|
-
*
|
|
10658
|
-
*
|
|
10961
|
+
* WARNING: this is a **dev-mode only** function (thus should always be guarded by the `ngDevMode`)
|
|
10962
|
+
* and must **not** be used in production bundles. The function makes megamorphic reads, which might
|
|
10963
|
+
* be too slow for production mode.
|
|
10659
10964
|
*
|
|
10660
|
-
*
|
|
10661
|
-
*
|
|
10965
|
+
* Checks if the current component is declared inside of a standalone component template.
|
|
10966
|
+
*
|
|
10967
|
+
* @param lView An `LView` that represents a current component that is being rendered.
|
|
10662
10968
|
*/
|
|
10663
|
-
function
|
|
10664
|
-
|
|
10665
|
-
|
|
10666
|
-
// if
|
|
10667
|
-
|
|
10668
|
-
// Verify that we will not get into infinite loop.
|
|
10669
|
-
ngDevMode && assertInjectImplementationNotEqual(ɵɵdirectiveInject);
|
|
10670
|
-
return ɵɵinject(token, flags);
|
|
10671
|
-
}
|
|
10672
|
-
const tNode = getCurrentTNode();
|
|
10673
|
-
return getOrCreateInjectable(tNode, lView, resolveForwardRef(token), flags);
|
|
10969
|
+
function isHostComponentStandalone(lView) {
|
|
10970
|
+
!ngDevMode && throwError('Must never be called in production mode');
|
|
10971
|
+
const componentDef = getDeclarationComponentDef(lView);
|
|
10972
|
+
// Treat host component as non-standalone if we can't obtain the def.
|
|
10973
|
+
return !!componentDef?.standalone;
|
|
10674
10974
|
}
|
|
10675
10975
|
/**
|
|
10676
|
-
*
|
|
10677
|
-
*
|
|
10678
|
-
*
|
|
10679
|
-
* This instruction allows the actual error message to be optimized away when ngDevMode is turned
|
|
10680
|
-
* off, saving bytes of generated code while still providing a good experience in dev mode.
|
|
10976
|
+
* WARNING: this is a **dev-mode only** function (thus should always be guarded by the `ngDevMode`)
|
|
10977
|
+
* and must **not** be used in production bundles. The function makes megamorphic reads, which might
|
|
10978
|
+
* be too slow for production mode.
|
|
10681
10979
|
*
|
|
10682
|
-
*
|
|
10683
|
-
*
|
|
10980
|
+
* Constructs a string describing the location of the host component template. The function is used
|
|
10981
|
+
* in dev mode to produce error messages.
|
|
10684
10982
|
*
|
|
10685
|
-
* @
|
|
10983
|
+
* @param lView An `LView` that represents a current component that is being rendered.
|
|
10686
10984
|
*/
|
|
10687
|
-
function
|
|
10688
|
-
|
|
10689
|
-
|
|
10985
|
+
function getTemplateLocationDetails(lView) {
|
|
10986
|
+
!ngDevMode && throwError('Must never be called in production mode');
|
|
10987
|
+
const hostComponentDef = getDeclarationComponentDef(lView);
|
|
10988
|
+
const componentClassName = hostComponentDef?.type?.name;
|
|
10989
|
+
return componentClassName ? ` (used in the '${componentClassName}' component template)` : '';
|
|
10990
|
+
}
|
|
10991
|
+
/**
|
|
10992
|
+
* The set of known control flow directives.
|
|
10993
|
+
* We use this set to produce a more precises error message with a note
|
|
10994
|
+
* that the `CommonModule` should also be included.
|
|
10995
|
+
*/
|
|
10996
|
+
const KNOWN_CONTROL_FLOW_DIRECTIVES = new Set(['ngIf', 'ngFor', 'ngSwitch', 'ngSwitchCase', 'ngSwitchDefault']);
|
|
10997
|
+
/**
|
|
10998
|
+
* Returns true if the tag name is allowed by specified schemas.
|
|
10999
|
+
* @param schemas Array of schemas
|
|
11000
|
+
* @param tagName Name of the tag
|
|
11001
|
+
*/
|
|
11002
|
+
function matchingSchemas(schemas, tagName) {
|
|
11003
|
+
if (schemas !== null) {
|
|
11004
|
+
for (let i = 0; i < schemas.length; i++) {
|
|
11005
|
+
const schema = schemas[i];
|
|
11006
|
+
if (schema === NO_ERRORS_SCHEMA ||
|
|
11007
|
+
schema === CUSTOM_ELEMENTS_SCHEMA && tagName && tagName.indexOf('-') > -1) {
|
|
11008
|
+
return true;
|
|
11009
|
+
}
|
|
11010
|
+
}
|
|
11011
|
+
}
|
|
11012
|
+
return false;
|
|
10690
11013
|
}
|
|
10691
11014
|
|
|
10692
11015
|
/**
|
|
@@ -11495,21 +11818,6 @@ class LContainerDebug {
|
|
|
11495
11818
|
}
|
|
11496
11819
|
}
|
|
11497
11820
|
|
|
11498
|
-
let shouldThrowErrorOnUnknownProperty = false;
|
|
11499
|
-
/**
|
|
11500
|
-
* Sets a strict mode for JIT-compiled components to throw an error on unknown properties,
|
|
11501
|
-
* instead of just logging the error.
|
|
11502
|
-
* (for AOT-compiled ones this check happens at build time).
|
|
11503
|
-
*/
|
|
11504
|
-
function ɵsetUnknownPropertyStrictMode(shouldThrow) {
|
|
11505
|
-
shouldThrowErrorOnUnknownProperty = shouldThrow;
|
|
11506
|
-
}
|
|
11507
|
-
/**
|
|
11508
|
-
* Gets the current value of the strict mode.
|
|
11509
|
-
*/
|
|
11510
|
-
function ɵgetUnknownPropertyStrictMode() {
|
|
11511
|
-
return shouldThrowErrorOnUnknownProperty;
|
|
11512
|
-
}
|
|
11513
11821
|
/**
|
|
11514
11822
|
* A permanent marker promise which signifies that the current CD tree is
|
|
11515
11823
|
* clean.
|
|
@@ -11668,21 +11976,6 @@ function createTNodeAtIndex(tView, index, type, name, attrs) {
|
|
|
11668
11976
|
}
|
|
11669
11977
|
return tNode;
|
|
11670
11978
|
}
|
|
11671
|
-
/**
|
|
11672
|
-
* Checks if the current component is declared inside of a standalone component template.
|
|
11673
|
-
*
|
|
11674
|
-
* @param lView An `LView` that represents a current component that is being rendered.
|
|
11675
|
-
*/
|
|
11676
|
-
function isHostComponentStandalone(lView) {
|
|
11677
|
-
!ngDevMode && throwError('Must never be called in production mode');
|
|
11678
|
-
const declarationLView = lView[DECLARATION_COMPONENT_VIEW];
|
|
11679
|
-
const context = declarationLView[CONTEXT];
|
|
11680
|
-
// Unable to obtain a context, fall back to the non-standalone scenario.
|
|
11681
|
-
if (!context)
|
|
11682
|
-
return false;
|
|
11683
|
-
const componentDef = getComponentDef$1(context.constructor);
|
|
11684
|
-
return !!(componentDef?.standalone);
|
|
11685
|
-
}
|
|
11686
11979
|
/**
|
|
11687
11980
|
* When elements are created dynamically after a view blueprint is created (e.g. through
|
|
11688
11981
|
* i18nApply()), we need to adjust the blueprint for future
|
|
@@ -12349,10 +12642,8 @@ function elementPropertyInternal(tView, tNode, lView, propName, value, renderer,
|
|
|
12349
12642
|
propName = mapPropName(propName);
|
|
12350
12643
|
if (ngDevMode) {
|
|
12351
12644
|
validateAgainstEventProperties(propName);
|
|
12352
|
-
if (!
|
|
12353
|
-
|
|
12354
|
-
handleUnknownPropertyError(propName, tNode);
|
|
12355
|
-
return;
|
|
12645
|
+
if (!isPropertyValid(element, propName, tNode.value, tView.schemas)) {
|
|
12646
|
+
handleUnknownPropertyError(propName, tNode.value, tNode.type, lView);
|
|
12356
12647
|
}
|
|
12357
12648
|
ngDevMode.rendererSetProperty++;
|
|
12358
12649
|
}
|
|
@@ -12371,7 +12662,7 @@ function elementPropertyInternal(tView, tNode, lView, propName, value, renderer,
|
|
|
12371
12662
|
// If the node is a container and the property didn't
|
|
12372
12663
|
// match any of the inputs or schemas we should throw.
|
|
12373
12664
|
if (ngDevMode && !matchingSchemas(tView.schemas, tNode.value)) {
|
|
12374
|
-
handleUnknownPropertyError(propName, tNode);
|
|
12665
|
+
handleUnknownPropertyError(propName, tNode.value, tNode.type, lView);
|
|
12375
12666
|
}
|
|
12376
12667
|
}
|
|
12377
12668
|
}
|
|
@@ -12423,79 +12714,6 @@ function setNgReflectProperties(lView, element, type, dataValue, value) {
|
|
|
12423
12714
|
}
|
|
12424
12715
|
}
|
|
12425
12716
|
}
|
|
12426
|
-
/**
|
|
12427
|
-
* Validates that the property of the element is known at runtime and returns
|
|
12428
|
-
* false if it's not the case.
|
|
12429
|
-
* This check is relevant for JIT-compiled components (for AOT-compiled
|
|
12430
|
-
* ones this check happens at build time).
|
|
12431
|
-
*
|
|
12432
|
-
* The property is considered known if either:
|
|
12433
|
-
* - it's a known property of the element
|
|
12434
|
-
* - the element is allowed by one of the schemas
|
|
12435
|
-
* - the property is used for animations
|
|
12436
|
-
*
|
|
12437
|
-
* @param element Element to validate
|
|
12438
|
-
* @param tagName Name of the tag to check
|
|
12439
|
-
* @param propName Name of the property to check
|
|
12440
|
-
* @param schemas Array of schemas
|
|
12441
|
-
*/
|
|
12442
|
-
function validateProperty(element, tagName, propName, schemas) {
|
|
12443
|
-
// If `schemas` is set to `null`, that's an indication that this Component was compiled in AOT
|
|
12444
|
-
// mode where this check happens at compile time. In JIT mode, `schemas` is always present and
|
|
12445
|
-
// defined as an array (as an empty array in case `schemas` field is not defined) and we should
|
|
12446
|
-
// execute the check below.
|
|
12447
|
-
if (schemas === null)
|
|
12448
|
-
return true;
|
|
12449
|
-
// The property is considered valid if the element matches the schema, it exists on the element,
|
|
12450
|
-
// or it is synthetic, and we are in a browser context (web worker nodes should be skipped).
|
|
12451
|
-
if (matchingSchemas(schemas, tagName) || propName in element || isAnimationProp(propName)) {
|
|
12452
|
-
return true;
|
|
12453
|
-
}
|
|
12454
|
-
// Note: `typeof Node` returns 'function' in most browsers, but on IE it is 'object' so we
|
|
12455
|
-
// need to account for both here, while being careful with `typeof null` also returning 'object'.
|
|
12456
|
-
return typeof Node === 'undefined' || Node === null || !(element instanceof Node);
|
|
12457
|
-
}
|
|
12458
|
-
/**
|
|
12459
|
-
* Returns true if the tag name is allowed by specified schemas.
|
|
12460
|
-
* @param schemas Array of schemas
|
|
12461
|
-
* @param tagName Name of the tag
|
|
12462
|
-
*/
|
|
12463
|
-
function matchingSchemas(schemas, tagName) {
|
|
12464
|
-
if (schemas !== null) {
|
|
12465
|
-
for (let i = 0; i < schemas.length; i++) {
|
|
12466
|
-
const schema = schemas[i];
|
|
12467
|
-
if (schema === NO_ERRORS_SCHEMA ||
|
|
12468
|
-
schema === CUSTOM_ELEMENTS_SCHEMA && tagName && tagName.indexOf('-') > -1) {
|
|
12469
|
-
return true;
|
|
12470
|
-
}
|
|
12471
|
-
}
|
|
12472
|
-
}
|
|
12473
|
-
return false;
|
|
12474
|
-
}
|
|
12475
|
-
/**
|
|
12476
|
-
* Logs or throws an error that a property is not supported on an element.
|
|
12477
|
-
* @param propName Name of the invalid property.
|
|
12478
|
-
* @param tagName Name of the node on which we encountered the property.
|
|
12479
|
-
*/
|
|
12480
|
-
function handleUnknownPropertyError(propName, tNode) {
|
|
12481
|
-
let tagName = tNode.value;
|
|
12482
|
-
// Special-case a situation when a structural directive is applied to
|
|
12483
|
-
// an `<ng-template>` element, for example: `<ng-template *ngIf="true">`.
|
|
12484
|
-
// In this case the compiler generates the `ɵɵtemplate` instruction with
|
|
12485
|
-
// the `null` as the tagName. The directive matching logic at runtime relies
|
|
12486
|
-
// on this effect (see `isInlineTemplate`), thus using the 'ng-template' as
|
|
12487
|
-
// a default value of the `tNode.value` is not feasible at this moment.
|
|
12488
|
-
if (!tagName && tNode.type === 4 /* TNodeType.Container */) {
|
|
12489
|
-
tagName = 'ng-template';
|
|
12490
|
-
}
|
|
12491
|
-
const message = `Can't bind to '${propName}' since it isn't a known property of '${tagName}'.`;
|
|
12492
|
-
if (shouldThrowErrorOnUnknownProperty) {
|
|
12493
|
-
throw new RuntimeError(303 /* RuntimeErrorCode.UNKNOWN_BINDING */, message);
|
|
12494
|
-
}
|
|
12495
|
-
else {
|
|
12496
|
-
console.error(formatRuntimeError(303 /* RuntimeErrorCode.UNKNOWN_BINDING */, message));
|
|
12497
|
-
}
|
|
12498
|
-
}
|
|
12499
12717
|
/**
|
|
12500
12718
|
* Instantiate a root component.
|
|
12501
12719
|
*/
|
|
@@ -14069,7 +14287,11 @@ function createRootComponent(componentView, componentDef, rootLView, rootContext
|
|
|
14069
14287
|
const component = instantiateRootComponent(tView, rootLView, componentDef);
|
|
14070
14288
|
rootContext.components.push(component);
|
|
14071
14289
|
componentView[CONTEXT] = component;
|
|
14072
|
-
hostFeatures
|
|
14290
|
+
if (hostFeatures !== null) {
|
|
14291
|
+
for (const feature of hostFeatures) {
|
|
14292
|
+
feature(component, componentDef);
|
|
14293
|
+
}
|
|
14294
|
+
}
|
|
14073
14295
|
// We want to generate an empty QueryList for root content queries for backwards
|
|
14074
14296
|
// compatibility with ViewEngine.
|
|
14075
14297
|
if (componentDef.contentQueries) {
|
|
@@ -14110,13 +14332,10 @@ function createRootContext(scheduler, playerHandler) {
|
|
|
14110
14332
|
* renderComponent(AppComponent, {hostFeatures: [LifecycleHooksFeature]});
|
|
14111
14333
|
* ```
|
|
14112
14334
|
*/
|
|
14113
|
-
function LifecycleHooksFeature(
|
|
14114
|
-
const lView = readPatchedLView(component);
|
|
14115
|
-
ngDevMode && assertDefined(lView, 'LView is required');
|
|
14116
|
-
const tView = lView[TVIEW];
|
|
14335
|
+
function LifecycleHooksFeature() {
|
|
14117
14336
|
const tNode = getCurrentTNode();
|
|
14118
14337
|
ngDevMode && assertDefined(tNode, 'TNode is required');
|
|
14119
|
-
registerPostOrderHooks(
|
|
14338
|
+
registerPostOrderHooks(getLView()[TVIEW], tNode);
|
|
14120
14339
|
}
|
|
14121
14340
|
/**
|
|
14122
14341
|
* Wait on component until it is rendered.
|
|
@@ -15251,21 +15470,6 @@ function setDirectiveInputsWhichShadowsStyling(tView, tNode, lView, value, isCla
|
|
|
15251
15470
|
* Use of this source code is governed by an MIT-style license that can be
|
|
15252
15471
|
* found in the LICENSE file at https://angular.io/license
|
|
15253
15472
|
*/
|
|
15254
|
-
let shouldThrowErrorOnUnknownElement = false;
|
|
15255
|
-
/**
|
|
15256
|
-
* Sets a strict mode for JIT-compiled components to throw an error on unknown elements,
|
|
15257
|
-
* instead of just logging the error.
|
|
15258
|
-
* (for AOT-compiled ones this check happens at build time).
|
|
15259
|
-
*/
|
|
15260
|
-
function ɵsetUnknownElementStrictMode(shouldThrow) {
|
|
15261
|
-
shouldThrowErrorOnUnknownElement = shouldThrow;
|
|
15262
|
-
}
|
|
15263
|
-
/**
|
|
15264
|
-
* Gets the current value of the strict mode.
|
|
15265
|
-
*/
|
|
15266
|
-
function ɵgetUnknownElementStrictMode() {
|
|
15267
|
-
return shouldThrowErrorOnUnknownElement;
|
|
15268
|
-
}
|
|
15269
15473
|
function elementStartFirstCreatePass(index, tView, lView, native, name, attrsIndex, localRefsIndex) {
|
|
15270
15474
|
ngDevMode && assertFirstCreatePass(tView);
|
|
15271
15475
|
ngDevMode && ngDevMode.firstCreatePass++;
|
|
@@ -15274,8 +15478,7 @@ function elementStartFirstCreatePass(index, tView, lView, native, name, attrsInd
|
|
|
15274
15478
|
const tNode = getOrCreateTNode(tView, index, 2 /* TNodeType.Element */, name, attrs);
|
|
15275
15479
|
const hasDirectives = resolveDirectives(tView, lView, tNode, getConstant(tViewConsts, localRefsIndex));
|
|
15276
15480
|
if (ngDevMode) {
|
|
15277
|
-
|
|
15278
|
-
validateElementIsKnown(native, tNode.value, tView.schemas, hasDirectives, hostIsStandalone);
|
|
15481
|
+
validateElementIsKnown(native, lView, tNode.value, tView.schemas, hasDirectives);
|
|
15279
15482
|
}
|
|
15280
15483
|
if (tNode.attrs !== null) {
|
|
15281
15484
|
computeStaticStyling(tNode, tNode.attrs, false);
|
|
@@ -15400,65 +15603,6 @@ function ɵɵelement(index, name, attrsIndex, localRefsIndex) {
|
|
|
15400
15603
|
ɵɵelementEnd();
|
|
15401
15604
|
return ɵɵelement;
|
|
15402
15605
|
}
|
|
15403
|
-
/**
|
|
15404
|
-
* Validates that the element is known at runtime and produces
|
|
15405
|
-
* an error if it's not the case.
|
|
15406
|
-
* This check is relevant for JIT-compiled components (for AOT-compiled
|
|
15407
|
-
* ones this check happens at build time).
|
|
15408
|
-
*
|
|
15409
|
-
* The element is considered known if either:
|
|
15410
|
-
* - it's a known HTML element
|
|
15411
|
-
* - it's a known custom element
|
|
15412
|
-
* - the element matches any directive
|
|
15413
|
-
* - the element is allowed by one of the schemas
|
|
15414
|
-
*
|
|
15415
|
-
* @param element Element to validate
|
|
15416
|
-
* @param tagName Name of the tag to check
|
|
15417
|
-
* @param schemas Array of schemas
|
|
15418
|
-
* @param hasDirectives Boolean indicating that the element matches any directive
|
|
15419
|
-
* @param hostIsStandalone Boolean indicating whether the host is a standalone component
|
|
15420
|
-
*/
|
|
15421
|
-
function validateElementIsKnown(element, tagName, schemas, hasDirectives, hostIsStandalone) {
|
|
15422
|
-
// If `schemas` is set to `null`, that's an indication that this Component was compiled in AOT
|
|
15423
|
-
// mode where this check happens at compile time. In JIT mode, `schemas` is always present and
|
|
15424
|
-
// defined as an array (as an empty array in case `schemas` field is not defined) and we should
|
|
15425
|
-
// execute the check below.
|
|
15426
|
-
if (schemas === null)
|
|
15427
|
-
return;
|
|
15428
|
-
// If the element matches any directive, it's considered as valid.
|
|
15429
|
-
if (!hasDirectives && tagName !== null) {
|
|
15430
|
-
// The element is unknown if it's an instance of HTMLUnknownElement, or it isn't registered
|
|
15431
|
-
// as a custom element. Note that unknown elements with a dash in their name won't be instances
|
|
15432
|
-
// of HTMLUnknownElement in browsers that support web components.
|
|
15433
|
-
const isUnknown =
|
|
15434
|
-
// Note that we can't check for `typeof HTMLUnknownElement === 'function'`,
|
|
15435
|
-
// because while most browsers return 'function', IE returns 'object'.
|
|
15436
|
-
(typeof HTMLUnknownElement !== 'undefined' && HTMLUnknownElement &&
|
|
15437
|
-
element instanceof HTMLUnknownElement) ||
|
|
15438
|
-
(typeof customElements !== 'undefined' && tagName.indexOf('-') > -1 &&
|
|
15439
|
-
!customElements.get(tagName));
|
|
15440
|
-
if (isUnknown && !matchingSchemas(schemas, tagName)) {
|
|
15441
|
-
const schemas = `'${hostIsStandalone ? '@Component' : '@NgModule'}.schemas'`;
|
|
15442
|
-
let message = `'${tagName}' is not a known element:\n`;
|
|
15443
|
-
message += `1. If '${tagName}' is an Angular component, then verify that it is ${hostIsStandalone ? 'included in the \'@Component.imports\' of this component' :
|
|
15444
|
-
'a part of this module'}.\n`;
|
|
15445
|
-
if (tagName && tagName.indexOf('-') > -1) {
|
|
15446
|
-
message +=
|
|
15447
|
-
`2. If '${tagName}' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the ${schemas} of this component to suppress this message.`;
|
|
15448
|
-
}
|
|
15449
|
-
else {
|
|
15450
|
-
message +=
|
|
15451
|
-
`2. To allow any element add 'NO_ERRORS_SCHEMA' to the ${schemas} of this component.`;
|
|
15452
|
-
}
|
|
15453
|
-
if (shouldThrowErrorOnUnknownElement) {
|
|
15454
|
-
throw new RuntimeError(304 /* RuntimeErrorCode.UNKNOWN_ELEMENT */, message);
|
|
15455
|
-
}
|
|
15456
|
-
else {
|
|
15457
|
-
console.error(formatRuntimeError(304 /* RuntimeErrorCode.UNKNOWN_ELEMENT */, message));
|
|
15458
|
-
}
|
|
15459
|
-
}
|
|
15460
|
-
}
|
|
15461
|
-
}
|
|
15462
15606
|
|
|
15463
15607
|
/**
|
|
15464
15608
|
* @license
|
|
@@ -21941,7 +22085,7 @@ class Version {
|
|
|
21941
22085
|
/**
|
|
21942
22086
|
* @publicApi
|
|
21943
22087
|
*/
|
|
21944
|
-
const VERSION = new Version('14.0.
|
|
22088
|
+
const VERSION = new Version('14.0.1');
|
|
21945
22089
|
|
|
21946
22090
|
/**
|
|
21947
22091
|
* @license
|
|
@@ -22613,6 +22757,7 @@ class EnvironmentNgModuleRefAdapter extends NgModuleRef$1 {
|
|
|
22613
22757
|
* Create a new environment injector.
|
|
22614
22758
|
*
|
|
22615
22759
|
* @publicApi
|
|
22760
|
+
* @developerPreview
|
|
22616
22761
|
*/
|
|
22617
22762
|
function createEnvironmentInjector(providers, parent = null, debugName = null) {
|
|
22618
22763
|
const adapter = new EnvironmentNgModuleRefAdapter(providers, parent, debugName);
|
|
@@ -22640,14 +22785,14 @@ class StandaloneService {
|
|
|
22640
22785
|
if (!componentDef.standalone) {
|
|
22641
22786
|
return null;
|
|
22642
22787
|
}
|
|
22643
|
-
if (!this.cachedInjectors.has(componentDef)) {
|
|
22788
|
+
if (!this.cachedInjectors.has(componentDef.id)) {
|
|
22644
22789
|
const providers = internalImportProvidersFrom(false, componentDef.type);
|
|
22645
22790
|
const standaloneInjector = providers.length > 0 ?
|
|
22646
22791
|
createEnvironmentInjector([providers], this._injector, `Standalone[${componentDef.type.name}]`) :
|
|
22647
22792
|
null;
|
|
22648
|
-
this.cachedInjectors.set(componentDef, standaloneInjector);
|
|
22793
|
+
this.cachedInjectors.set(componentDef.id, standaloneInjector);
|
|
22649
22794
|
}
|
|
22650
|
-
return this.cachedInjectors.get(componentDef);
|
|
22795
|
+
return this.cachedInjectors.get(componentDef.id);
|
|
22651
22796
|
}
|
|
22652
22797
|
ngOnDestroy() {
|
|
22653
22798
|
try {
|
|
@@ -23147,13 +23292,26 @@ function getPipeDef(name, registry) {
|
|
|
23147
23292
|
}
|
|
23148
23293
|
}
|
|
23149
23294
|
if (ngDevMode) {
|
|
23150
|
-
|
|
23151
|
-
const declarationLView = lView[DECLARATION_COMPONENT_VIEW];
|
|
23152
|
-
const context = declarationLView[CONTEXT];
|
|
23153
|
-
const component = context ? ` in the '${context.constructor.name}' component` : '';
|
|
23154
|
-
throw new RuntimeError(-302 /* RuntimeErrorCode.PIPE_NOT_FOUND */, `The pipe '${name}' could not be found${component}!`);
|
|
23295
|
+
throw new RuntimeError(-302 /* RuntimeErrorCode.PIPE_NOT_FOUND */, getPipeNotFoundErrorMessage(name));
|
|
23155
23296
|
}
|
|
23156
23297
|
}
|
|
23298
|
+
/**
|
|
23299
|
+
* Generates a helpful error message for the user when a pipe is not found.
|
|
23300
|
+
*
|
|
23301
|
+
* @param name Name of the missing pipe
|
|
23302
|
+
* @returns The error message
|
|
23303
|
+
*/
|
|
23304
|
+
function getPipeNotFoundErrorMessage(name) {
|
|
23305
|
+
const lView = getLView();
|
|
23306
|
+
const declarationLView = lView[DECLARATION_COMPONENT_VIEW];
|
|
23307
|
+
const context = declarationLView[CONTEXT];
|
|
23308
|
+
const hostIsStandalone = isHostComponentStandalone(lView);
|
|
23309
|
+
const componentInfoMessage = context ? ` in the '${context.constructor.name}' component` : '';
|
|
23310
|
+
const verifyMessage = `Verify that it is ${hostIsStandalone ? 'included in the \'@Component.imports\' of this component' :
|
|
23311
|
+
'declared or imported in this module'}`;
|
|
23312
|
+
const errorMessage = `The pipe '${name}' could not be found${componentInfoMessage}. ${verifyMessage}`;
|
|
23313
|
+
return errorMessage;
|
|
23314
|
+
}
|
|
23157
23315
|
/**
|
|
23158
23316
|
* Invokes a pipe with 1 arguments.
|
|
23159
23317
|
*
|
|
@@ -24974,7 +25132,7 @@ function patchComponentDefWithScope(componentDef, transitiveScopes) {
|
|
|
24974
25132
|
}
|
|
24975
25133
|
/**
|
|
24976
25134
|
* Compute the pair of transitive scopes (compilation scope and exported scope) for a given type
|
|
24977
|
-
* (
|
|
25135
|
+
* (either a NgModule or a standalone component / directive / pipe).
|
|
24978
25136
|
*/
|
|
24979
25137
|
function transitiveScopesFor(type) {
|
|
24980
25138
|
if (isNgModule(type)) {
|
|
@@ -26600,7 +26758,10 @@ const TestBed = TestBedRender3;
|
|
|
26600
26758
|
*/
|
|
26601
26759
|
const getTestBed = _getTestBedRender3;
|
|
26602
26760
|
/**
|
|
26603
|
-
* Allows injecting dependencies in `beforeEach()` and `it()`.
|
|
26761
|
+
* Allows injecting dependencies in `beforeEach()` and `it()`. Note: this function
|
|
26762
|
+
* (imported from the `@angular/core/testing` package) can **only** be used to inject dependencies
|
|
26763
|
+
* in tests. To inject dependencies in your application code, use the [`inject`](api/core/inject)
|
|
26764
|
+
* function from the `@angular/core` package instead.
|
|
26604
26765
|
*
|
|
26605
26766
|
* Example:
|
|
26606
26767
|
*
|