// Copyright 2012 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. (function(global, utils, extrasUtils) { "use strict"; %CheckIsBootstrapping(); // ------------------------------------------------------------------- // Imports var InternalArray = utils.InternalArray; var promiseHandledBySymbol = utils.ImportNow("promise_handled_by_symbol"); var promiseForwardingHandlerSymbol = utils.ImportNow("promise_forwarding_handler_symbol"); var GlobalPromise = global.Promise; // ------------------------------------------------------------------- // Define exported functions. // Combinators. // ES#sec-promise.all // Promise.all ( iterable ) function PromiseAll(iterable) { if (!IS_RECEIVER(this)) { throw %make_type_error(kCalledOnNonObject, "Promise.all"); } // false debugEvent so that forwarding the rejection through all does not // trigger redundant ExceptionEvents var deferred = %new_promise_capability(this, false); var resolutions = new InternalArray(); var count; // For catch prediction, don't treat the .then calls as handling it; // instead, recurse outwards. var instrumenting = DEBUG_IS_ACTIVE; if (instrumenting) { SET_PRIVATE(deferred.reject, promiseForwardingHandlerSymbol, true); } function CreateResolveElementFunction(index, values, promiseCapability) { var alreadyCalled = false; return (x) => { if (alreadyCalled === true) return; alreadyCalled = true; values[index] = x; if (--count === 0) { var valuesArray = []; %MoveArrayContents(values, valuesArray); %_Call(promiseCapability.resolve, UNDEFINED, valuesArray); } }; } try { var i = 0; count = 1; for (var value of iterable) { var nextPromise = this.resolve(value); ++count; var throwawayPromise = nextPromise.then( CreateResolveElementFunction(i, resolutions, deferred), deferred.reject); // For catch prediction, mark that rejections here are semantically // handled by the combined Promise. if (instrumenting && %is_promise(throwawayPromise)) { SET_PRIVATE(throwawayPromise, promiseHandledBySymbol, deferred.promise); } ++i; } // 6.d if (--count === 0) { var valuesArray = []; %MoveArrayContents(resolutions, valuesArray); %_Call(deferred.resolve, UNDEFINED, valuesArray); } } catch (e) { %_Call(deferred.reject, UNDEFINED, e); } return deferred.promise; } // ES#sec-promise.race // Promise.race ( iterable ) function PromiseRace(iterable) { if (!IS_RECEIVER(this)) { throw %make_type_error(kCalledOnNonObject, PromiseRace); } // false debugEvent so that forwarding the rejection through race does not // trigger redundant ExceptionEvents var deferred = %new_promise_capability(this, false); // For catch prediction, don't treat the .then calls as handling it; // instead, recurse outwards. var instrumenting = DEBUG_IS_ACTIVE; if (instrumenting) { SET_PRIVATE(deferred.reject, promiseForwardingHandlerSymbol, true); } try { for (var value of iterable) { var throwawayPromise = this.resolve(value).then(deferred.resolve, deferred.reject); // For catch prediction, mark that rejections here are semantically // handled by the combined Promise. if (instrumenting && %is_promise(throwawayPromise)) { SET_PRIVATE(throwawayPromise, promiseHandledBySymbol, deferred.promise); } } } catch (e) { %_Call(deferred.reject, UNDEFINED, e); } return deferred.promise; } // ------------------------------------------------------------------- // Install exported functions. utils.InstallFunctions(GlobalPromise, DONT_ENUM, [ "all", PromiseAll, "race", PromiseRace, ]); })