/* * Copyright (C) 2015 Yusuke Suzuki . * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ function all(iterable) { "use strict"; if (!@isObject(this)) @throwTypeError("|this| is not an object"); var promiseCapability = @newPromiseCapability(this); var values = []; var index = 0; var remainingElementsCount = 1; function newResolveElement(index) { var alreadyCalled = false; return (argument) => { if (alreadyCalled) return @undefined; alreadyCalled = true; @putByValDirect(values, index, argument); --remainingElementsCount; if (remainingElementsCount === 0) return promiseCapability.@resolve.@call(@undefined, values); return @undefined; }; } try { var promiseResolve = this.resolve; if (!@isCallable(promiseResolve)) @throwTypeError("Promise resolve is not a function"); for (var value of iterable) { @putByValDirect(values, index, @undefined); var nextPromise = promiseResolve.@call(this, value); var resolveElement = newResolveElement(index); ++remainingElementsCount; nextPromise.then(resolveElement, promiseCapability.@reject); ++index; } --remainingElementsCount; if (remainingElementsCount === 0) promiseCapability.@resolve.@call(@undefined, values); } catch (error) { promiseCapability.@reject.@call(@undefined, error); } return promiseCapability.@promise; } function allSettled(iterable) { "use strict"; if (!@isObject(this)) @throwTypeError("|this| is not an object"); var promiseCapability = @newPromiseCapability(this); var values = []; var remainingElementsCount = 1; var index = 0; function newResolveRejectElements(index) { var alreadyCalled = false; return [ (value) => { if (alreadyCalled) return @undefined; alreadyCalled = true; var obj = { status: "fulfilled", value }; @putByValDirect(values, index, obj); --remainingElementsCount; if (remainingElementsCount === 0) return promiseCapability.@resolve.@call(@undefined, values); return @undefined; }, (reason) => { if (alreadyCalled) return @undefined; alreadyCalled = true; var obj = { status: "rejected", reason }; @putByValDirect(values, index, obj); --remainingElementsCount; if (remainingElementsCount === 0) return promiseCapability.@resolve.@call(@undefined, values); return @undefined; } ]; } try { var promiseResolve = this.resolve; if (!@isCallable(promiseResolve)) @throwTypeError("Promise resolve is not a function"); for (var value of iterable) { @putByValDirect(values, index, @undefined); var nextPromise = promiseResolve.@call(this, value); var [resolveElement, rejectElement] = newResolveRejectElements(index); ++remainingElementsCount; nextPromise.then(resolveElement, rejectElement); ++index; } --remainingElementsCount; if (remainingElementsCount === 0) promiseCapability.@resolve.@call(@undefined, values); } catch (error) { promiseCapability.@reject.@call(@undefined, error); } return promiseCapability.@promise; } function any(iterable) { "use strict"; if (!@isObject(this)) @throwTypeError("|this| is not an object"); var promiseCapability = @newPromiseCapability(this); var errors = []; var remainingElementsCount = 1; var index = 0; function newRejectElement(index) { var alreadyCalled = false; return (reason) => { if (alreadyCalled) return @undefined; alreadyCalled = true; @putByValDirect(errors, index, reason); --remainingElementsCount; if (remainingElementsCount === 0) return promiseCapability.@reject.@call(@undefined, new @AggregateError(errors)); return @undefined; }; } try { var promiseResolve = this.resolve; if (!@isCallable(promiseResolve)) @throwTypeError("Promise resolve is not a function"); for (var value of iterable) { @putByValDirect(errors, index, @undefined); var nextPromise = promiseResolve.@call(this, value); var rejectElement = newRejectElement(index); ++remainingElementsCount; nextPromise.then(promiseCapability.@resolve, rejectElement); ++index; } --remainingElementsCount; if (remainingElementsCount === 0) throw new @AggregateError(errors); } catch (error) { promiseCapability.@reject.@call(@undefined, error); } return promiseCapability.@promise; } function race(iterable) { "use strict"; if (!@isObject(this)) @throwTypeError("|this| is not an object"); var promiseCapability = @newPromiseCapability(this); try { var promiseResolve = this.resolve; if (!@isCallable(promiseResolve)) @throwTypeError("Promise resolve is not a function"); for (var value of iterable) { var nextPromise = promiseResolve.@call(this, value); nextPromise.then(promiseCapability.@resolve, promiseCapability.@reject); } } catch (error) { promiseCapability.@reject.@call(@undefined, error); } return promiseCapability.@promise; } function reject(reason) { "use strict"; if (!@isObject(this)) @throwTypeError("|this| is not an object"); if (this === @Promise) { var promise = @newPromise(); @rejectPromiseWithFirstResolvingFunctionCallCheck(promise, reason); return promise; } return @promiseRejectSlow(this, reason); } function resolve(value) { "use strict"; if (!@isObject(this)) @throwTypeError("|this| is not an object"); return @promiseResolve(this, value); } @nakedConstructor function Promise(executor) { "use strict"; if (!@isCallable(executor)) @throwTypeError("Promise constructor takes a function argument"); var promise = @createPromise(this, /* isInternalPromise */ false); var capturedPromise = promise; try { executor( (resolution) => { return @resolvePromiseWithFirstResolvingFunctionCallCheck(capturedPromise, resolution); }, (reason) => { return @rejectPromiseWithFirstResolvingFunctionCallCheck(capturedPromise, reason); }); } catch (error) { @rejectPromiseWithFirstResolvingFunctionCallCheck(promise, error); } return promise; } @nakedConstructor function InternalPromise(executor) { "use strict"; if (!@isCallable(executor)) @throwTypeError("InternalPromise constructor takes a function argument"); var promise = @createPromise(this, /* isInternalPromise */ true); var capturedPromise = promise; try { executor( (resolution) => { return @resolvePromiseWithFirstResolvingFunctionCallCheck(capturedPromise, resolution); }, (reason) => { return @rejectPromiseWithFirstResolvingFunctionCallCheck(capturedPromise, reason); }); } catch (error) { @rejectPromiseWithFirstResolvingFunctionCallCheck(promise, error); } return promise; }