Adds support for TypeScript 4.7. Changes include:
* Bumping the TS version as well as some Bazel dependencies to include https://github.com/bazelbuild/rules_nodejs/pull/3420.
* Adding a backwards-compatibility layer for calls to `updateTypeParameterDeclaration`.
* Making `LView` generic in order to make it easier to type the context based on the usage. Currently the context can be 4 different types which coupled with stricter type checking would required a lot of extra casting all over `core`.
* Fixing a bunch of miscellaneous type errors.
* Removing assertions of `ReferenceEntry.isDefinition` in a few of the language service tests. The field isn't returned by TS anymore and we weren't using it for anything.
* Resolving in error in the language service that was caused by TS attempting to parse HTML files when we try to open them. Previous TS was silently setting them as `ScriptKind.Unknown` and ignoring the errors, but now it throws. I've worked around it by setting them as `ScriptKind.JSX`.
PR Close#45749
Updates us to version 4.0 of Jasmine and fixes some errors that were the result of us depending upon deprecated APIs. We need to do this both to stay up to date and because it was going to break eventually, because one of the Bazel packages was logging a deprecation warning that version 4.0 was required.
There were also some cases where the state of `ngDevMode` had started leaking out between tests.
PR Close#45558
Updates us to version 4.0 of Jasmine and fixes some errors that were the result of us depending upon deprecated APIs. We need to do this both to stay up to date and because it was going to break eventually, because one of the Bazel packages was logging a deprecation warning that version 4.0 was required.
There were also some cases where the state of `ngDevMode` had started leaking out between tests.
PR Close#45558
Close#44913
The following case is not handled correctly by `zone.js`.
```
const delayedPromise = new Promise((resolve) => {
setTimeout(resolve, 1, 'timeout');
});
new Promise((resolve) => {
resolve(delayedPromise);
resolve('second call');
}).then(console.log);
```
It should output `timeout`, since the promise is resolved by the
1st resolve, the `second call` should be ignored.
So this is a bug that the original implementation not ensure the
`resolve` is only called once.
PR Close#45283
We must read `Symbol.species` safely because `this` may be anything. For instance, `this`
may be an object without a prototype (created through `Object.create(null)`); thus
`this.constructor` will be undefined. One of the use cases is SystemJS creating
prototype-less objects (modules) via `Object.create(null)`. The SystemJS creates an empty
object and copies promise properties into that object (within the `getOrCreateLoad`
function). The zone.js then checks if the resolved value has the `then` method and invokes
it with the `value` context. Otherwise, this will throw an error: `TypeError: Cannot read
properties of undefined (reading 'Symbol(Symbol.species)')`.
PR Close#45369
.substr() is deprecated so we replace it with functions which work similarily but aren't deprecated
Signed-off-by: Tobias Speicher <rootcommander@gmail.com>
PR Close#45397
Before this change, the macrotask for `setInterval(callback, ms)` was no
longer tracked by `TaskTrackingZoneSpec` after the `callback` was
invoked for the first time. Now the periodic macrotask is tracked until
it is cancelled, e.g. `clearInterval(id)`.
BREAKING CHANGE: in TaskTrackingZoneSpec track a periodic task until it is cancelled
The breaking change is scoped only to the plugin
`zone.js/plugins/task-tracking`. If you used `TaskTrackingZoneSpec` and
checked the pending macroTasks e.g. using `(this.ngZone as any)._inner
._parent._properties.TaskTrackingZone.getTasksFor('macroTask')`, then
its behavior slightly changed for periodic macrotasks. For example,
previously the `setInterval` macrotask was no longer tracked after its
callback was executed for the first time. Now it's tracked until
the task is explicitly cancelled, e.g with `clearInterval(id)`.
fixes 45350
PR Close#45391
For legacy browsers, we still use the eventNames array to patch event instead of
using `Object.getOwnPropertyNames()` to keep backward compatibility.
PR Close#40962
Zone.js supports the google closure compiler in the advance optimization mode,
to prevent closure compiler modify the `onProperty` name such as `Element.prototype.onclick`,
Zone.js implements the `onProperty` patch logic by declaring all the
event names in the source code, this increases the bundle size and also require
updating the event names array to keep the information updated.
Now google closure compiler has the required event names defined in the built-in
externs files, so zone.js can use more simple implementation and decrease the bundle size
of zone.js (about 4k).
PR Close#40962
`AsyncTestZoneSpec` triggers jasmine `done()` function multiple times
and causes warning
```
An asynchronous function called its 'done' callback more than once. This is a bug in the spec, beforeAll, beforeEach, afterAll, or afterEach function in question. This will be treated as an error in a future version. See<https://jasmine.github.io/tutorials/upgrading_to_Jasmine_4.0#deprecations-due-to-calling-done-multiple-times> for more information
```
The reproduce case will be running some `Zone.run()` inside
`waitForAsync()`.
```
it('multiple done', waitForAsync(() => {
Zone.current.run(() => {});
Zone.current.run(() => {});
}));
```
The reason the `done()` is called in the `onInvoke()` hook is to handle
the case that the testBody is totally sync, but we should only do this
check for the entry function not for all `Zone.run()` scenario.
Another issue is if we run nested zone inside `waitForAsync()`, the
`onHasTask()` hook will be triggered multiple times, and cause `done()`
be triggered multiple times, so we need to only trigger the `done()`
when the zone is `AsyncTestZone`.
PR Close#45025
Related to #41434
Fix several flaky cases.
1. should restore `window.onerror` in test cases.
2. expect().toThrow() should pass a function.
PR Close#41526
To make our test output i.e. devmode output more aligned
with what we produce in the NPM packages, or to be more
aligned with what Angular applications will usually consume,
the devmode output is switched from ES5 to ES2015.
Additionally various tsconfigs (outside of Bazel) have been
updated to match with the other parts of the build. The rules
are:
ES2015 for test configurations, ES2020 for actual code that will
end up being shipped (this includes the IDE-only tsconfigs).
PR Close#44505
Adds support for TypeScript 4.5. Includes the following changes:
* Bumping the package versions.
* Fixing a few calls to `createExportSpecifier` and `createImportSpecifier` that require an extra parameter.
* Adding some missing methods to the TS compiler hosts.
* Fixing an issue in the TS mocks for the ngcc tests where a regex was too agressive and was trying to match a path like `/node_modules/@typescript/lib-es5`.
* Accounting for type-only import specifiers when reporting DI errors (see #43620).
Fixes#43620.
PR Close#44164
With this change we update `rollup` and remove the usage of no longer maintained `rollup-plugin-commonjs` and `rollup-plugin-node-resolve` plugins.
PR Close#43737
Adds support for TypeScript 4.4. High-level overview of the changes made in this PR:
* Bumps the various packages to `typescript@4.4.2` and `tslib@2.3.0`.
* The `useUnknownInCatchVariables` compiler option has been disabled so that we don't have to cast error objects explicitly everywhere.
* TS now passes in a third argument to the `__spreadArray` call inside child class constructors. I had to update a couple of places in the runtime and ngcc to be able to pick up the calls correctly.
* TS now generates code like `(0, foo)(arg1, arg2)` for imported function calls. I had to update a few of our tests to account for it. See https://github.com/microsoft/TypeScript/pull/44624.
* Our `ngtsc` test setup calls the private `matchFiles` function from TS. I had to update our usage, because a new parameter was added.
* There was one place where we were setting the readonly `hasTrailingComma` property. I updated the usage to pass in the value when constructing the object instead.
* Some browser types were updated which meant that I had to resolve some trivial type errors.
* The downlevel decorators tranform was running into an issue where the Closure synthetic comments were being emitted twice. I've worked around it by recreating the class declaration node instead of cloning it.
PR Close#43281
This commit performs several updates to stop running tests in IE11 on CI (since IE11 support was deprecated in v12 and will be dropped in v13).
PR Close#43002
Updates to TypeScript 4.3.4 which contains a fix for a printer
regression that caused unexpected JavaScript output with our
compiler transforms.
See: https://github.com/microsoft/TypeScript/pull/44070.
Updates to TypeScript 4.3.4 which contains a fix for a printer
PR Close#42600
Close#41867
In the previous commit https://github.com/angular/angular/pull/41562#issuecomment-822696973,
the error thrown in the event listener will be caught and re-thrown, but there is a bug
in the commit, if there is only one listener for the specified event name, the error
will not be re-thrown, so this commit fixes the issue and make sure the error is re-thrown.
PR Close#41868
Switches the repository to TypeScript 4.3 and the latest
version of tslib. This involves updating the peer dependency
ranges on `typescript` for the compiler CLI and for the Bazel
package. Tests for new TypeScript features have been added to
ensure compatibility with Angular's ngtsc compiler.
PR Close#42022
This change moves the `dev-infra/browsers` folder into `dev-infra/bazel`.
The browser folder is providing custom configuration for Bazel, so it
should live within the `bazel` folder for a more well-structured
`dev-infra` folder.
PR Close#42268
Close#41520.
This case related to the issue #41522.
```
Zone.root
.fork({
name: 'xhr',
onHasTask(delegate, currentZone, zone, taskState) {
console.log('hasMacrotask', taskState.macroTask);
return delegate.hasTask(zone, taskState);
},
})
.run(() => {
const xhr = new XMLHttpRequest();
xhr.open('GET', 'https://cdnjs.cloudflare.com/ajax/libs/zone.js/0.11.4/zone.min.js');
xhr.addEventListener('load', () => {
throw new Error();
});
xhr.send();
});
```
zone.js invoke all `onload` event handlers before change the XHR task's state from
`scheduled` to `notscheduled`, so if any `onload` listener throw error, the XHR task
wlll be hang to `scheduled`, and leave the macroTask status in the zone wrongly.
This has been fixed in the previous commit, this commit add test to verify the case.
PR Close#41562
Close#41522
`zone.js` patches event listeners and run all event listeners together, if
one event handler throws error, the listeners afterward may not be invoked.
Reproduction:
```
export class AppComponent implements AfterViewInit {
@ViewChild('btn') btn: ElementRef;
title = 'event-error';
constructor(private ngZone: NgZone) {}
ngAfterViewInit() {
this.ngZone.runOutsideAngular(() => {
this.btn.nativeElement.addEventListener('click', () => {
throw new Error('test1');
});
this.btn.nativeElement.addEventListener('click', () => {
console.log('add eventlistener click');
});
});
}
}
```
Until now no Angular users report this issue becuase in the `ngZone`, all
error will be caught and will not rethrow, so the event listeners afterward
will still continue to execute, but if the event handlers are outside of `ngZone`,
the error will break the execution.
This commit catch all errors, and after all event listeners finished invocation,
rethrow the errors in seperate `microTasks`, the reason I am using `microTask` here
is to handle multiple errors case.
PR Close#41562
Close#41520.
This case related to the issue #41522.
```
Zone.root
.fork({
name: 'xhr',
onHasTask(delegate, currentZone, zone, taskState) {
console.log('hasMacrotask', taskState.macroTask);
return delegate.hasTask(zone, taskState);
},
})
.run(() => {
const xhr = new XMLHttpRequest();
xhr.open('GET', 'https://cdnjs.cloudflare.com/ajax/libs/zone.js/0.11.4/zone.min.js');
xhr.addEventListener('load', () => {
throw new Error();
});
xhr.send();
});
```
zone.js invoke all `onload` event handlers before change the XHR task's state from
`scheduled` to `notscheduled`, so if any `onload` listener throw error, the XHR task
wlll be hang to `scheduled`, and leave the macroTask status in the zone wrongly.
This has been fixed in the previous commit, this commit add test to verify the case.
PR Close#41562
Close#41522
`zone.js` patches event listeners and run all event listeners together, if
one event handler throws error, the listeners afterward may not be invoked.
Reproduction:
```
export class AppComponent implements AfterViewInit {
@ViewChild('btn') btn: ElementRef;
title = 'event-error';
constructor(private ngZone: NgZone) {}
ngAfterViewInit() {
this.ngZone.runOutsideAngular(() => {
this.btn.nativeElement.addEventListener('click', () => {
throw new Error('test1');
});
this.btn.nativeElement.addEventListener('click', () => {
console.log('add eventlistener click');
});
});
}
}
```
Until now no Angular users report this issue becuase in the `ngZone`, all
error will be caught and will not rethrow, so the event listeners afterward
will still continue to execute, but if the event handlers are outside of `ngZone`,
the error will break the execution.
This commit catch all errors, and after all event listeners finished invocation,
rethrow the errors in seperate `microTasks`, the reason I am using `microTask` here
is to handle multiple errors case.
PR Close#41562
With this change we update several dependencies to avoid Renovate creating a lot of PRs during onboarding. We also remove yarn workspaces as after further analysis these are not needed.
Certain dependencies such as `@octokit/rest`, `remark` and `@babel/*` have not been updated as they require a decent amount of work to update, and it's best to leave them for a seperate PR.
PR Close#41434
Close#40387
Currently zone.js patches `setTimeout` and keeps a `tasksByHandleId` map to keep `timerId` <-> `ZoneTask`
relationship. This is needed so that when `clearTimeout(timerId)` is called, zone.js can find the associated
`ZoneTask`. Now zone.js set the `tasksByHandleId` map in the `scheduleTask` function, but if the `setTimeout`
is running in the `FakeAsyncZoneSpec` or any other `ZoneSpec` with `onScheduleTask` hooks. The `scheduleTask`
in `timer` patch may not be invoked.
For example:
```
fakeAsync(() => {
setTimeout(() => {});
tick();
});
```
In this case, the `timerId` kept in the `tasksByHandleId` map is not cleared.
This is because the `FakeAsyncZoneSpec` in the `onScheduleTask` hook looks like this.
```
onScheduleTask(delegate, ..., task) {
fakeAsyncScheduler.setTimeout(task);
return task;
}
```
Because `FakeAsyncZoneSpec` handles the task itself and it doesn't call `parentDelegate.onScheduleTask`,
therefore the default `scheduleTask` in the `timer` patch is not invoked.
In this commit, the cleanup logic is moved from `scheduleTask` to `setTimeout` patch entry to
avoid the memory leak.
PR Close#40586
When migrating zone.js from gulp to bazel, some legacy build config files are still there,
we have `rollup-es5.config.js` and `rollup-es5_global-es2015.config.js`, since in gulp build
system, build `es5` or `esm` files are set in the config file, but in the bazel world,
the output format is not config in the config.js file, but is required by the downstream
bazel target. So we don't really need the two rollup config files any longer.
Another difference is in `rollup-es5.config.js`, the `external` and `global` libraries names
are also config there, and these settings are also valid for `es2015` build, these settings
are not in the `es2015.config.js` for some legacy reasons. So we don't need to keep this
difference either.
PR Close#40481
Close#40215
`fesm2015/zone.js` is built to `esm` bundle with rollup, so the 'use strict';
statement is not generated in the bundle, even we put the 'use strict' in the src code,
rollup removes the code in the final bundle.
So if we load the `fesm2015/zone.js` as a module, such as `ng serve`, in the index.html
```
<script src="polyfills.js" type="module"></script>
```
Everything works fine, since polyfills.js is loaded as `module`, so it is always `strict`.
But in `ng test`, webpack concat the `zone.js` and loaded into the karma html. For other app and
test code, they are still `strict` since they are `module` because they have `export/import`
statement, but `zone.js` is a bundle without `export`, it is a `side effect` bundle, so after
loaded by webpack, it becomes non-strict. Which causes some issues, such as #40215,
the root cause is the `this` context should be `undefined` but treated as `Window` in `non-strict` mode.
```
Object.prototype.toString.apply(undefined);
// should be [object undefined], but it is [object Window] in non-strict mode.
// zone.js patched version of toString
Object.prototype.toString = function() {
...
// in non-strict mode, this is Window
return originalObjectPrototypeToString.call(this);
}
```
So in this commit, `'use strict';` is always added to the `esm` bundles.
PR Close#40456
Fix a case where, if the parent class had already been patched, it would
not patch the child class. In addition to checking if the method is
defined in the prototype, and not inherited, it also does the same for
the unpatched method.
PR Close#39850
Close#38863
Monkey patches `queueMicrotask()` API, so the callback runs in the zone
when scheduled, and also the task is run as `microTask`.
```
Zone.current.fork({
name: 'queueMicrotask',
onScheduleTask: (delegate: ZoneDelegate, curr: Zone, target: Zone, task: Task) => {
logs.push(task.type);
logs.push(task.source);
return delegate.scheduleTask(target, task);
}
}).run(() => {
queueMicrotask(() => {
expect(logs).toEqual(['microTask', 'queueMicrotask']);
expect(Zone.current.name).toEqual('queueMicrotask');
done();
});
});
```
PR Close#38904
Add back the zone.js externs file test for google closure compiler.
The test compiles a test program with and without `zone_externs`.
1. With `zone_externs`, the code should keep the APIs defined in the `zone_externs`.
2. Without `zone_externs`, the code will not keep these APIs.
PR Close#39108
In `FakeAsyncZoneSpec`, there are several variables and APIs to identify
different times, and the names are confusing, in this commit, they are
renamed for more clear understandings.
1. currentTickTime, the tick millis advanced.
2. getFakeBaseSystemTime(), return the fake base system time.
3. setFakeBaseSystemTime(), set the fake base system time.
4. getRealSystemTime(), get the underlying native system time.
PR Close#39127