Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TEST ONLY: Combined ZoneJS changes for g3 testing #36043

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/zone.js/MODULE.md
Expand Up @@ -43,6 +43,7 @@ Below is the full list of currently supported modules.
|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|
|MessagePort|MessagePort onProperties APIs will be patched as Zone aware EventTask. (By default, MessagePort patch will not be loaded by zone.js) |__Zone_disable_MessagePort = true|

- NodeJS

Expand Down
1 change: 1 addition & 0 deletions packages/zone.js/bundles.bzl
Expand Up @@ -39,6 +39,7 @@ ES5_BUNDLES = {
"zone-patch-rxjs": _DIR + "rxjs/rxjs",
"webapis-shadydom": _DIR + "browser/shadydom",
"zone-patch-socket-io": _DIR + "extra/socket-io",
"zone-patch-message-port": _DIR + "browser/message-port",
"zone-patch-user-media": _DIR + "browser/webapis-user-media",
"zone-testing": _DIR + "testing/zone-testing",
"zone-testing-bundle": _DIR + "browser/rollup-legacy-test-main",
Expand Down
18 changes: 18 additions & 0 deletions packages/zone.js/lib/browser/message-port.ts
@@ -0,0 +1,18 @@
/**
* @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
*/

/**
* Monkey patch `MessagePort.prototype.onmessage` and `MessagePort.prototype.onmessageerror`
* properties to make the callback in the zone when the value are set.
*/
Zone.__load_patch('MessagePort', (global: any, Zone: ZoneType, api: _ZonePrivate) => {
const MessagePort = global['MessagePort'];
if (typeof MessagePort !== 'undefined' && MessagePort.prototype) {
api.patchOnProperties(MessagePort.prototype, ['message', 'messageerror']);
}
});
50 changes: 29 additions & 21 deletions packages/zone.js/lib/common/promise.ts
Expand Up @@ -20,6 +20,8 @@ Zone.__load_patch('ZoneAwarePromise', (global: any, Zone: ZoneType, api: _ZonePr

const __symbol__ = api.symbol;
const _uncaughtPromiseErrors: UncaughtPromiseError[] = [];
const isDisableWrappingUncaughtPromiseRejection =
global[__symbol__('DISABLE_WRAPPING_UNCAUGHT_PROMISE_REJECTION')] === true;
const symbolPromise = __symbol__('Promise');
const symbolThen = __symbol__('then');
const creationTrace = '__creationTrace__';
Expand All @@ -41,13 +43,11 @@ Zone.__load_patch('ZoneAwarePromise', (global: any, Zone: ZoneType, api: _ZonePr

api.microtaskDrainDone = () => {
while (_uncaughtPromiseErrors.length) {
while (_uncaughtPromiseErrors.length) {
const uncaughtPromiseError: UncaughtPromiseError = _uncaughtPromiseErrors.shift() !;
try {
uncaughtPromiseError.zone.runGuarded(() => { throw uncaughtPromiseError; });
} catch (error) {
handleUnhandledRejection(error);
}
const uncaughtPromiseError: UncaughtPromiseError = _uncaughtPromiseErrors.shift() !;
try {
uncaughtPromiseError.zone.runGuarded(() => { throw uncaughtPromiseError; });
} catch (error) {
handleUnhandledRejection(error);
}
}
};
Expand All @@ -58,7 +58,7 @@ Zone.__load_patch('ZoneAwarePromise', (global: any, Zone: ZoneType, api: _ZonePr
api.onUnhandledError(e);
try {
const handler = (Zone as any)[UNHANDLED_PROMISE_REJECTION_HANDLER_SYMBOL];
if (handler && typeof handler === 'function') {
if (typeof handler === 'function') {
handler.call(this, e);
}
} catch (err) {
Expand Down Expand Up @@ -176,20 +176,28 @@ Zone.__load_patch('ZoneAwarePromise', (global: any, Zone: ZoneType, api: _ZonePr
}
if (queue.length == 0 && state == REJECTED) {
(promise as any)[symbolState] = REJECTED_NO_CATCH;
try {
// try to print more readable error log
throw new Error(
'Uncaught (in promise): ' + readableObjectToString(value) +
(value && value.stack ? '\n' + value.stack : ''));
} catch (err) {
const error: UncaughtPromiseError = err;
error.rejection = value;
error.promise = promise;
error.zone = Zone.current;
error.task = Zone.currentTask !;
_uncaughtPromiseErrors.push(error);
api.scheduleMicroTask(); // to make sure that it is running
let uncaughtPromiseError = value;
if (!isDisableWrappingUncaughtPromiseRejection) {
// If disable wrapping uncaught promise reject
// and the rejected value is an Error object,
// use the value instead of wrapping it.
try {
// Here we throws a new Error to print more readable error log
// and if the value is not an error, zone.js builds an `Error`
// Object here to attach the stack information.
throw new Error(
'Uncaught (in promise): ' + readableObjectToString(value) +
(value && value.stack ? '\n' + value.stack : ''));
} catch (err) {
uncaughtPromiseError = err;
}
}
uncaughtPromiseError.rejection = value;
uncaughtPromiseError.promise = promise;
uncaughtPromiseError.zone = Zone.current;
uncaughtPromiseError.task = Zone.currentTask !;
_uncaughtPromiseErrors.push(uncaughtPromiseError);
api.scheduleMicroTask(); // to make sure that it is running
}
}
}
Expand Down
53 changes: 32 additions & 21 deletions packages/zone.js/lib/rxjs/rxjs.ts
Expand Up @@ -50,22 +50,28 @@ type ZoneSubscriberContext = {
},
set: function(this: Observable<any>, subscribe: any) {
(this as any)._zone = Zone.current;
(this as any)._zoneSubscribe = function(this: ZoneSubscriberContext) {
if (this._zone && this._zone !== Zone.current) {
const tearDown = this._zone.run(subscribe, this, arguments as any);
if (tearDown && typeof tearDown === 'function') {
const zone = this._zone;
return function(this: ZoneSubscriberContext) {
if (zone !== Zone.current) {
return zone.run(tearDown, this, arguments as any);
}
return tearDown.apply(this, arguments);
};
if (!subscribe) {
(this as any)._zoneSubscribe = subscribe;
} else {
(this as any)._zoneSubscribe = function(this: ZoneSubscriberContext) {
if (this._zone && this._zone !== Zone.current) {
const tearDown = this._zone.run(subscribe, this, arguments as any);
if (typeof tearDown === 'function') {
const zone = this._zone;
return function(this: ZoneSubscriberContext) {
if (zone !== Zone.current) {
return zone.run(tearDown, this, arguments as any);
}
return tearDown.apply(this, arguments);
};
} else {
return tearDown;
}
} else {
return subscribe.apply(this, arguments);
}
return tearDown;
}
return subscribe.apply(this, arguments);
};
};
}
}
},
subjectFactory: {
Expand Down Expand Up @@ -113,12 +119,17 @@ type ZoneSubscriberContext = {
},
set: function(this: Subscription, unsubscribe: any) {
(this as any)._zone = Zone.current;
(this as any)._zoneUnsubscribe = function() {
if (this._zone && this._zone !== Zone.current) {
return this._zone.run(unsubscribe, this, arguments);
}
return unsubscribe.apply(this, arguments);
};
if (!unsubscribe) {
(this as any)._zoneUnsubscribe = unsubscribe;
} else {
(this as any)._zoneUnsubscribe = function() {
if (this._zone && this._zone !== Zone.current) {
return this._zone.run(unsubscribe, this, arguments);
} else {
return unsubscribe.apply(this, arguments);
}
};
}
}
}
});
Expand Down
10 changes: 8 additions & 2 deletions packages/zone.js/lib/zone.api.extensions.ts
Expand Up @@ -17,22 +17,28 @@ interface EventTarget {
*
* Remove all event listeners by name for this event target.
*
* This method is optional because it may not be available if you use `noop zone` when
* bootstrapping Angular application or disable the `EventTarget` monkey patch by `zone.js`.
*
* If the `eventName` is provided, will remove event listeners of that name.
* If the `eventName` is not provided, will remove all event listeners associated with
* `EventTarget`.
*
* @param eventName the name of the event, such as `click`. This parameter is optional.
*/
removeAllListeners(eventName?: string): void;
removeAllListeners?(eventName?: string): void;
/**
*
* Retrieve all event listeners by name.
*
* This method is optional because it may not be available if you use `noop zone` when
* bootstrapping Angular application or disable the `EventTarget` monkey patch by `zone.js`.
*
* If the `eventName` is provided, will return an array of event handlers or event listener
* objects of the given event.
* If the `eventName` is not provided, will return all listeners.
*
* @param eventName the name of the event, such as click. This parameter is optional.
*/
eventListeners(eventName?: string): EventListenerOrEventListenerObject[];
eventListeners?(eventName?: string): EventListenerOrEventListenerObject[];
}
11 changes: 11 additions & 0 deletions packages/zone.js/lib/zone.configurations.api.ts
Expand Up @@ -529,6 +529,17 @@ interface ZoneGlobalConfigurations {
* The preceding code makes all scroll event listeners passive.
*/
__zone_symbol__PASSIVE_EVENTS?: boolean;

/**
* Disable wrapping uncaught promise rejection.
*
* By default, `zone.js` wraps the uncaught promise rejection in a new `Error` object
* which contains additional information such as a value of the rejection and a stack trace.
*
* If you set `__zone_symbol__DISABLE_WRAPPING_UNCAUGHT_PROMISE_REJECTION = true;` before
* importing `zone.js`, `zone.js` will not wrap the uncaught promise rejection.
*/
__zone_symbol__DISABLE_WRAPPING_UNCAUGHT_PROMISE_REJECTION?: boolean;
}

/**
Expand Down
27 changes: 26 additions & 1 deletion packages/zone.js/test/BUILD.bazel
Expand Up @@ -33,6 +33,7 @@ ts_library(
],
exclude = [
"common/Error.spec.ts",
"common/promise-disable-wrap-uncaught-promise-rejection.spec.ts",
],
),
deps = [
Expand Down Expand Up @@ -253,7 +254,10 @@ env_entry_point = ":browser-env-setup.ts"

test_srcs = glob(
["browser/*.ts"],
exclude = ["browser/shadydom.spec.ts"],
exclude = [
"browser/shadydom.spec.ts",
"common/promise-disable-wrap-uncaught-promise-rejection.spec.ts",
],
) + [
"extra/cordova.spec.ts",
"mocha-patch.spec.ts",
Expand Down Expand Up @@ -323,3 +327,24 @@ karma_test(
"browser_shadydom_entry_point.ts",
],
)

karma_test(
name = "browser_disable_wrap_uncaught_promise_rejection",
bootstraps = {"browser_disable_wrap_uncaught_promise_rejection": [
"//packages/zone.js/dist:zone-testing-bundle.js",
]},
ci = False,
env_deps = [
"//packages/zone.js/lib",
],
env_entry_point = ":browser_disable_wrap_uncaught_promise_rejection_setup.ts",
env_srcs = ["browser_disable_wrap_uncaught_promise_rejection_setup.ts"],
test_deps = [
"//packages/zone.js/lib",
],
test_entry_point = ":browser_disable_wrap_uncaught_promise_rejection_entry_point.ts",
test_srcs = [
"common/promise-disable-wrap-uncaught-promise-rejection.spec.ts",
"browser_disable_wrap_uncaught_promise_rejection_entry_point.ts",
],
)