Chromium Code Reviews| 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 promiseCombinedDeferredSymbol = | |
| 16 utils.ImportNow("promise_combined_deferred_symbol"); | |
| 15 var promiseHasHandlerSymbol = | 17 var promiseHasHandlerSymbol = |
| 16 utils.ImportNow("promise_has_handler_symbol"); | 18 utils.ImportNow("promise_has_handler_symbol"); |
| 17 var promiseOnRejectSymbol = utils.ImportNow("promise_on_reject_symbol"); | 19 var promiseOnRejectSymbol = utils.ImportNow("promise_on_reject_symbol"); |
| 18 var promiseOnResolveSymbol = | 20 var promiseOnResolveSymbol = |
| 19 utils.ImportNow("promise_on_resolve_symbol"); | 21 utils.ImportNow("promise_on_resolve_symbol"); |
| 20 var promiseRawSymbol = utils.ImportNow("promise_raw_symbol"); | 22 var promiseRawSymbol = utils.ImportNow("promise_raw_symbol"); |
| 21 var promiseStatusSymbol = utils.ImportNow("promise_status_symbol"); | 23 var promiseStatusSymbol = utils.ImportNow("promise_status_symbol"); |
| 22 var promiseValueSymbol = utils.ImportNow("promise_value_symbol"); | 24 var promiseValueSymbol = utils.ImportNow("promise_value_symbol"); |
| 23 var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol"); | 25 var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol"); |
| 24 | 26 |
| (...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 291 } | 293 } |
| 292 } | 294 } |
| 293 | 295 |
| 294 function PromiseAll(iterable) { | 296 function PromiseAll(iterable) { |
| 295 var deferred = %_CallFunction(this, PromiseDeferred); | 297 var deferred = %_CallFunction(this, PromiseDeferred); |
| 296 var resolutions = []; | 298 var resolutions = []; |
| 297 try { | 299 try { |
| 298 var count = 0; | 300 var count = 0; |
| 299 var i = 0; | 301 var i = 0; |
| 300 for (var value of iterable) { | 302 for (var value of iterable) { |
| 301 this.resolve(value).then( | 303 var promise = this.resolve(value).then( |
| 302 // Nested scope to get closure over current i. | 304 // Nested scope to get closure over current i. |
| 303 // TODO(arv): Use an inner let binding once available. | 305 // TODO(arv): Use an inner let binding once available. |
| 304 (function(i) { | 306 (function(i) { |
| 305 return function(x) { | 307 return function(x) { |
| 306 resolutions[i] = x; | 308 resolutions[i] = x; |
| 307 if (--count === 0) deferred.resolve(resolutions); | 309 if (--count === 0) deferred.resolve(resolutions); |
| 308 } | 310 } |
| 309 })(i), | 311 })(i), |
| 310 function(r) { deferred.reject(r); }); | 312 function(r) { deferred.reject(r); }); |
| 313 SET_PRIVATE(promise, promiseCombinedDeferredSymbol, deferred); | |
| 311 ++i; | 314 ++i; |
| 312 ++count; | 315 ++count; |
| 313 } | 316 } |
| 314 | 317 |
| 315 if (count === 0) { | 318 if (count === 0) { |
| 316 deferred.resolve(resolutions); | 319 deferred.resolve(resolutions); |
| 317 } | 320 } |
| 318 | 321 |
| 319 } catch (e) { | 322 } catch (e) { |
| 320 deferred.reject(e) | 323 deferred.reject(e) |
| 321 } | 324 } |
| 322 return deferred.promise; | 325 return deferred.promise; |
| 323 } | 326 } |
| 324 | 327 |
| 325 function PromiseRace(iterable) { | 328 function PromiseRace(iterable) { |
| 326 var deferred = %_CallFunction(this, PromiseDeferred); | 329 var deferred = %_CallFunction(this, PromiseDeferred); |
| 327 try { | 330 try { |
| 328 for (var value of iterable) { | 331 for (var value of iterable) { |
| 329 this.resolve(value).then( | 332 var promise = this.resolve(value).then( |
| 330 function(x) { deferred.resolve(x) }, | 333 function(x) { deferred.resolve(x) }, |
| 331 function(r) { deferred.reject(r) }); | 334 function(r) { deferred.reject(r) }); |
| 335 SET_PRIVATE(promise, promiseCombinedDeferredSymbol, deferred); | |
| 332 } | 336 } |
| 333 } catch (e) { | 337 } catch (e) { |
| 334 deferred.reject(e) | 338 deferred.reject(e) |
| 335 } | 339 } |
| 336 return deferred.promise; | 340 return deferred.promise; |
| 337 } | 341 } |
| 338 | 342 |
| 339 | 343 |
| 340 // Utility for debugger | 344 // Utility for debugger |
| 341 | 345 |
| 342 function PromiseHasUserDefinedRejectHandlerRecursive(promise) { | 346 function PromiseHasUserDefinedRejectHandlerRecursive(promise) { |
| 343 var queue = GET_PRIVATE(promise, promiseOnRejectSymbol); | 347 var queue = GET_PRIVATE(promise, promiseOnRejectSymbol); |
| 344 if (IS_UNDEFINED(queue)) return false; | 348 if (IS_UNDEFINED(queue)) return false; |
| 345 for (var i = 0; i < queue.length; i += 2) { | 349 for (var i = 0; i < queue.length; i += 2) { |
| 346 if (queue[i] != PromiseIdRejectHandler) return true; | 350 var handler = queue[i]; |
| 347 if (PromiseHasUserDefinedRejectHandlerRecursive(queue[i + 1].promise)) { | 351 var promise = queue[i + 1].promise; |
| 352 if (handler !== PromiseIdRejectHandler) { | |
| 353 var deferred = GET_PRIVATE(promise, promiseCombinedDeferredSymbol); | |
| 354 if (IS_UNDEFINED(deferred)) return true; | |
| 355 if (PromiseHasUserDefinedRejectHandlerRecursive(deferred.promise)) { | |
|
rossberg
2015/10/19 14:24:29
Why the extra conditional and not a tail call?
re
Yang
2015/10/19 16:24:09
A promise is considered to have a reject handler i
| |
| 356 return true; | |
| 357 } | |
| 358 } else if (PromiseHasUserDefinedRejectHandlerRecursive(promise)) { | |
| 348 return true; | 359 return true; |
| 349 } | 360 } |
| 350 } | 361 } |
| 351 return false; | 362 return false; |
| 352 } | 363 } |
| 353 | 364 |
| 354 // Return whether the promise will be handled by a user-defined reject | 365 // Return whether the promise will be handled by a user-defined reject |
| 355 // handler somewhere down the promise chain. For this, we do a depth-first | 366 // handler somewhere down the promise chain. For this, we do a depth-first |
| 356 // search for a reject handler that's not the default PromiseIdRejectHandler. | 367 // search for a reject handler that's not the default PromiseIdRejectHandler. |
| 357 function PromiseHasUserDefinedRejectHandler() { | 368 function PromiseHasUserDefinedRejectHandler() { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 393 // This allows extras to create promises quickly without building extra | 404 // This allows extras to create promises quickly without building extra |
| 394 // resolve/reject closures, and allows them to later resolve and reject any | 405 // resolve/reject closures, and allows them to later resolve and reject any |
| 395 // promise without having to hold on to those closures forever. | 406 // promise without having to hold on to those closures forever. |
| 396 utils.InstallFunctions(extrasUtils, 0, [ | 407 utils.InstallFunctions(extrasUtils, 0, [ |
| 397 "createPromise", PromiseCreate, | 408 "createPromise", PromiseCreate, |
| 398 "resolvePromise", PromiseResolve, | 409 "resolvePromise", PromiseResolve, |
| 399 "rejectPromise", PromiseReject | 410 "rejectPromise", PromiseReject |
| 400 ]); | 411 ]); |
| 401 | 412 |
| 402 }) | 413 }) |
| OLD | NEW |