In Chrome 83 passing a TrustedScript to eval just returns the
TrustedScript back without evaluating it, causing the
newTrustedFunctionFor{Dev,JIT} functions to fail. This is a browser bug
that has been fixed in Chrome 84, and only affects Angular applications
running with JIT (which includes unit tests).
As a temporary workaround for users still on Chrome 83, detect when this
occurs in the newTrustedFunctionFor* functions and fall back to the
straightforward, non-Trusted Types compatible implementation. The only
combination that is left affected consists of Angular applications
running with JIT, that have explicitly configured Trusted Types in
enforcement mode, with users that are still on Chrome 83.
Also correct docstring for newTrustedFunctionForJIT.
PR Close#40815
This commit implements creating of `ɵɵngDeclarePipe()` calls in partial
compilation, and processing of those calls in the linker and JIT compiler.
See #40677
PR Close#40803
This commit fixes the issue of the ASSERTION ERROR issue when
a projected node(RNode) inside an array is checked against the types
of TNodeType.Element, TNodeType.Container, TNodeType.ElementContainer,
TNodeType.IcuContainer, TNodeType.Projection. As it's inside an array,
it doesn't fall into any of those types, as a result, it throws
the ASSERTION ERROR.
PR Close#37120
PR Close#37167
Prior to this patch, if an element was removed multiple times (due
to the nature of parent/child elements), the leave listeners may
have been fired for an element that was already removed. This patch
adds a guard within the animations code to prevent this.
PR Close#40712
The `AsyncPipe.transform<T>(emitter)` method must infer the `T`
type from the `emitter` parameter. Since we changed the `AsyncPipe`
to expect a `Subscribable<T>` rather than `Observable<T>` the
`EventEmitter.subscribe()` method needs to have a tighter signature.
Otherwise TypeScript struggles to infer the type and ends up making
it `unknown`.
Fixes#40637
PR Close#40644
fix https://github.com/angular/components/issues/21674
When setting `ngZoneRunCoalescing` to true, `onStable` is not emitted correctly.
The reason is before this commit, the code looks like this
```
// Application code call `ngZone.run()`
ngZone.run(() => {}); // step 1
// Inside NgZone, in the OnInvoke hook, NgZone try to delay the checkStable()
function delayChangeDetectionForEvents(zone: NgZonePrivate) {
if (zone.lastRequestAnimationFrameId !== -1) { // step 9
return;
}
zone.lastRequestAnimationFrameId = zone.nativeRequestAnimationFrame.call(global, () => { // step 2
if (!zone.fakeTopEventTask) {
zone.fakeTopEventTask = Zone.root.scheduleEventTask('fakeTopEventTask', () => {
zone.lastRequestAnimationFrameId = -1; // step 3
updateMicroTaskStatus(zone); // step 4
checkStable(zone); // step 6
}, undefined, () => {}, () => {});
}
zone.fakeTopEventTask.invoke();
});
updateMicroTaskStatus(zone);
}
function updateMicroTaskStatus(zone: NgZonePrivate, ignoreCheckRAFId = false) {
if (zone._hasPendingMicrotasks ||
((zone.shouldCoalesceEventChangeDetection || zone.shouldCoalesceRunChangeDetection) &&
zone.lastRequestAnimationFrameId !== -1)) { // step 5
zone.hasPendingMicrotasks = true;
} else {
zone.hasPendingMicrotasks = false;
}
}
function checkStable(zone: NgZonePrivate) {
if (zone._nesting == 0 && !zone.hasPendingMicrotasks && !zone.isStable) { // step 7
try {
zone._nesting++;
zone.onMicrotaskEmpty.emit(null);
...
}
// application ref subscribe onMicroTaskEmpty
ngZone.onMicroTaskEmpty.subscribe(() => {
ngZone.run(() => { // step 8
tick();
});
});
```
And the process is:
1. step 1: application call ngZone.run()
2. step 2: NgZone delay the checkStable() call in a requestAnimationFrame, and also set
zone.lastRequestAnimationFrameId
3. step 3: Inside the requestAnimationFrame callback, reset zone.lastRequestAnimationFrameId first
4. step 4: update microTask status
5, step 5: if zone.lastRequestAnimationFrameId is -1, that means no microTask pending.
6. step 6: checkStable and trigger onMicrotaskEmpty emitter.
7. step 7: ApplicationRef subscribed onMicrotaskEmpty, so it will call another `ngZone.run()` to process
tick()
8. step 8: And this new `ngZone.run()` will try to check `zone.lastRequestAnimationFrameId` in `step 9`
when trying to delay the checkStable(), and since the zone.lastRequestAnimationFrameId is already reset
to -1 in step 3, so this ngZone.run() will run into step 2 again.
9. And become a infinite loop..., so onStable is never emit
In this commit, the `zone.lastRequestAnimationFrameId` reset is moved after `checkStable()` call.
PR Close#40540
The codebase currently contains several `EMPTY_ARRAY` constants,
and they can end up in the bundle of an application.
A recent commit 6fbe219 tipped us off
as it introduced several `noop` occurrences in the golden symbol files.
After investigating with @petebacondarwin,
we decided to remove the duplicated symbols.
This probably shaves only a few bytes,
but this commit removes the duplicated functions,
by always using the one in `core/src/utils/empty`.
PR Close#40587
Previously, in `_mismatch()`, the `DefaultIterableDiffer` first checks
`_linkedRecords` for `itemTrackBy`, then checks `_unlinkedRecords`.
This cause the `DefaultIterableDiffer` to move "later" items that match the
`itemTrackBy` from the old collection, rather than using the "earlier" one.
Now we check `_unlinkedRecords` first, so that the `DefaultIterableDiffer`
can give a more stable and reasonable result after diffing. For example,
rather than (`a1` and `a2` have same trackById)
```
a1 b c a2 => b a2 c a1
```
we get
```
a1 b c a2 => b a1 c a2
```
where a1 and a2 retain their original order despite both
having the same track by value.
Fixes#23815
PR Close#23941
rxjs was only used within one location within the static queries migration to workaround
a previous limitation that schematics could not directly use a promise. However, promise
support has been available since 8.0. This change removes the observable promise wrapping.
It also removes an any cast that was previously needed to workaround rxjs version mismatches
during compilation.
PR Close#38657
This commits adds additional expectations to verify that the bloom
filter is able to correctly handle token IDs that exceed the size of
the bloom filter (which is currently 256 bits).
PR Close#40489
The injector system uses a bloom filter to determine if a token is
possibly defined in the node injector tree, which is stored across
multiple bloom buckets that each represent 32 bits of the full 256-bit
wide bloom hash. This means that a computation is required to determine
the exact bloom bucket which is responsible for storing any given 32-bit
interval, which was previously computed using three bitmask operations
and three branches to derive the bloom bucket offset.
This commit exploits the observation that all bits beyond the low 5 bits
of the bloom hash are an accurate representation for the bucket offset,
if shifted right such that those bits become the least significant bits.
This reduces the three bitmask operations and three branches with a
single shift operation, while additionally offering a code size
improvement.
PR Close#40489
Because the query now has `flags` which specify the mode, the static query
instruction can now be remove. It is simply normal query with `static` flag.
PR Close#40091
Previous implementation would fire changes `QueryList.changes.subscribe`
whenever the `QueryList` was recomputed. This resulted in artificially
high number of change notifications, as it is possible that recomputing
`QueryList` results in the same list. When the `QueryList` gets recomputed
is an implementation detail and it should not be the thing which determines
how often change event should fire.
This change introduces a new `emitDistinctChangesOnly` option for
`ContentChildren` and `ViewChildren`.
```
export class QueryCompWithStrictChangeEmitParent {
@ContentChildren('foo', {
// This option will become the default in the future
emitDistinctChangesOnly: true,
})
foos!: QueryList<any>;
}
```
PR Close#40091
This commit updates the logic that calculates `useFactory` function arguments to avoid relying on `instanceof`
checks (thus always retaining symbols) and relies on flags that DI decorators contain (as a monkey-patched property).
Another perf benefit is having less megamorphic reads while calculating args for the `useFactory` call: we used to
check whether a token has `ngMetadataName` property 4 times (in worst case), now we have just 1 megamorphic read in
all cases.
Closes#40143.
PR Close#40145
The `template` and `isInline` fields were previously stored in a nested
object, which was initially done to accommodate for additional template
information to support accurate source maps for external templates. In
the meantime the source mapping has been accomplished in a different
way, and I feel this flattened structure is simpler and smaller so is
preferable over the nested object. This change also makes the `isInline`
property optional with a default value of `false`.
PR Close#40383