Since we aren't using clang anymore, we can remove the comments and the workarounds that were in place to prevent it from doing the wrong thing.
PR Close#55750
This commit updates the implementation of the `addEventListener` patcher.
We're currently creating an abort event listener on the signal (when it's provided)
and never remove it. The abort event listener creates a closure which captures `task`
(tasks capture zones and other stuff too) and prevent `task`, zones and signals from
being garbage collected.
We now store the function which removes the abort event listener when the actual event
listener is being removed. The function is stored on task data since task data is already
being used to store different types of information that's necessary to be shared between
`addEventListener` and `removeEventListener`.
Closes#54739
PR Close#55339
This commit updates the list of Node.js `fs` APIs to be patched because
they haven't been updated for a long time. It adds `opendir,lutimes,writev`.
For example, the `opendir` method was added to Node.js in version 12.12.0 in
2019, causing some of the APIs to potentially be always called within the
`<root>` context.
**Note:** There are missing unit tests for these changes because in unit tests,
`fs` is patched by Bazel's Node.js rules and its `node_patches.cjs`. However,
the APIs are successfully patched in the real production code and are called
with the correct context.
PR Close#54396
This commit adds `declare` to each interface in the `zone-impl` to
prevent renaming of any interface properties by compiler optimizations.
This would otherwise cause issues if multiple applications depend on ZoneJS and
compile the interface properties to different names.
PR Close#54966
This was a bit complicated, but the typings test (`packages/zone.js/test/typings/...`) was failing due to an unresolved import on `./zone-impl`.
The main cause is that `//packages/zone.js:zone_js_d_ts` was generating the output `zone.d.ts` file by _concatenating_ `zone.d.ts` with `zone.api.extensions.d.ts` and `zone.configurations.api.d.ts`. Now that `zone.d.ts` imports `zone-impl.d.ts`, concatenation is no longer a viable means of bundling this content.
To fix this, I created a new `packages/zone.js/zone.ts` entry point and imported the underlying `zone.ts` file as well as the two extensions. I added `extract_types` to pull the `*.d.ts` files out of the target (because all the JS is bundled separately) and used those files in the final NPM package. This is sufficient to pass the typings test and should be equivalent to what exists today.
PR Close#53443
As this was, `__symbol__` was being called as a static field initializer, which runs during module evaluation, meaning it happened at import time. However for tests, the Zone prefix is overridden which changes the result of `__symbol__`. This change happens too late to be picked up by `__symbol__` at top-level execution, so instead we defer it until `symbolParentUnresolved` is actually read.
PR Close#53443
This moves timer patching from a top-level side effect into the `patchFakeAsyncTest` function. Top-level statements are evaluated before the Node patches run and have a chance to patch them with the Zone versions of these timers, meaning `FakeAsyncTestZoneSpec` was repatching the native versions between tests. The fix here is to grab the patched versions of these timers during the `patchFakeAsyncTest` function where we can be confident Node patches have already run.
PR Close#53443
This moves the internals of `fake-async-test.ts` outside `patchFakeAsyncTest` and exports them. This way they can be imported without depending on the top-level side effects of loading Zone.
PR Close#53443
For some reason the `_global` name appears to conflict with another `_global` name. Not entirely sure how or why, but the easiest fix seems to be to just give the variable a unique name.
PR Close#53443
While reading this is not a top-level side effect, it does _depend_ on a top-level side effect. Specifically, `node-env-setup.ts` set this value. Now that its side effect is moved into a function, we can't read it as the top-level of `zone-impl.ts` and need to wait until `__symbol__` is actually called outside of top-level scope.
PR Close#53443
While `TaskTrackingZoneSpec` was implicitly global previously, it does not need to be exposed in a `declare global {}` block. This is because classic scripts in TypeScript are only implicitly global within the same compilation. `TaskTrackingZoneSpec` was not exposed in the existing `.d.ts` files shipped with the `zone.js` package. Within google3, this is also a separate compilation and was not accessible. As a result, `TaskTrackingZoneSpec` was always private and we do not need a global to maintain compatibility.
PR Close#53443
While `ProxyZoneSpec` was implicitly global previously, it does not need to be exposed in a `declare global {}` block. This is because classic scripts in TypeScript are only implicitly global within the same compilation. `ProxyZoneSpec` was not exposed in the existing `.d.ts` files shipped with the `zone.js` package. Within google3, this is also a separate compilation and was not accessible. As a result, `ProxyZoneSpec` was always private and we do not need a global to maintain compatibility.
PR Close#53443
Since each patch no longer contains top-level side effects, each bundled entry point needs to import and call its associated patch. For the most part this just means that each entry point imports the associated patch and invokes it at the top-level scope.
Note that many of these entry points did not actually have a dependency on `Zone` and had no guarantee that it was loaded prior to execution. To maintain consistency, the missing dependencies on `Zone` are left as-is. They will use the global instance of `Zone` and if users fail to load it prior to importing a specific patch, then the patch will fail just as it did previously.
PR Close#53443
This drop the top-level side effects in `zone.ts` and allows the initialization to be reused across the various entry points in the package.
PR Close#53443
This particular is slightly different from the others because it does not have a hard dependency on `Zone`. It doesn't actually use `Zone` directly during the patch because the patch just sets a `legacyPatch` global. To maintain consistency, this continues to use global `Zone` and does _not_ accept `Zone` as a parameter. While it's using a global in an inconvenient way, this isn't a problem right now because it doesn't cause or require a dependency on a top-level side effect.
PR Close#53443
This removes top-level side effects from each of these files and drops the dependency on global `Zone`, instead allowing it to be provided to each patch as a parameter.
Most of these are pure mechanical transformations. A couple notable files which were somewhat unique:
* `async-test.ts`, `fake-async-test.ts`, and `wtf.ts` had unique IIFE usage and patch `Zone` itself. This removes the IIFE and exports the function instead.
* `jest.ts` and `jasmine.ts` have a unique `jest` global usage which needs to be declared.
PR Close#53443
These are all the symbols originally under `declare global {}` with the same names. Unfortunatley TypeScript treats a `declare global {}` scope as the parent scope, so we need to import with a different name than the global, meaning everything gets an `_` prefix.
PR Close#53443
This removes a name collision on `Zone` with the interface. Otherwise putting the `interface Zone {}` and `class Zone {}` in the same scope when the IIFE is removed will cause a conflict.
PR Close#53443
This drops global declarations from this file (as they will be limited to `zone.ts`. It also deletes the `/** @internal */` annotation on `AmbientZone` which is no longer necessary since it isn't in the `declare global` and deletes the global Zone declaration which is also unnecessary.
PR Close#53443
This is just a straight copy, no code is altered. The new `zone-impl.ts` file will contain the actual definitions exported directly without any global declarations or top-level side effects. The existing `zone.ts` will remain as an entry point with those globals and side-effects.
PR Close#53443
This commit updates the implementation of the `customElements` patch and also
patches FACE callbacks (`formAssociatedCallback`, `formDisabledCallback`, `formResetCallback`
and `formStateRestoreCallback`). This now allows invoking those callbacks in the same zone
where the custom element has been defined.
PR Close#50686
This commit updates the implementation of the zone.js `fs` patch to
restore the implementation of `realpath.native` and patches it as a macrotask,
along with other functions of the `fs` package. This is the only nested function
that must be patched.
Closes: #45546
PR Close#54208
This commit updates the implementation of the `fetch` patch and additionally
patches `Response` methods which return promises. These are `arrayBuffer`, `blob`,
`formData`, `json` and `text`. This fixes the issue when zone becomes stable too early
before all of the `fetch` tasks complete. Given the following code:
```ts
appRef.isStable.subscribe(console.log);
fetch(...).then(response => response.json()).then(console.log);
```
The `isStable` observer would log `false, true, false, true`. This was happening because
`json()` was returning a native promise (and not a `ZoneAwarePromise`). But calling `then`
on the native promise returns a `ZoneAwarePromise` which notifies Angular about the task
being scheduled and forces to re-calculate the `isStable` state.
Issue: #50327
PR Close#50653
This commit updates the signature of the `ZoneGlobalConfigurations` interface and adds
missing `__Zone_ignore_on_properties` property, which may be setup to ignore specific `on`
properties from being patched.
PR Close#50737
Make Zone.js compatible with moduleDetection:force by turning files that
are currently incompatible from scripts into modules using an empty
export statement.
PR Close#53445
fetch support AbortSignal, zone.js schedules a macroTask when fetch()
```
fetch(..., {signal: abortSignal});
```
we should also be able to cancel fetch with `zoneTask.cancel` call.
So this commit create an internal AbortSignal to handle
`zoneTask.cancel()` call and also delegate the `options.signal` from the
user code.
PR Close#49595
Close#49591
```
const ac = new AbortController();
addEventListener(eventName, handler, {signal: ac.signal);`
ac.abort();
```
Currently `zone.js` doesn't support the `signal` option, this PR allows
the user to use AbortContoller to remove the event listener.
PR Close#49595
In the original `Promise` impelmentation, zone.js follow the spec from
https://promisesaplus.com/#point-51.
```
const p1 = Promise.resolve(1);
const p2 = Promise.resolve(p1);
p1 === p2; // false
```
in this case, `p2` should be the same status with `p1` but they are
still different instances.
And for some edge case.
```
class MyPromise extends Promise {
constructor(sub) {
super((res) => res(null));
this.sub = sub;
}
then(onFufilled, onRejected) {
this.sub.then(onFufilled, onRejected);
}
}
const p1 = new Promise(setTimeout(res), 100);
const myP = new MyPromise(p1);
const r = await myP;
r === 1; // false
```
So in the above code, `myP` is not the same instance with `p1`,
and since `myP` is resolved in constructor, so `await myP` will
just pass without waiting for `p1`.
And in the current `tc39` spec here https://tc39.es/ecma262/multipage/control-abstraction-objects.html#sec-promise-resolve
`Promise.resolve(subP)` should return `subP`.
```
const p1 = Promise.resolve(1);
const p2 = Promise.resolve(p1);
p1 === p2; // true
```
So the above `MyPromise` can wait for the `p1` correctly.
PR Close#53423
Before this commit, zone.js wraps the uncaught promise rejection error
to a new Error object includes more information such as Zone stack
traces. This feature is provided from the very beginning of Zone.js,
but this feature becomes very annoying and make the user difficult to
debug.
So this commit disable this wrapping behavior by default, and user can
enable this feature back by setting
`DISABLE_WRAPPING_UNCAUGHT_PROMISE_REJECTION` to `false`.
PR Close#52492
`globalThis` global property contains the global `this` value, which is usually akin to the global object. This is needed for better compatibility with CloudFlare workers were global nor window are defined as globals.
PR Close#52367
This commit removes access to deep imports and `zone-testing-bundle` and `zone-testing-node-bundle`
This commit removed access to deep and legacy `dist` imports. `zone-testing-bundle` and `zone-testing-node-bundle` are also no longer generated.
BREAKING CHANGE:
Deep and legacy `dist/` imports like `zone.js/bundles/zone-testing.js` and `zone.js/dist/zone` are no longer allowed. `zone-testing-bundle` and `zone-testing-node-bundle` are also no longer part of the package.
The proper way to import `zone.js` and `zone.js/testing` is:
```js
import 'zone.js';
import 'zone.js/testing';
```
PR Close#51752
In https://github.com/angular/angular/pull/49144 we introduced a change to only path `Promise.prototype.then` due to Node.js `SafePromise` complaining about `Promise.prototype.then` called on incompatible receiver. This however introduced a number of regressions. This commit reverts this change and re-introduces the changes to patch the entire promise on Node.
The original `SafePromise` problem is no longer reproducible as of Node.js version 18.13+ as it was addressed as part of https://github.com/nodejs/node/pull/45175.
While the Angular CLI does not yet generate ESM server bundles, users using ESM with dynamic imports will require using Node.js 18.13 or later.
Closes#50513, closes#50457, closes#50414 and closes#49930
PR Close#50552