build: move zone.js to angular repo (#30962)

PR Close #30962
This commit is contained in:
JiaLiPassion
2019-06-20 11:27:39 -07:00
committed by Kara Erickson
parent 7b3bcc23af
commit 5eb7426216
271 changed files with 30890 additions and 19 deletions
+14
View File
@@ -641,6 +641,17 @@ jobs:
name: "Running Material unit tests"
command: ./scripts/ci/run_angular_material_unit_tests.sh
test_zonejs:
<<: *job_defaults
steps:
- *attach_workspace
- *init_environment
# Install
- run: yarn --cwd packages/zone.js install --frozen-lockfile --non-interactive
# Run zone.js tools tests
- run: yarn --cwd packages/zone.js promisetest
- run: yarn --cwd packages/zone.js promisefinallytest
workflows:
version: 2
default_workflow:
@@ -725,6 +736,9 @@ workflows:
- material-unit-tests:
requires:
- build-ivy-npm-packages
- test_zonejs:
requires:
- setup
saucelabs_tests:
jobs:
+1
View File
@@ -74,6 +74,7 @@ karma_web_test(
"//packages/core/test:test_lib",
"//packages/forms/test:test_lib",
"//packages/http/test:test_lib",
"//packages/zone.js/test:karma_jasmine_test_ci",
# "//packages/router/test:test_lib",
# //packages/router/test:test_lib fails with:
# IE 11.0.0 (Windows 8.1.0.0) bootstrap should restore the scrolling position FAILED
+6 -3
View File
@@ -42,6 +42,7 @@
"@schematics/angular": "^8.0.0-beta.15",
"@types/angular": "^1.6.47",
"@types/base64-js": "1.2.5",
"@types/bluebird": "^3.5.27",
"@types/chai": "^4.1.2",
"@types/chokidar": "^1.7.5",
"@types/convert-source-map": "^1.5.1",
@@ -57,6 +58,7 @@
"@types/selenium-webdriver": "3.0.7",
"@types/shelljs": "^0.7.8",
"@types/source-map": "^0.5.1",
"@types/systemjs": "0.19.32",
"@types/yargs": "^11.1.1",
"@webcomponents/custom-elements": "^1.0.4",
"angular": "npm:[email protected]",
@@ -66,12 +68,14 @@
"angular-mocks-1.5": "npm:[email protected]",
"angular-mocks-1.6": "npm:[email protected]",
"base64-js": "1.2.1",
"bluebird": "^3.5.5",
"brotli": "^1.3.2",
"canonical-path": "1.0.0",
"chai": "^4.1.2",
"chalk": "^2.3.1",
"chokidar": "^2.1.1",
"convert-source-map": "^1.5.1",
"core-js": "^2.4.1",
"dependency-graph": "^0.7.2",
"diff": "^3.5.0",
"domino": "2.1.2",
@@ -88,6 +92,7 @@
"minimist": "1.2.0",
"mock-fs": "^4.10.1",
"node-uuid": "1.4.8",
"nodejs-websocket": "^1.7.2",
"protractor": "^5.4.2",
"reflect-metadata": "^0.1.3",
"rollup": "^1.1.0",
@@ -121,7 +126,6 @@
"@bazel/buildifier": "^0.25.1",
"@bazel/ibazel": "~0.9.0",
"@types/minimist": "^1.2.0",
"@types/systemjs": "0.19.32",
"browserstacktunnel-wrapper": "2.0.1",
"check-side-effects": "0.0.21",
"clang-format": "1.0.41",
@@ -129,14 +133,13 @@
"cldr-data-downloader": "0.3.2",
"cldrjs": "0.5.0",
"conventional-changelog": "^2.0.3",
"core-js": "^2.4.1",
"cors": "2.8.4",
"entities": "1.1.1",
"firebase-tools": "5.1.1",
"firefox-profile": "1.0.3",
"glob": "7.1.2",
"gulp": "3.9.1",
"gulp-clang-format": "1.0.23",
"gulp-clang-format": "1.0.27",
"gulp-connect": "5.0.0",
"gulp-conventional-changelog": "^2.0.3",
"gulp-filter": "^5.1.0",
+1
View File
@@ -42,5 +42,6 @@
"examples/**/main.ts",
"platform-server/integrationtest",
"router/test/aot_ngsummary_test",
"zone.js"
]
}
+47
View File
@@ -0,0 +1,47 @@
load("@build_bazel_rules_nodejs//:defs.bzl", "npm_package", "rollup_bundle")
load("@npm_bazel_jasmine//:index.bzl", "jasmine_node_test")
load("@npm_bazel_typescript//:defs.bzl", "ts_library")
load("//packages/zone.js:bundles.bzl", "ES2015_BUNDLES", "ES5_BUNDLES", "ES5_GLOBAL_BUNDLES")
exports_files([
"tsconfig.json",
])
genrule(
name = "LICENSE_copy",
srcs = ["//:LICENSE"],
outs = ["LICENSE"],
cmd = "cp $< $@",
)
genrule(
name = "LICENSE_wrapped",
srcs = ["//:LICENSE"],
outs = ["LICENSE.wrapped"],
cmd = "(echo '/**\n @license' && cat $< && echo '*/') > $@",
)
npm_package(
name = "npm_package",
srcs = [
"CHANGELOG.md",
"README.md",
"package.json",
],
visibility = ["//packages/zone.js/test:__pkg__"],
deps = [
":LICENSE.wrapped",
":LICENSE_copy",
"//packages/zone.js/dist:zone_externs",
"//packages/zone.js/lib",
] + [
"//packages/zone.js/dist:" + b + "-dist"
for b in ES5_BUNDLES
] + [
"//packages/zone.js/dist:" + b + "-dist"
for b in ES2015_BUNDLES
] + [
"//packages/zone.js/dist:" + b + "-dist"
for b in ES5_GLOBAL_BUNDLES
] + ["//packages/zone.js/dist:zone_d_ts"],
)
File diff suppressed because it is too large Load Diff
+90
View File
@@ -0,0 +1,90 @@
To run tests
------------
Make sure your environment is set up with:
`yarn`
In a separate process, run the WebSockets server:
`yarn ws-server`
Run the browser tests using Karma:
`yarn test`
Run the node.js tests:
`yarn test-node`
Run tslint:
`yarn lint`
Run format with clang-format:
`yarn format`
Run all checks (lint/format/browser test/test-node):
`yarn ci`
Before Commit
------------
Please make sure you pass all following checks before commit
- gulp lint (tslint)
- gulp format:enforce (clang-format)
- gulp promisetest (promise a+ test)
- yarn test (karma browser test)
- gulp test-node (node test)
You can run
`yarn ci`
to do all those checks for you.
You can also add the script into your git pre-commit hook
```
echo -e 'exec npm run ci' > .git/hooks/pre-commit
chmod u+x .git/hooks/pre-commit
```
Webdriver Test
--------------
`zone.js` also supports running webdriver e2e tests.
1. run locally
```
yarn webdriver-start
yarn webdriver-http
yarn webdriver-test
```
2. run locally with sauce connect
```
// export SAUCE_USERNAME and SAUCE_ACCESS_KEY
export SAUCE_USERNAME=XXXX
export SAUCE_ACCESS_KEY=XXX
sc -u $SAUCE_USERNAME -k $SAUCE_ACCESS_KEY
yarn webdriver-http
yarn webdriver-sauce-test
```
Releasing
---------
To make a `dry-run`, run the following commands.
```
$ VERSION=<version>
$ git tag 'zone.js-$VERSION'
$ yarn bazel --output_base=$(mktemp -d) run //packages/zone.js:npm_package.pack --workspace_status_command="echo BUILD_SCM_VERSION $VERSION"
```
If everything looks fine, replace `.pack` with `.publish` to push to the npm registry.
+139
View File
@@ -0,0 +1,139 @@
# Modules
Starting from zone.js v0.8.9, you can choose which web API modules you want to patch as to reduce overhead introduced by the patching of these modules. For example,
the below samples show how to disable some modules. You just need to define a few global variables
before loading zone.js.
```
<script>
__Zone_disable_Error = true; // Zone will not patch Error
__Zone_disable_on_property = true; // Zone will not patch onProperty such as button.onclick
__Zone_disable_geolocation = true; // Zone will not patch geolocation API
__Zone_disable_toString = true; // Zone will not patch Function.prototype.toString
__Zone_disable_blocking = true; // Zone will not patch alert/prompt/confirm
__Zone_disable_PromiseRejectionEvent = true; // Zone will not patch PromiseRejectionEventHandler
</script>
<script src="../dist/zone.js"></script>
```
Below is the full list of currently supported modules.
- Common
|Module Name|Behavior with zone.js patch|How to disable|
|--|--|--|
|Error|stack frames will have the Zone's name information, (By default, Error patch will not be loaded by zone.js)|__Zone_disable_Error = true|
|toString|Function.toString will be patched to return native version of toString|__Zone_disable_toString = true|
|ZoneAwarePromise|Promise.then will be patched as Zone aware MicroTask|__Zone_disable_ZoneAwarePromise = true|
|bluebird|Bluebird will use Zone.scheduleMicroTask as async scheduler. (By default, bluebird patch will not be loaded by zone.js)|__Zone_disable_bluebird = true|
- Browser
|Module Name|Behavior with zone.js patch|How to disable|
|--|--|--|
|on_property|target.onProp will become zone aware target.addEventListener(prop)|__Zone_disable_on_property = true|
|timers|setTimeout/setInterval/setImmediate will be patched as Zone MacroTask|__Zone_disable_timers = true|
|requestAnimationFrame|requestAnimationFrame will be patched as Zone MacroTask|__Zone_disable_requestAnimationFrame = true|
|blocking|alert/prompt/confirm will be patched as Zone.run|__Zone_disable_blocking = true|
|EventTarget|target.addEventListener will be patched as Zone aware EventTask|__Zone_disable_EventTarget = true|
|IE BrowserTools check|in IE, browser tool will not use zone patched eventListener|__Zone_disable_IE_check = true|
|CrossContext check|in webdriver, enable check event listener is cross context|__Zone_enable_cross_context_check = true|
|XHR|XMLHttpRequest will be patched as Zone aware MacroTask|__Zone_disable_XHR = true|
|geolocation|navigator.geolocation's prototype will be patched as Zone.run|__Zone_disable_geolocation = true|
|PromiseRejectionEvent|PromiseRejectEvent will fire when ZoneAwarePromise has unhandled error|__Zone_disable_PromiseRejectionEvent = true|
|mediaQuery|mediaQuery addListener API will be patched as Zone aware EventTask. (By default, mediaQuery patch will not be loaded by zone.js) |__Zone_disable_mediaQuery = true|
|notification|notification onProperties API will be patched as Zone aware EventTask. (By default, notification patch will not be loaded by zone.js) |__Zone_disable_notification = true|
- NodeJS
|Module Name|Behavior with zone.js patch|How to disable|
|--|--|--|
|node_timers|NodeJS patch timer|__Zone_disable_node_timers = true|
|fs|NodeJS patch fs function as macroTask|__Zone_disable_fs = true|
|EventEmitter|NodeJS patch EventEmitter as Zone aware EventTask|__Zone_disable_EventEmitter = true|
|nextTick|NodeJS patch process.nextTick as microTask|__Zone_disable_nextTick = true|
|handleUnhandledPromiseRejection|NodeJS handle unhandledPromiseRejection from ZoneAwarePromise|__Zone_disable_handleUnhandledPromiseRejection = true|
|crypto|NodeJS patch crypto function as macroTask|__Zone_disable_crypto = true|
- on_property
You can also disable specific on_properties by setting `__Zone_ignore_on_properties` as follows: for example,
if you want to disable `window.onmessage` and `HTMLElement.prototype.onclick` from zone.js patching,
you can do like this.
```
<script>
__Zone_ignore_on_properties = [
{
target: window,
ignoreProperties: ['message']
}, {
target: HTMLElement.prototype,
ignoreProperties: ['click']
}
];
</script>
<script src="../dist/zone.js"></script>
```
- Error
By default, `zone.js/dist/zone-error` will not be loaded for performance concern.
This package will provide following functionality.
1. Error inherit: handle `extend Error` issue.
```
class MyError extends Error {}
const myError = new MyError();
console.log('is MyError instanceof Error', (myError instanceof Error));
```
without `zone-error` patch, the example above will output `false`, with the patch, the reuslt will be `true`.
2. BlacklistZoneStackFrames: remove zone.js stack from `stackTrace`, and add `zone` information. Without this patch, a lot of `zone.js` invocation stack will be shown
in stack frames.
```
at zone.run (polyfill.bundle.js: 3424)
at zoneDelegate.invokeTask (polyfill.bundle.js: 3424)
at zoneDelegate.runTask (polyfill.bundle.js: 3424)
at zone.drainMicroTaskQueue (polyfill.bundle.js: 3424)
at a.b.c (vendor.bundle.js: 12345 <angular>)
at d.e.f (main.bundle.js: 23456)
```
with this patch, those zone frames will be removed,
and the zone information `<angular>/<root>` will be added
```
at a.b.c (vendor.bundle.js: 12345 <angular>)
at d.e.f (main.bundle.js: 23456 <root>)
```
The second feature will slow down the `Error` performance, so `zone.js` provide a flag to let you be able to control the behavior.
The flag is `__Zone_Error_BlacklistedStackFrames_policy`. And the available options is:
1. default: this is the default one, if you load `zone.js/dist/zone-error` without
setting the flag, `default` will be used, and `BlackListStackFrames` will be available
when `new Error()`, you can get a `error.stack` which is `zone stack free`. But this
will slow down `new Error()` a little bit.
2. disable: this will disable `BlackListZoneStackFrame` feature, and if you load
`zone.js/dist/zone-error`, you will only get a `wrapped Error` which can handle
`Error inherit` issue.
3. lazy: this is a feature to let you be able to get `BlackListZoneStackFrame` feature,
but not impact performance. But as a trade off, you can't get the `zone free stack
frames` by access `error.stack`. You can only get it by access `error.zoneAwareStack`.
- Angular(2+)
Angular uses zone.js to manage async operations and decide when to perform change detection. Thus, in Angular,
the following APIs should be patched, otherwise Angular may not work as expected.
1. ZoneAwarePromise
2. timer
3. on_property
4. EventTarget
5. XHR
+229
View File
@@ -0,0 +1,229 @@
# Zone.js's support for non standard apis
Zone.js patched most standard APIs such as DOM event listeners, XMLHttpRequest in Browser, EventEmitter and fs API in Node.js so they can be in zone.
But there are still a lot of non standard APIs that are not patched by default, such as MediaQuery, Notification,
WebAudio and so on. We are adding support to those APIs, and our progress is updated here.
## Currently supported non standard Web APIs
* MediaQuery
* Notification
## Currently supported polyfills
* webcomponents
Usage:
```
<script src="webcomponents-lite.js"></script>
<script src="node_modules/zone.js/dist/zone.js"></script>
<script src="node_modules/zone.js/dist/webapis-shadydom.js"></script>
```
## Currently supported non standard node APIs
## Currently supported non standard common APIs
* bluebird promise
Browser Usage:
```
<script src="zone.js"></script>
<script src="bluebird.js"></script>
<script src="zone-bluebird.js"></script>
<script>
Zone[Zone['__symbol__']('bluebird')](Promise);
</script>
```
After those steps, window.Promise will become a ZoneAware Bluebird Promise.
Node Sample Usage:
```
require('zone.js');
const Bluebird = require('bluebird');
require('zone.js/dist/zone-bluebird');
Zone[Zone['__symbol__']('bluebird')](Bluebird);
Zone.current.fork({
name: 'bluebird'
}).run(() => {
Bluebird.resolve(1).then(r => {
console.log('result ', r, 'Zone', Zone.current.name);
});
});
```
In NodeJS environment, you can choose to use Bluebird Promise as global.Promise
or use ZoneAwarePromise as global.Promise.
To run the jasmine test cases of bluebird
```
npm install bluebird
```
then modify test/node_tests.ts
remove the comment of the following line
```
//import './extra/bluebird.spec';
```
## Others
* Cordova
patch `cordova.exec` API
`cordova.exec(success, error, service, action, args);`
`success` and `error` will be patched with `Zone.wrap`.
to load the patch, you should load in the following order.
```
<script src="zone.js"></script>
<script src="cordova.js"></script>
<script src="zone-patch-cordova.js"></script>
```
## Usage
By default, those APIs' support will not be loaded in zone.js or zone-node.js,
so if you want to load those API's support, you should load those files by yourself.
For example, if you want to add MediaQuery patch, you should do like this:
```
<script src="path/zone.js"></script>
<script src="path/webapis-media-query.js"></script>
```
* rxjs
`zone.js` also provide a `rxjs` patch to make sure rxjs Observable/Subscription/Operator run in correct zone.
For details please refer to [pull request 843](https://github.com/angular/zone.js/pull/843). The following sample code describes the idea.
```
const constructorZone = Zone.current.fork({name: 'constructor'});
const subscriptionZone = Zone.current.fork({name: 'subscription'});
const operatorZone = Zone.current.fork({name: 'operator'});
let observable;
let subscriber;
constructorZone.run(() => {
observable = new Observable((_subscriber) => {
subscriber = _subscriber;
console.log('current zone when construct observable:', Zone.current.name); // will output constructor.
return () => {
console.log('current zone when unsubscribe observable:', Zone.current.name); // will output constructor.
}
});
});
subscriptionZone.run(() => {
observable.subscribe(() => {
console.log('current zone when subscription next', Zone.current.name); // will output subscription.
}, () => {
console.log('current zone when subscription error', Zone.current.name); // will output subscription.
}, () => {
console.log('current zone when subscription complete', Zone.current.name); // will output subscription.
});
});
operatorZone.run(() => {
observable.map(() => {
console.log('current zone when map operator', Zone.current.name); // will output operator.
});
});
```
Currently basically everything the `rxjs` API includes
- Observable
- Subscription
- Subscriber
- Operators
- Scheduler
is patched, so each asynchronous call will run in the correct zone.
## Usage.
For example, in an Angular application, you can load this patch in your `app.module.ts`.
```
import 'zone.js/dist/zone-patch-rxjs';
```
* electron
In electron, we patched the following APIs with `zone.js`
1. Browser API
2. NodeJS
3. Electorn Native API
## Usage.
add following line into `polyfill.ts` after loading zone-mix.
```
//import 'zone.js/dist/zone'; // originally added by angular-cli, comment it out
import 'zone.js/dist/zone-mix'; // add zone-mix to patch both Browser and Nodejs
import 'zone.js/dist/zone-patch-electron'; // add zone-patch-electron to patch Electron native API
```
there is a sampel repo [zone-electron](https://github.com/JiaLiPassion/zone-electron).
* socket.io-client
user need to patch `io` themselves just like following code.
```javascript
<script src="socket.io-client/dist/socket.io.js"></script>
<script src="zone.js/dist/zone.js"></script>
<script src="zone.js/dist/zone-patch-socket-io.js"></script>
<script>
// patch io here
Zone[Zone.__symbol__('socketio')](io);
</script>
```
please reference the sample repo [zone-socketio](https://github.com/JiaLiPassion/zone-socketio) about
detail usage.
* jsonp
## Usage.
provide a helper method to patch jsonp. Because jsonp has a lot of implementation, so
user need to provide the information to let json `send` and `callback` in zone.
there is a sampel repo [zone-jsonp](https://github.com/JiaLiPassion/test-zone-js-with-jsonp) here,
sample usage is:
```javascript
import 'zone.js/dist/zone-patch-jsonp';
Zone['__zone_symbol__jsonp']({
jsonp: getJSONP,
sendFuncName: 'send',
successFuncName: 'jsonpSuccessCallback',
failedFuncName: 'jsonpFailedCallback'
});
```
* ResizeObserver
Currently only `Chrome 64` native support this feature.
you can add the following line into `polyfill.ts` after loading `zone.js`.
```
import 'zone.js/dist/zone';
import 'zone.js/dist/zone-patch-resize-observer';
```
there is a sample repo [zone-resize-observer](https://github.com/JiaLiPassion/zone-resize-observer) here
+92
View File
@@ -0,0 +1,92 @@
# Zone.js
[![CDNJS](https://img.shields.io/cdnjs/v/zone.js.svg)](https://cdnjs.com/libraries/zone.js)
Implements _Zones_ for JavaScript, inspired by [Dart](https://www.dartlang.org/articles/zones/).
> If you're using zone.js via unpkg (i.e. using `https://unpkg.com/zone.js`)
> and you're using any of the following libraries, make sure you import them first
> * 'newrelic' as it patches global.Promise before zone.js does
> * 'async-listener' as it patches global.setTimeout, global.setInterval before zone.js does
> * 'continuation-local-storage' as it uses async-listener
# NEW Zone.js POST-v0.6.0
See the new API [here](./lib/zone.ts).
Read up on [Zone Primer](https://docs.google.com/document/d/1F5Ug0jcrm031vhSMJEOgp1l-Is-Vf0UCNDY-LsQtAIY).
## What's a Zone?
A Zone is an execution context that persists across async tasks.
You can think of it as [thread-local storage](http://en.wikipedia.org/wiki/Thread-local_storage) for JavaScript VMs.
See this video from ng-conf 2014 for a detailed explanation:
[![screenshot of the zone.js presentation and ng-conf 2014](/presentation.png)](//www.youtube.com/watch?v=3IqtmUscE_U&t=150)
## See also
* [async-listener](https://github.com/othiym23/async-listener) - a similar library for node
* [Async stack traces in Chrome](http://www.html5rocks.com/en/tutorials/developertools/async-call-stack/)
* [strongloop/zone](https://github.com/strongloop/zone) (Deprecated)
* [vizone](https://github.com/gilbox/vizone) - control flow visualizer that uses zone.js
## Standard API support
zone.js patched most standard web APIs (such as DOM events, `XMLHttpRequest`, ...) and nodejs APIs
(`EventEmitter`, `fs`, ...), for more details, please see [STANDARD-APIS.md](STANDARD-APIS.md).
## Nonstandard API support
We are adding support to some nonstandard APIs, such as MediaQuery and
Notification. Please see [NON-STANDARD-APIS.md](NON-STANDARD-APIS.md) for more details.
## Examples
You can find some samples to describe how to use zone.js in [SAMPLE.md](SAMPLE.md).
## Modules
zone.js patches the async APIs described above, but those patches will have some overhead.
Starting from zone.js v0.8.9, you can choose which web API module you want to patch.
For more details, please
see [MODULE.md](MODULE.md).
## Bundles
There are several bundles under `dist` folder.
|Bundle|Summary|
|---|---|
|zone.js|the default bundle, contains the most used APIs such as `setTimeout/Promise/EventTarget...`, also this bundle supports all evergreen and legacy (IE/Legacy Firefox/Legacy Safari) Browsers|
|zone-evergreen.js|the bundle for evergreen browsers, doesn't include the `patch` for `legacy` browsers such as `IE` or old versions of `Firefox/Safari`|
|zone-legacy.js|the patch bundle for legacy browsers, only includes the `patch` for `legacy` browsers such as `IE` or old versions of `Firefox/Safari`. This bundle must be loaded after `zone-evergreen.js`, **`zone.js`=`zone-evergreen.js` + `zone-legacy.js`**|
|zone-testing.js|the bundle for zone testing support, including `jasmine/mocha` support and `async/fakeAsync/sync` test utilities|
|zone-externs.js|the API definitions for `closure compiler`|
And here are the additional optional patches not included in the main zone.js bundles
|Patch|Summary|
|---|---|
|webapis-media-query.js|patch for `MediaQuery APIs`|
|webapis-notification.js|patch for `Notification APIs`|
|webapis-rtc-peer-connection.js|patch for `RTCPeerConnection APIs`|
|webapis-shadydom.js|patch for `Shady DOM APIs`|
|zone-bluebird.js|patch for `Bluebird APIs`|
|zone-error.js|patch for `Error Global Object`, supports remove `Zone StackTrace`|
|zone-patch-canvas.js|patch for `Canvas API`|
|zone-patch-cordova.js|patch for `Cordova API`|
|zone-patch-electron.js|patch for `Electron API`|
|zone-patch-fetch.js|patch for `Fetch API`|
|zone-patch-jsonp.js|utility for `jsonp API`|
|zone-patch-resize-observer.js|patch for `ResizeObserver API`|
|zone-patch-rxjs.js|patch for `rxjs API`|
|zone-patch-rxjs-fake-async.js|patch for `rxjs fakeasync test`|
|zone-patch-socket-io.js|patch for `socket-io`|
|zone-patch-user-media.js|patch for `UserMedia API`|
## Promise A+ test passed
[![Promises/A+ 1.1 compliant](https://promisesaplus.com/assets/logo-small.png)](https://promisesaplus.com/)
## License
MIT
+23
View File
@@ -0,0 +1,23 @@
# Sample
### Basic Sample
use `zone.js` and `long-stack-trace-zone.js` to display longStackTrace information in html.
[basic](https://stackblitz.com/edit/zonejs-basic?file=index.js)
### Async Task Counting Sample
use `zone.js` to monitor async tasks and print the count info.
[counting](https://stackblitz.com/edit/zonejs-counting?file=index.js)
### Profiling Sample
use `zone.js` to profiling sort algorithm.
[profiling](https://stackblitz.com/edit/zonejs-profiling?file=index.js)
### Throttle with longStackTrace
use `long-stack-trace-zone` to display full flow of complex async operations such as throttle XHR requests.
[throttle](https://stackblitz.com/edit/zonejs-throttle?file=index.js)
+148
View File
@@ -0,0 +1,148 @@
# Zone.js's support for standard apis
Zone.js patched most standard APIs such as DOM event listeners, XMLHttpRequest in Browser, EventEmitter and fs API in Node.js so they can be in zone.
In this document, all patched API are listed.
For non-standard APIs, please see [NON-STANDARD-APIS.md](NON-STANDARD-APIS.md)
## Patch Mechanisms
There are several patch mechanisms
- wrap: makes callbacks run in zones, and makes applications able to receive onInvoke and onIntercept callbacks
- Task: just like in the JavaScript VM, applications can receive onScheduleTask, onInvokeTask, onCancelTask and onHasTask callbacks
1. MacroTask
2. MicroTask
3. EventTask
Some APIs which should be treated as Tasks, but are currently still patched in the wrap way. These will be patched as Tasks soon.
## Browser
Web APIs
| API | Patch Mechanism | Others |
| --- | --- | --- |
| setTimeout/clearTimeout | MacroTask | app can get handlerId, interval, args, isPeriodic(false) through task.data |
| setImmediate/clearImmediate | MacroTask | same with setTimeout |
| setInterval/clearInterval | MacroTask | isPeriodic is true, so setInterval will not trigger onHasTask callback |
| requestAnimationFrame/cancelAnimationFrame | MacroTask | |
| mozRequestAnimationFrame/mozCancelAnimationFrame | MacroTask | |
| webkitRequestAnimationFrame/webkitCancelAnimationFrame | MacroTask | |
| alert | wrap | |
| prompt | wrap | |
| confirm | wrap | |
| Promise | MicroTask | |
| EventTarget | EventTask | see below Event Target for more details |
| HTMLElement on properties | EventTask | see below on properties for more details |
| XMLHttpRequest.send/abort | MacroTask | |
| XMLHttpRequest on properties | EventTask | |
| IDBIndex on properties | EventTask | |
| IDBRequest on properties | EventTask | |
| IDBOpenDBRequest on properties | EventTask | |
| IDBDatabaseRequest on properties | EventTask | |
| IDBTransaction on properties | EventTask | |
| IDBCursor on properties | EventTask | |
| WebSocket on properties | EventTask | |
| MutationObserver | wrap | |
| WebkitMutationObserver | wrap | |
| FileReader | wrap | |
| registerElement | wrap | |
EventTarget
- For browsers supporting EventTarget, Zone.js just patches EventTarget, so everything that inherits
from EventTarget will also be patched.
- For browsers that do not support EventTarget, Zone.js will patch the following APIs in the IDL
that inherit from EventTarget
|||||
|---|---|---|---|
|ApplicationCache|EventSource|FileReader|InputMethodContext|
|MediaController|MessagePort|Node|Performance|
|SVGElementInstance|SharedWorker|TextTrack|TextTrackCue|
|TextTrackList|WebKitNamedFlow|Window|Worker|
|WorkerGlobalScope|XMLHttpRequest|XMLHttpRequestEventTarget|XMLHttpRequestUpload|
|IDBRequest|IDBOpenDBRequest|IDBDatabase|IDBTransaction|
|IDBCursor|DBIndex|WebSocket|
The following 'on' properties, such as onclick, onreadystatechange, are patched in Zone.js as EventTasks
|||||
|---|---|---|---|
|copy|cut|paste|abort|
|blur|focus|canplay|canplaythrough|
|change|click|contextmenu|dblclick|
|drag|dragend|dragenter|dragleave|
|dragover|dragstart|drop|durationchange|
|emptied|ended|input|invalid|
|keydown|keypress|keyup|load|
|loadeddata|loadedmetadata|loadstart|message|
|mousedown|mouseenter|mouseleave|mousemove|
|mouseout|mouseover|mouseup|pause|
|play|playing|progress|ratechange|
|reset|scroll|seeked|seeking|
|select|show|stalled|submit|
|suspend|timeupdate|volumechange|waiting|
|mozfullscreenchange|mozfullscreenerror|mozpointerlockchange|mozpointerlockerror|
|error|webglcontextrestored|webglcontextlost|webglcontextcreationerror|
## NodeJS
| API | Patch Mechanism | Others |
| --- | --- | --- |
| setTimeout/clearTimeout | MacroTask | app can get handlerId, interval, args, isPeriodic(false) through task.data |
| setImmediate/clearImmediate | MacroTask | same with setTimeout |
| setInterval/clearInterval | MacroTask | isPeriodic is true, so setInterval will not trigger onHasTask callback |
| process.nextTick | Microtask | isPeriodic is true, so setInterval will not trigger onHasTask callback |
| Promise | MicroTask | |
| EventEmitter | EventTask | All APIs inherit EventEmitter are patched as EventTask |
| crypto | MacroTask | |
| fs | MacroTask | all async methods are patched |
EventEmitter, addEventListener, prependEventListener and 'on' will be patched once as EventTasks, and removeEventListener and
removeAllListeners will remove those EventTasks
## Electron
Zone.js does not patch the Electron API, although in Electron both browser APIs and node APIs are patched, so
if you want to include Zone.js in Electron, please use dist/zone-mix.js
## ZoneAwareError
ZoneAwareError replaces global Error, and adds zone information to stack trace.
ZoneAwareError also handles 'this' issue.
This type of issue would happen when creating an error without `new`: `this` would be `undefined` in strict mode, and `global` in
non-strict mode. It could cause some very difficult to detect issues.
```javascript
const error = Error();
```
ZoneAwareError makes sure that `this` is ZoneAwareError even without new.
## ZoneAwarePromise
ZoneAwarePromise wraps the global Promise and makes it run in zones as a MicroTask.
It also passes promise A+ tests.
## BlackListEvents
Sometimes we don't want some `event` to be patched by `zone.js`, we can blacklist events
by following settings.
```javascript
// disable on properties
var targets = [window, Document, HTMLBodyElement, HTMLElement];
__Zone_ignore_on_properties = [];
targets.forEach(function (target) {
__Zone_ignore_on_properties.push({
target: target,
ignoreProperties: ['scroll']
});
});
// disable addEventListener
global['__zone_symbol__BLACK_LISTED_EVENTS'] = ['scroll'];
```
+50
View File
@@ -0,0 +1,50 @@
"""
Describe all the output bundles in the zone.js npm package
by mapping the bundle name to the source location.
"""
_DIR = "//packages/zone.js/lib:"
ES5_GLOBAL_BUNDLES = {
"zone": _DIR + "browser/rollup-legacy-main",
"zone-mix": _DIR + "mix/rollup-mix",
"zone-node": _DIR + "node/rollup-main",
"zone-testing-node-bundle": _DIR + "node/rollup-test-main",
}
ES5_BUNDLES = {
"async-test": _DIR + "testing/async-testing",
"fake-async-test": _DIR + "testing/fake-async",
"long-stack-trace-zone": _DIR + "zone-spec/long-stack-trace",
"proxy": _DIR + "zone-spec/proxy",
"zone-patch-rxjs-fake-async": _DIR + "rxjs/rxjs-fake-async",
"sync-test": _DIR + "zone-spec/sync-test",
"task-tracking": _DIR + "zone-spec/task-tracking",
"wtf": _DIR + "zone-spec/wtf",
"zone-error": _DIR + "common/error-rewrite",
"zone-legacy": _DIR + "browser/browser-legacy",
"zone-bluebird": _DIR + "extra/bluebird",
"zone-patch-canvas": _DIR + "browser/canvas",
"zone-patch-cordova": _DIR + "extra/cordova",
"zone-patch-electron": _DIR + "extra/electron",
"zone-patch-fetch": _DIR + "common/fetch",
"jasmine-patch": _DIR + "jasmine/jasmine",
"zone-patch-jsonp": _DIR + "extra/jsonp",
"webapis-media-query": _DIR + "browser/webapis-media-query",
"mocha-patch": _DIR + "mocha/mocha",
"webapis-notification": _DIR + "browser/webapis-notification",
"zone-patch-promise-test": _DIR + "testing/promise-testing",
"zone-patch-resize-observer": _DIR + "browser/webapis-resize-observer",
"webapis-rtc-peer-connection": _DIR + "browser/webapis-rtc-peer-connection",
"zone-patch-rxjs": _DIR + "rxjs/rxjs",
"webapis-shadydom": _DIR + "browser/shadydom",
"zone-patch-socket-io": _DIR + "extra/socket-io",
"zone-patch-user-media": _DIR + "browser/webapis-user-media",
"zone-testing": _DIR + "testing/zone-testing",
"zone-testing-bundle": _DIR + "browser/rollup-legacy-test-main",
}
ES2015_BUNDLES = {
"zone-evergreen": _DIR + "browser/rollup-main",
"zone-evergreen-testing-bundle": _DIR + "browser/rollup-test-main",
}
+28
View File
@@ -0,0 +1,28 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
const fs = require('fs');
module.exports = function(config) {
let chkResult = true;
config.targets.forEach(target => {
if (target.checkTarget) {
try {
const stats = fs.statSync(target.path);
if (stats.size > target.limit) {
console.error(
`file ${target.path} size over limit, limit is ${target.limit}, actual is ${stats.size}`);
chkResult = false;
}
} catch (err) {
console.error(`failed to get filesize: ${target.path}`);
chkResult = false;
}
}
});
return chkResult;
};
+200
View File
@@ -0,0 +1,200 @@
load("@build_bazel_rules_nodejs//:defs.bzl", "rollup_bundle")
load("//packages/zone.js:bundles.bzl", "ES2015_BUNDLES", "ES5_BUNDLES", "ES5_GLOBAL_BUNDLES")
package(default_visibility = ["//packages/zone.js:__subpackages__"])
# copy this file from //lib to //dist
genrule(
name = "zone_externs",
srcs = ["//packages/zone.js/lib:closure/zone_externs.js"],
outs = ["zone_externs.js"],
cmd = "cp $< $@",
)
genrule(
name = "zone_d_ts",
srcs = ["//packages/zone.js/lib"],
outs = ["zone.js.d.ts"],
cmd = "find $(SRCS) -name \"zone.d.ts\" -exec cp {} $(@D)/zone.js.d.ts \;",
)
[
rollup_bundle(
name = b[0].replace("-", "_") + "_rollup",
entry_point = b[1] + ".ts",
globals = {
"electron": "electron",
},
license_banner = "//packages:license-banner.txt",
deps = [
"//packages/zone.js/lib",
],
)
for b in ES5_BUNDLES.items()
]
[
rollup_bundle(
name = b[0].replace("-", "_") + "_rollup",
entry_point = b[1] + ".ts",
global_name = "Zone",
license_banner = "//packages:license-banner.txt",
deps = [
"//packages/zone.js/lib",
],
)
for b in ES5_GLOBAL_BUNDLES.items() + ES2015_BUNDLES.items()
]
# the es5 filegroups
[
filegroup(
name = b[0] + ".es5",
srcs = [":" + b[0].replace("-", "_") + "_rollup"],
output_group = "es5_umd",
)
for b in ES5_BUNDLES.items() + ES5_GLOBAL_BUNDLES.items()
]
# the es5.min filegroups
[
filegroup(
name = b[0] + ".es5.min",
srcs = [":" + b[0].replace("-", "_") + "_rollup"],
output_group = "es5_umd_min",
)
for b in ES5_BUNDLES.items() + ES5_GLOBAL_BUNDLES.items()
]
# the es2015 filegroups
[
filegroup(
name = b[0] + ".umd",
srcs = [":" + b[0].replace("-", "_") + "_rollup"],
output_group = "umd",
)
for b in ES2015_BUNDLES.items()
]
# the es2015.min filegroups
[
filegroup(
name = b[0] + ".umd.min",
srcs = [":" + b[0].replace("-", "_") + "_rollup"],
output_group = "umd_min",
)
for b in ES2015_BUNDLES.items()
]
# Extract and rename each es5 bundle to a .js and .min.js in the dist/ dir
[
genrule(
name = b[0] + "-dist",
srcs = [
b[0] + ".es5",
b[0] + ".es5.min",
],
outs = [
b[0] + ".js",
b[0] + ".min.js",
],
cmd = " && ".join([
"mkdir -p $(@D)",
"cp $(@D)/" + b[0].replace("-", "_") + "_rollup.es5umd.js $(@D)/" + b[0] + ".js",
"cp $(@D)/" + b[0].replace("-", "_") + "_rollup.min.es5umd.js $(@D)/" + b[0] + ".min.js",
]),
)
for b in ES5_BUNDLES.items() + ES5_GLOBAL_BUNDLES.items()
]
# Extract and rename each es5 bundle to a .js and .min.js in the dist/ dir
[
genrule(
name = b[0] + "-dist-dev-test",
srcs = [
b[0] + ".es5",
],
outs = [
b[0] + ".dev.test.js",
],
cmd = " && ".join([
"mkdir -p $(@D)",
"cp $(@D)/" + b[0].replace("-", "_") + "_rollup.es5umd.js $(@D)/" + b[0] + ".dev.test.js",
]),
)
for b in ES5_BUNDLES.items() + ES5_GLOBAL_BUNDLES.items()
]
[
genrule(
name = b + "-dist-dev-test",
srcs = [
b + ".umd",
],
outs = [
b + ".dev.test.js",
],
cmd = " && ".join([
"mkdir -p $(@D)",
"cp $(@D)/" + b.replace("-", "_") + "_rollup.umd.js $(@D)/" + b + ".dev.test.js",
]),
)
for b in ES2015_BUNDLES
]
# Extract and rename each es5 bundle to a .js and .min.js in the dist/ dir
[
genrule(
name = b[0] + "-dist-test",
srcs = [
b[0] + ".es5.min",
],
outs = [
b[0] + ".test.min.js",
],
cmd = " && ".join([
"mkdir -p $(@D)",
"cp $(@D)/" + b[0].replace("-", "_") + "_rollup.min.es5umd.js $(@D)/" + b[0] + ".test.min.js",
]),
)
for b in ES5_BUNDLES.items() + ES5_GLOBAL_BUNDLES.items()
]
# Extract and rename each es2015 bundle to a .js and .min.js in the dist/ dir
[
genrule(
name = b + "-dist",
srcs = [
b + ".umd",
b + ".umd.min",
],
outs = [
b + ".js",
b + ".min.js",
],
cmd = " && ".join([
"mkdir -p $(@D)",
"cp $(@D)/" + b.replace("-", "_") + "_rollup.umd.js $(@D)/" + b + ".js",
"cp $(@D)/" + b.replace("-", "_") + "_rollup.min.umd.js $(@D)/" + b + ".min.js",
]),
)
for b in ES2015_BUNDLES
]
# Extract and rename each es5 bundle to a .js and .min.js in the dist/ dir
[
genrule(
name = b + "-dist-test",
srcs = [
b + ".umd.min",
],
outs = [
b + ".test.min.js",
],
cmd = " && ".join([
"mkdir -p $(@D)",
"cp $(@D)/" + b.replace("-", "_") + "_rollup.min.umd.js $(@D)/" + b + ".test.min.js",
]),
)
for b in ES2015_BUNDLES
]
Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

+9
View File
@@ -0,0 +1,9 @@
@startuml
scheduling --> unknown: zoneSpec.onScheduleTask\nor task.scheduleFn\nthrow error
running --> scheduled: error in \ntask.callback\nand task is\nperiodical\ntask
running --> notScheduled: error in\ntask.callback\nand\ntask is not\nperiodical
running: zoneSpec.onHandleError
running --> throw: error in\n task.callback\n and \nzoneSpec.onHandleError\n return true
canceling --> unknown: zoneSpec.onCancelTask\n or task.cancelFn\n throw error
unknown --> throw
@enduml
Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

+21
View File
@@ -0,0 +1,21 @@
@startuml
[*] --> notScheduled: initialize
notScheduled --> scheduling: addEventListener
scheduling: zoneSpec.onScheduleTask
scheduling: zoneSpec.onHasTask
scheduling --> scheduled
scheduled --> running: event\n triggered
running: zoneSpec:onInvokeTask
scheduled --> canceling: removeEventListener
canceling: zoneSpec.onCancelTask
canceling --> notScheduled
canceling: zoneSpec.onHasTask
running --> scheduled: callback\n finished
running: zoneSpec.onHasTask
running --> canceling: removeEventListener
@enduml
Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

+14
View File
@@ -0,0 +1,14 @@
@startuml
[*] --> notScheduled: initialize
notScheduled --> scheduling: promise.then/\nprocess.nextTick\nand so on
scheduling: zoneSpec.onScheduleTask
scheduling: zoneSpec.onHasTask
scheduling --> scheduled
scheduled --> running: callback
running: zoneSpec:onInvokeTask
running --> notScheduled
running: zoneSpec.onHasTask
@enduml
Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

@@ -0,0 +1,18 @@
@startuml
[*] --> notScheduled: initialize
notScheduled --> scheduling: setTimeout/\nXMLHttpRequest.send\nand so on
scheduling: zoneSpec.onScheduleTask
scheduling: zoneSpec.onHasTask
scheduling --> scheduled
scheduled --> running: timeout callback\nreadystatechange\ncallback
running: zoneSpec:onInvokeTask
scheduled --> canceling: clearTimeout\n/abort request
canceling: zoneSpec.onCancelTask
canceling --> notScheduled
canceling: zoneSpec.onHasTask
running --> notScheduled
running: zoneSpec.onHasTask
@enduml
Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

+18
View File
@@ -0,0 +1,18 @@
@startuml
[*] --> notScheduled: initialize
notScheduled --> scheduling: scheduleTask
scheduling: zoneSpec.onScheduleTask
scheduling: zoneSpec.onHasTask
scheduling --> scheduled: override with\n anotherZone
scheduled --> running: timeout callback\nreadystatechange\ncallback
running: anotherZoneSpec:onInvokeTask
scheduled --> canceling: clearTimeout\n/abort request
canceling: anotherZoneSpec.onCancelTask
canceling --> notScheduled
canceling: zneSpec.onHasTask
running --> notScheduled
running: zoneSpec.onHasTask
@enduml
Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

@@ -0,0 +1,18 @@
@startuml
[*] --> notScheduled: initialize
notScheduled --> scheduling: setInterval
scheduling: zoneSpec.onScheduleTask
scheduling: zoneSpec.onHasTask
scheduling --> scheduled
scheduled --> running: interval\n callback
running: zoneSpec:onInvokeTask
scheduled --> canceling: clearInterval
canceling: zoneSpec.onCancelTask
canceling --> notScheduled
canceling: zoneSpec.onHasTask
running --> scheduled: callback\n finished
running --> canceling: clearInterval
@enduml
Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

+20
View File
@@ -0,0 +1,20 @@
@startuml
[*] --> notScheduled: initialize
notScheduled --> scheduling: ①current zone\n scheduleTask
notScheduled --> scheduling: ③anotherZone\n scheduleTask
scheduling: anotherZoneSpec.onScheduleTask
scheduling: anotherZoneSpec.onHasTask
scheduling --> notScheduled: ②cancelScheduleRequest
scheduling --> scheduled
scheduled --> running: callback
running: anotherZoneSpec:onInvokeTask
scheduled --> canceling: cancelTask
canceling: anotherZoneSpec.onCancelTask
canceling --> notScheduled
canceling: anotherZoneSpec.onHasTask
running --> notScheduled
running: anotherZoneSpec.onHasTask
@enduml
+80
View File
@@ -0,0 +1,80 @@
## Task lifecycle
We handle several kinds of tasks in zone.js,
- MacroTask
- MicroTask
- EventTask
For details, please refer to [here](../dist/zone.js.d.ts)
This document will explain the lifecycle (state-transition) of different types of tasks and also the triggering of various zonespec's callback during that cycle.
The motivation to write this document has come from this [PR](https://github.com/angular/zone.js/pull/629) of @mhevery. This has made the task's state more clear. Also, tasks can now be cancelled and rescheduled in different zone.
### MicroTask
Such as Promise.then, process.nextTick, they are microTasks, the lifecycle(state transition)
looks like this.
![MicroTask](microtask.png "MicroTask")
ZoneSpec's onHasTask callback will be triggered when the first microTask were scheduled or the
last microTask was invoked.
### EventTask
Such as EventTarget's EventListener, EventEmitter's EventListener, their lifecycle(state transition)
looks like this.
![EventTask](eventtask.png "EventTask")
ZoneSpec's onHasTask callback will be triggered when the first eventTask were scheduled or the
last eventTask was cancelled.
EventTask will go back to scheduled state after invoked(running state), and will become notScheduled after cancelTask(such as removeEventListener)
### MacroTask
#### Non Periodical MacroTask
Such as setTimeout/XMLHttpRequest, their lifecycle(state transition)
looks like this.
![non-periodical-macroTask](non-periodical-macrotask.png "non periodical macroTask")
ZoneSpec's onHasTask callback will be triggered when the first macroTask were scheduled or the
last macroTask was invoked or cancelled.
Non periodical macroTask will become notScheduled after being invoked or being cancelled(such as clearTimeout)
#### Periodical MacroTask
Such as setInterval, their lifecycle(state transition)
looks like this.
![periodical-MacroTask](periodical-macrotask.png "periodical MacroTask")
ZoneSpec's onHasTask callback will be triggered when first macroTask was scheduled or last macroTask
was cancelled, it will not triggered after invoke, because it is periodical and become scheduled again.
Periodical macroTask will go back to scheduled state after invoked(running state), and will become notScheduled after cancelTask(such as clearInterval)
### Reschedule Task to a new zone
Sometimes you may want to reschedule task into different zone, the lifecycle looks like
![reschedule-task](reschedule-task.png "reschedule task")
the ZoneTask's cancelScheduleRequest method can be only called in onScheduleTask callback of ZoneSpec,
because it is still under scheduling state.
And after rescheduling, the task will be scheduled to new zone(the otherZoneSpec in the graph),
and will have nothing todo with the original zone.
### Override zone when scheduling
Sometimes you may want to just override the zone when scheduling, the lifecycle looks like
![override-task](override-task.png "override task")
After overriding, the task will be invoked/cancelled in the new zone(the otherZoneSpec in the graph),
but hasTask callback will still be invoked in original zone.
### Error occurs in task lifecycle
![error](error.png "error")

Some files were not shown because too many files have changed in this diff Show More