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 3// found in the LICENSE file. 4 5(function(global, utils, extrasUtils) { 6 7"use strict"; 8 9%CheckIsBootstrapping(); 10 11// ------------------------------------------------------------------- 12// Imports 13 14var InternalArray = utils.InternalArray; 15var promiseHandledBySymbol = 16 utils.ImportNow("promise_handled_by_symbol"); 17var promiseForwardingHandlerSymbol = 18 utils.ImportNow("promise_forwarding_handler_symbol"); 19var GlobalPromise = global.Promise; 20 21// ------------------------------------------------------------------- 22// Define exported functions. 23 24// Combinators. 25 26// ES#sec-promise.all 27// Promise.all ( iterable ) 28function PromiseAll(iterable) { 29 if (!IS_RECEIVER(this)) { 30 throw %make_type_error(kCalledOnNonObject, "Promise.all"); 31 } 32 33 // false debugEvent so that forwarding the rejection through all does not 34 // trigger redundant ExceptionEvents 35 var deferred = %new_promise_capability(this, false); 36 var resolutions = new InternalArray(); 37 var count; 38 39 // For catch prediction, don't treat the .then calls as handling it; 40 // instead, recurse outwards. 41 var instrumenting = DEBUG_IS_ACTIVE; 42 if (instrumenting) { 43 SET_PRIVATE(deferred.reject, promiseForwardingHandlerSymbol, true); 44 } 45 46 function CreateResolveElementFunction(index, values, promiseCapability) { 47 var alreadyCalled = false; 48 return (x) => { 49 if (alreadyCalled === true) return; 50 alreadyCalled = true; 51 values[index] = x; 52 if (--count === 0) { 53 var valuesArray = []; 54 %MoveArrayContents(values, valuesArray); 55 %_Call(promiseCapability.resolve, UNDEFINED, valuesArray); 56 } 57 }; 58 } 59 60 try { 61 var i = 0; 62 count = 1; 63 for (var value of iterable) { 64 var nextPromise = this.resolve(value); 65 ++count; 66 var throwawayPromise = nextPromise.then( 67 CreateResolveElementFunction(i, resolutions, deferred), 68 deferred.reject); 69 // For catch prediction, mark that rejections here are semantically 70 // handled by the combined Promise. 71 if (instrumenting && %is_promise(throwawayPromise)) { 72 SET_PRIVATE(throwawayPromise, promiseHandledBySymbol, deferred.promise); 73 } 74 ++i; 75 } 76 77 // 6.d 78 if (--count === 0) { 79 var valuesArray = []; 80 %MoveArrayContents(resolutions, valuesArray); 81 %_Call(deferred.resolve, UNDEFINED, valuesArray); 82 } 83 84 } catch (e) { 85 %_Call(deferred.reject, UNDEFINED, e); 86 } 87 return deferred.promise; 88} 89 90// ES#sec-promise.race 91// Promise.race ( iterable ) 92function PromiseRace(iterable) { 93 if (!IS_RECEIVER(this)) { 94 throw %make_type_error(kCalledOnNonObject, PromiseRace); 95 } 96 97 // false debugEvent so that forwarding the rejection through race does not 98 // trigger redundant ExceptionEvents 99 var deferred = %new_promise_capability(this, false); 100 101 // For catch prediction, don't treat the .then calls as handling it; 102 // instead, recurse outwards. 103 var instrumenting = DEBUG_IS_ACTIVE; 104 if (instrumenting) { 105 SET_PRIVATE(deferred.reject, promiseForwardingHandlerSymbol, true); 106 } 107 108 try { 109 for (var value of iterable) { 110 var throwawayPromise = this.resolve(value).then(deferred.resolve, 111 deferred.reject); 112 // For catch prediction, mark that rejections here are semantically 113 // handled by the combined Promise. 114 if (instrumenting && %is_promise(throwawayPromise)) { 115 SET_PRIVATE(throwawayPromise, promiseHandledBySymbol, deferred.promise); 116 } 117 } 118 } catch (e) { 119 %_Call(deferred.reject, UNDEFINED, e); 120 } 121 return deferred.promise; 122} 123 124// ------------------------------------------------------------------- 125// Install exported functions. 126 127utils.InstallFunctions(GlobalPromise, DONT_ENUM, [ 128 "all", PromiseAll, 129 "race", PromiseRace, 130]); 131 132}) 133