|
|
@@ -0,0 +1,159 @@
|
|
|
+//-------------------------------------------------------------------------------------------------------
|
|
|
+// Copyright (C) Microsoft. All rights reserved.
|
|
|
+// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
|
|
+//-------------------------------------------------------------------------------------------------------
|
|
|
+
|
|
|
+/**exception(uncaught):stack();**/
|
|
|
+
|
|
|
+function unhandledPromiseRejection1() {
|
|
|
+ Promise.resolve(true)
|
|
|
+ .then(() => {
|
|
|
+ throw new Error('error for unhandledPromiseRejection1')
|
|
|
+ });
|
|
|
+}
|
|
|
+unhandledPromiseRejection1();
|
|
|
+
|
|
|
+function unhandledPromiseRejection2() {
|
|
|
+ Promise.resolve(true)
|
|
|
+ .then(() => {
|
|
|
+ throw new Error('error for unhandledPromiseRejection2');
|
|
|
+ })
|
|
|
+ .then(() => {
|
|
|
+ // no catch
|
|
|
+ });
|
|
|
+}
|
|
|
+unhandledPromiseRejection2();
|
|
|
+
|
|
|
+function unhandledPromiseRejection3() {
|
|
|
+ let p = Promise.resolve(true)
|
|
|
+ .then(() => {
|
|
|
+ throw new Error('error for unhandledPromiseRejection3');
|
|
|
+ })
|
|
|
+ .then(() => 0);
|
|
|
+ p.then(() => 0).then(() => 1); // this path is not caught
|
|
|
+ p.then(() => 2, (err) => { }); // this path is caught
|
|
|
+
|
|
|
+}
|
|
|
+unhandledPromiseRejection3();
|
|
|
+
|
|
|
+function unhandledPromiseRejection4() {
|
|
|
+ let p = Promise.resolve(true)
|
|
|
+ .then(() => {
|
|
|
+ throw new Error('error for unhandledPromiseRejection3');
|
|
|
+ })
|
|
|
+ .catch((err) => {
|
|
|
+ throw err;
|
|
|
+ });
|
|
|
+}
|
|
|
+unhandledPromiseRejection4();
|
|
|
+
|
|
|
+function handledPromiseRejection5() {
|
|
|
+ Promise.resolve(true)
|
|
|
+ .then(() => {
|
|
|
+ throw new Error('error for handledPromiseRejection5')
|
|
|
+ }).catch(() => { });
|
|
|
+}
|
|
|
+handledPromiseRejection5();
|
|
|
+
|
|
|
+function handledPromiseRejection6() {
|
|
|
+ Promise.resolve(true)
|
|
|
+ .then(() => {
|
|
|
+ throw new Error('error for handledPromiseRejection6');
|
|
|
+ })
|
|
|
+ .then(() => { }, () => { });
|
|
|
+}
|
|
|
+handledPromiseRejection6()
|
|
|
+
|
|
|
+function handledPromiseRejection7() {
|
|
|
+ let p = Promise.resolve(true)
|
|
|
+ .then(() => {
|
|
|
+ throw new Error('error for handledPromiseRejection7');
|
|
|
+ })
|
|
|
+ .then(() => 0);
|
|
|
+ p.then(() => 0).then(() => 1).catch(() => { }); // this path is caught
|
|
|
+ p.then(() => 2, (err) => { }); // this path is caught
|
|
|
+
|
|
|
+}
|
|
|
+handledPromiseRejection7();
|
|
|
+
|
|
|
+//
|
|
|
+// validate that when we have a handler from one script context
|
|
|
+// and a promise from another script context, we'll break appropriately
|
|
|
+//
|
|
|
+function unhandledPromiseRejectionCrossContext() {
|
|
|
+ var external = WScript.LoadScriptFile("JsDiagExceptionsInPromises_BreakOnFirstChanceExceptions.crosscontext.js", "samethread");
|
|
|
+ let p = Promise.prototype.then.call(
|
|
|
+ external.externalContextPromise.promise, () => {
|
|
|
+ });
|
|
|
+ external.externalContextPromise.resolvePromise();
|
|
|
+}
|
|
|
+unhandledPromiseRejectionCrossContext();
|
|
|
+
|
|
|
+//
|
|
|
+// validate that when we have a handler from one script context
|
|
|
+// and a promise from another script context, we'll not break if a rejection handler is available
|
|
|
+//
|
|
|
+function handledPromiseRejectionCrossContext() {
|
|
|
+ var external = WScript.LoadScriptFile("JsDiagExceptionsInPromises_BreakOnFirstChanceExceptions.crosscontext.js", "samethread");
|
|
|
+ let p = Promise.prototype.then.call(
|
|
|
+ external.externalContextPromise.promise, () => {}, () => {});
|
|
|
+ external.externalContextPromise.resolvePromise();
|
|
|
+}
|
|
|
+handledPromiseRejectionCrossContext();
|
|
|
+
|
|
|
+//
|
|
|
+// This one below is an edge case where we will break on uncaught exceptions
|
|
|
+// even though the rejection is handled. What's happening here is before
|
|
|
+// we execute the function onResolve, there is no handler attached
|
|
|
+// so we, then as part of executing onResolve, the catch handler is
|
|
|
+// attached. We'll break in the function below.
|
|
|
+//
|
|
|
+// I don't think it is worth fixing this since it seems like a relatively
|
|
|
+// rare case.
|
|
|
+//
|
|
|
+function handledPromiseRejection8_bugbug() {
|
|
|
+ var p = Promise.resolve(0).then(function onResolve() {
|
|
|
+ p.catch(() => { }); // lazily added catch on the currently executing promise
|
|
|
+ throw new Error('error for handledPromiseRejection8_bugbug');
|
|
|
+ });
|
|
|
+}
|
|
|
+handledPromiseRejection8_bugbug();
|
|
|
+
|
|
|
+//
|
|
|
+// In the case below, we're resolving a promise with a promise.
|
|
|
+// Ultimately, the rejections is handled, but according to
|
|
|
+// ES standard, the resolve of promiseA with promiseB gets
|
|
|
+// pushed on the task queue, therefore, at the time the exception
|
|
|
+// is raised, promiseB hasn't been "then'd".
|
|
|
+//
|
|
|
+// There are two ways to address this:
|
|
|
+// 1. Change the ResolveThenable task to run immediately vs runing in task queue (this would be in violation of the spec)
|
|
|
+// 2. Keep a list of the pending resolve-thenable tasks.
|
|
|
+//
|
|
|
+function handledPromiseRejection9_bugbug() {
|
|
|
+ function f1() {
|
|
|
+ let promiseA = new Promise((resolveA, rejectA) => {
|
|
|
+ let promiseB = Promise.resolve(true).then(() => {
|
|
|
+ throw new Error('error for handledPromiseRejection9_bugbug');
|
|
|
+ });
|
|
|
+ resolveA(promiseB);
|
|
|
+ });
|
|
|
+ return promiseA;
|
|
|
+ }
|
|
|
+
|
|
|
+ f1().catch((e) => {
|
|
|
+ });
|
|
|
+}
|
|
|
+handledPromiseRejection9_bugbug();
|
|
|
+
|
|
|
+
|
|
|
+function noRejection10() {
|
|
|
+ let p = Promise.resolve(true)
|
|
|
+ .then(() => {
|
|
|
+ try {
|
|
|
+ throw new Error('error for noRejection10');
|
|
|
+ } catch (err) {
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
+noRejection10();
|