| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 (function(global, utils, extrasUtils) { | 5 (function(global, utils, extrasUtils) { |
| 6 | 6 |
| 7 "use strict"; | 7 "use strict"; |
| 8 | 8 |
| 9 %CheckIsBootstrapping(); | 9 %CheckIsBootstrapping(); |
| 10 | 10 |
| 11 // ------------------------------------------------------------------- | 11 // ------------------------------------------------------------------- |
| 12 // Imports | 12 // Imports |
| 13 | 13 |
| 14 var InternalArray = utils.InternalArray; | 14 var InternalArray = utils.InternalArray; |
| 15 var promiseAsyncStackIDSymbol = | 15 var promiseAsyncStackIDSymbol = |
| 16 utils.ImportNow("promise_async_stack_id_symbol"); | 16 utils.ImportNow("promise_async_stack_id_symbol"); |
| 17 var promiseHandledBySymbol = | 17 var promiseHandledBySymbol = |
| 18 utils.ImportNow("promise_handled_by_symbol"); | 18 utils.ImportNow("promise_handled_by_symbol"); |
| 19 var promiseForwardingHandlerSymbol = | 19 var promiseForwardingHandlerSymbol = |
| 20 utils.ImportNow("promise_forwarding_handler_symbol"); | 20 utils.ImportNow("promise_forwarding_handler_symbol"); |
| 21 var promiseHandledHintSymbol = | |
| 22 utils.ImportNow("promise_handled_hint_symbol"); | |
| 23 var ObjectHasOwnProperty; // Used by HAS_PRIVATE. | 21 var ObjectHasOwnProperty; // Used by HAS_PRIVATE. |
| 24 var GlobalPromise = global.Promise; | 22 var GlobalPromise = global.Promise; |
| 25 | 23 |
| 26 utils.Import(function(from) { | 24 utils.Import(function(from) { |
| 27 ObjectHasOwnProperty = from.ObjectHasOwnProperty; | 25 ObjectHasOwnProperty = from.ObjectHasOwnProperty; |
| 28 }); | 26 }); |
| 29 | 27 |
| 30 // ------------------------------------------------------------------- | 28 // ------------------------------------------------------------------- |
| 31 | 29 |
| 32 // Core functionality. | 30 // Core functionality. |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 256 if (instrumenting && %is_promise(throwawayPromise)) { | 254 if (instrumenting && %is_promise(throwawayPromise)) { |
| 257 SET_PRIVATE(throwawayPromise, promiseHandledBySymbol, deferred.promise); | 255 SET_PRIVATE(throwawayPromise, promiseHandledBySymbol, deferred.promise); |
| 258 } | 256 } |
| 259 } | 257 } |
| 260 } catch (e) { | 258 } catch (e) { |
| 261 %_Call(deferred.reject, UNDEFINED, e); | 259 %_Call(deferred.reject, UNDEFINED, e); |
| 262 } | 260 } |
| 263 return deferred.promise; | 261 return deferred.promise; |
| 264 } | 262 } |
| 265 | 263 |
| 266 | |
| 267 // Utility for debugger | |
| 268 | |
| 269 function PromiseHasUserDefinedRejectHandlerCheck(handler, deferred) { | |
| 270 // Recurse to the forwarding Promise, if any. This may be due to | |
| 271 // - await reaction forwarding to the throwaway Promise, which has | |
| 272 // a dependency edge to the outer Promise. | |
| 273 // - PromiseIdResolveHandler forwarding to the output of .then | |
| 274 // - Promise.all/Promise.race forwarding to a throwaway Promise, which | |
| 275 // has a dependency edge to the generated outer Promise. | |
| 276 if (GET_PRIVATE(handler, promiseForwardingHandlerSymbol)) { | |
| 277 return PromiseHasUserDefinedRejectHandlerRecursive(deferred.promise); | |
| 278 } | |
| 279 | |
| 280 // Otherwise, this is a real reject handler for the Promise | |
| 281 return true; | |
| 282 } | |
| 283 | |
| 284 function PromiseHasUserDefinedRejectHandlerRecursive(promise) { | |
| 285 // If this promise was marked as being handled by a catch block | |
| 286 // in an async function, then it has a user-defined reject handler. | |
| 287 if (GET_PRIVATE(promise, promiseHandledHintSymbol)) return true; | |
| 288 | |
| 289 // If this Promise is subsumed by another Promise (a Promise resolved | |
| 290 // with another Promise, or an intermediate, hidden, throwaway Promise | |
| 291 // within async/await), then recurse on the outer Promise. | |
| 292 // In this case, the dependency is one possible way that the Promise | |
| 293 // could be resolved, so it does not subsume the other following cases. | |
| 294 var outerPromise = GET_PRIVATE(promise, promiseHandledBySymbol); | |
| 295 if (outerPromise && | |
| 296 PromiseHasUserDefinedRejectHandlerRecursive(outerPromise)) { | |
| 297 return true; | |
| 298 } | |
| 299 | |
| 300 if (!%is_promise(promise)) return false; | |
| 301 | |
| 302 var queue = %PromiseRejectReactions(promise); | |
| 303 var deferred = %PromiseDeferred(promise); | |
| 304 | |
| 305 if (IS_UNDEFINED(queue)) return false; | |
| 306 | |
| 307 if (!IS_ARRAY(queue)) { | |
| 308 return PromiseHasUserDefinedRejectHandlerCheck(queue, deferred); | |
| 309 } | |
| 310 | |
| 311 for (var i = 0; i < queue.length; i++) { | |
| 312 if (PromiseHasUserDefinedRejectHandlerCheck(queue[i], deferred[i])) { | |
| 313 return true; | |
| 314 } | |
| 315 } | |
| 316 return false; | |
| 317 } | |
| 318 | |
| 319 // Return whether the promise will be handled by a user-defined reject | |
| 320 // handler somewhere down the promise chain. For this, we do a depth-first | |
| 321 // search for a reject handler that's not the default PromiseIdRejectHandler. | |
| 322 // This function also traverses dependencies of one Promise on another, | |
| 323 // set up through async/await and Promises resolved with Promises. | |
| 324 function PromiseHasUserDefinedRejectHandler() { | |
| 325 return PromiseHasUserDefinedRejectHandlerRecursive(this); | |
| 326 }; | |
| 327 | |
| 328 function MarkPromiseAsHandled(promise) { | 264 function MarkPromiseAsHandled(promise) { |
| 329 %PromiseMarkAsHandled(promise); | 265 %PromiseMarkAsHandled(promise); |
| 330 } | 266 } |
| 331 | 267 |
| 332 // ------------------------------------------------------------------- | 268 // ------------------------------------------------------------------- |
| 333 // Install exported functions. | 269 // Install exported functions. |
| 334 | 270 |
| 335 utils.InstallFunctions(GlobalPromise, DONT_ENUM, [ | 271 utils.InstallFunctions(GlobalPromise, DONT_ENUM, [ |
| 336 "reject", PromiseReject, | 272 "reject", PromiseReject, |
| 337 "all", PromiseAll, | 273 "all", PromiseAll, |
| 338 "race", PromiseRace, | 274 "race", PromiseRace, |
| 339 "resolve", PromiseResolve | 275 "resolve", PromiseResolve |
| 340 ]); | 276 ]); |
| 341 | 277 |
| 342 %InstallToContext([ | 278 %InstallToContext([ |
| 343 "promise_create", PromiseCreate, | 279 "promise_create", PromiseCreate, |
| 344 "promise_has_user_defined_reject_handler", PromiseHasUserDefinedRejectHandler, | |
| 345 "promise_reject", DoRejectPromise, | 280 "promise_reject", DoRejectPromise, |
| 346 // TODO(gsathya): Remove this once we update the promise builtin. | 281 // TODO(gsathya): Remove this once we update the promise builtin. |
| 347 "promise_internal_reject", RejectPromise, | 282 "promise_internal_reject", RejectPromise, |
| 348 "promise_debug_get_info", PromiseDebugGetInfo, | 283 "promise_debug_get_info", PromiseDebugGetInfo, |
| 349 "new_promise_capability", NewPromiseCapability, | 284 "new_promise_capability", NewPromiseCapability, |
| 350 "internal_promise_capability", CreateInternalPromiseCapability, | 285 "internal_promise_capability", CreateInternalPromiseCapability, |
| 351 "promise_id_resolve_handler", PromiseIdResolveHandler, | 286 "promise_id_resolve_handler", PromiseIdResolveHandler, |
| 352 "promise_id_reject_handler", PromiseIdRejectHandler | 287 "promise_id_reject_handler", PromiseIdRejectHandler |
| 353 ]); | 288 ]); |
| 354 | 289 |
| 355 // This allows extras to create promises quickly without building extra | 290 // This allows extras to create promises quickly without building extra |
| 356 // resolve/reject closures, and allows them to later resolve and reject any | 291 // resolve/reject closures, and allows them to later resolve and reject any |
| 357 // promise without having to hold on to those closures forever. | 292 // promise without having to hold on to those closures forever. |
| 358 utils.InstallFunctions(extrasUtils, 0, [ | 293 utils.InstallFunctions(extrasUtils, 0, [ |
| 359 "createPromise", PromiseCreate, | 294 "createPromise", PromiseCreate, |
| 360 "rejectPromise", DoRejectPromise, | 295 "rejectPromise", DoRejectPromise, |
| 361 "markPromiseAsHandled", MarkPromiseAsHandled | 296 "markPromiseAsHandled", MarkPromiseAsHandled |
| 362 ]); | 297 ]); |
| 363 | 298 |
| 364 utils.Export(function(to) { | 299 utils.Export(function(to) { |
| 365 to.PromiseCreate = PromiseCreate; | 300 to.PromiseCreate = PromiseCreate; |
| 366 | 301 |
| 367 to.CreateInternalPromiseCapability = CreateInternalPromiseCapability; | 302 to.CreateInternalPromiseCapability = CreateInternalPromiseCapability; |
| 368 to.RejectPromise = RejectPromise; | 303 to.RejectPromise = RejectPromise; |
| 369 }); | 304 }); |
| 370 | 305 |
| 371 }) | 306 }) |
| OLD | NEW |