JsDiagExceptionsInPromises_BreakOnUncaughtExceptions.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. /**exception(uncaught):stack();**/
  6. function unhandledPromiseRejection1() {
  7. Promise.resolve(true)
  8. .then(() => {
  9. throw new Error('error for unhandledPromiseRejection1')
  10. });
  11. }
  12. unhandledPromiseRejection1();
  13. function unhandledPromiseRejection2() {
  14. Promise.resolve(true)
  15. .then(() => {
  16. throw new Error('error for unhandledPromiseRejection2');
  17. })
  18. .then(() => {
  19. // no catch
  20. });
  21. }
  22. unhandledPromiseRejection2();
  23. function unhandledPromiseRejection3() {
  24. let p = Promise.resolve(true)
  25. .then(() => {
  26. throw new Error('error for unhandledPromiseRejection3');
  27. })
  28. .then(() => 0);
  29. p.then(() => 0).then(() => 1); // this path is not caught
  30. p.then(() => 2, (err) => { }); // this path is caught
  31. }
  32. unhandledPromiseRejection3();
  33. function unhandledPromiseRejection4() {
  34. let p = Promise.resolve(true)
  35. .then(() => {
  36. throw new Error('error for unhandledPromiseRejection3');
  37. })
  38. .catch((err) => {
  39. throw err;
  40. });
  41. }
  42. unhandledPromiseRejection4();
  43. function handledPromiseRejection5() {
  44. Promise.resolve(true)
  45. .then(() => {
  46. throw new Error('error for handledPromiseRejection5')
  47. }).catch(() => { });
  48. }
  49. handledPromiseRejection5();
  50. function handledPromiseRejection6() {
  51. Promise.resolve(true)
  52. .then(() => {
  53. throw new Error('error for handledPromiseRejection6');
  54. })
  55. .then(() => { }, () => { });
  56. }
  57. handledPromiseRejection6()
  58. function handledPromiseRejection7() {
  59. let p = Promise.resolve(true)
  60. .then(() => {
  61. throw new Error('error for handledPromiseRejection7');
  62. })
  63. .then(() => 0);
  64. p.then(() => 0).then(() => 1).catch(() => { }); // this path is caught
  65. p.then(() => 2, (err) => { }); // this path is caught
  66. }
  67. handledPromiseRejection7();
  68. //
  69. // validate that when we have a handler from one script context
  70. // and a promise from another script context, we'll break appropriately
  71. //
  72. function unhandledPromiseRejectionCrossContext() {
  73. var external = WScript.LoadScriptFile("JsDiagExceptionsInPromises_BreakOnFirstChanceExceptions.crosscontext.js", "samethread");
  74. let p = Promise.prototype.then.call(
  75. external.externalContextPromise.promise, () => {
  76. });
  77. external.externalContextPromise.resolvePromise();
  78. }
  79. unhandledPromiseRejectionCrossContext();
  80. //
  81. // validate that when we have a handler from one script context
  82. // and a promise from another script context, we'll not break if a rejection handler is available
  83. //
  84. function handledPromiseRejectionCrossContext() {
  85. var external = WScript.LoadScriptFile("JsDiagExceptionsInPromises_BreakOnFirstChanceExceptions.crosscontext.js", "samethread");
  86. let p = Promise.prototype.then.call(
  87. external.externalContextPromise.promise, () => {}, () => {});
  88. external.externalContextPromise.resolvePromise();
  89. }
  90. handledPromiseRejectionCrossContext();
  91. //
  92. // This one below is an edge case where we will break on uncaught exceptions
  93. // even though the rejection is handled. What's happening here is before
  94. // we execute the function onResolve, there is no handler attached
  95. // so we, then as part of executing onResolve, the catch handler is
  96. // attached. We'll break in the function below.
  97. //
  98. // I don't think it is worth fixing this since it seems like a relatively
  99. // rare case.
  100. //
  101. function handledPromiseRejection8_bugbug() {
  102. var p = Promise.resolve(0).then(function onResolve() {
  103. p.catch(() => { }); // lazily added catch on the currently executing promise
  104. throw new Error('error for handledPromiseRejection8_bugbug');
  105. });
  106. }
  107. handledPromiseRejection8_bugbug();
  108. //
  109. // In the case below, we're resolving a promise with a promise.
  110. // Ultimately, the rejections is handled, but according to
  111. // ES standard, the resolve of promiseA with promiseB gets
  112. // pushed on the task queue, therefore, at the time the exception
  113. // is raised, promiseB hasn't been "then'd".
  114. //
  115. // There are two ways to address this:
  116. // 1. Change the ResolveThenable task to run immediately vs runing in task queue (this would be in violation of the spec)
  117. // 2. Keep a list of the pending resolve-thenable tasks.
  118. //
  119. function handledPromiseRejection9_bugbug() {
  120. function f1() {
  121. let promiseA = new Promise((resolveA, rejectA) => {
  122. let promiseB = Promise.resolve(true).then(() => {
  123. throw new Error('error for handledPromiseRejection9_bugbug');
  124. });
  125. resolveA(promiseB);
  126. });
  127. return promiseA;
  128. }
  129. f1().catch((e) => {
  130. });
  131. }
  132. handledPromiseRejection9_bugbug();
  133. function noRejection10() {
  134. let p = Promise.resolve(true)
  135. .then(() => {
  136. try {
  137. throw new Error('error for noRejection10');
  138. } catch (err) {
  139. }
  140. });
  141. }
  142. noRejection10();