2 * Copyright (C) 2017 Oleksandr Skachkov <gskachkov@gmail.com>.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 const promiseCapability = @newPromiseCapability(@Promise);
32 if (!@isObject(this) || !@isObject(this.@syncIterator)) {
33 promiseCapability.@reject.@call(@undefined, new @TypeError('Iterator is not an object.'));
34 return promiseCapability.@promise;
37 const syncIterator = this.@syncIterator;
40 const { done: nextDone, value: nextValue } = syncIterator.next(value);
41 const valueWrapperCapability = @newPromiseCapability(@Promise);
42 valueWrapperCapability.@resolve.@call(@undefined, nextValue);
43 valueWrapperCapability.@promise.@then(
44 function (result) { promiseCapability.@resolve.@call(@undefined, { done: !!nextDone, value: result }); },
45 function (error) { promiseCapability.@reject.@call(@undefined, error); });
47 promiseCapability.@reject.@call(@undefined, e);
50 return promiseCapability.@promise;
53 function return(value)
57 const promiseCapability = @newPromiseCapability(@Promise);
59 if (!@isObject(this) || !@isObject(this.@syncIterator)) {
60 promiseCapability.@reject.@call(@undefined, new @TypeError('Iterator is not an object.'));
61 return promiseCapability.@promise;
64 const syncIterator = this.@syncIterator;
69 returnMethod = syncIterator.return;
71 promiseCapability.@reject.@call(@undefined, e);
72 return promiseCapability.@promise;
75 if (returnMethod === @undefined) {
76 promiseCapability.@resolve.@call(@undefined, { value, done: true });
77 return promiseCapability.@promise;
81 const returnResult = returnMethod.@call(syncIterator, value);
83 if (!@isObject(returnResult)) {
84 promiseCapability.@reject.@call(@undefined, new @TypeError('Iterator result interface is not an object.'));
85 return promiseCapability.@promise;
88 const { done: resultDone, value: resultValue } = returnResult;
89 const valueWrapperCapability = @newPromiseCapability(@Promise);
91 valueWrapperCapability.@resolve.@call(@undefined, resultValue);
92 valueWrapperCapability.@promise.@then(
93 function (result) { promiseCapability.@resolve.@call(@undefined, { done: resultDone, value: result }); },
94 function (error) { promiseCapability.@reject.@call(@undefined, error); });
96 promiseCapability.@reject.@call(@undefined, e);
99 return promiseCapability.@promise;
102 function throw(exception)
106 const promiseCapability = @newPromiseCapability(@Promise);
108 if (!@isObject(this) || !@isObject(this.@syncIterator)) {
109 promiseCapability.@reject.@call(@undefined, new @TypeError('Iterator is not an object.'));
110 return promiseCapability.@promise;
113 const syncIterator = this.@syncIterator;
118 throwMethod = syncIterator.throw;
120 promiseCapability.@reject.@call(@undefined, e);
121 return promiseCapability.@promise;
124 if (throwMethod === @undefined) {
125 promiseCapability.@reject.@call(@undefined, exception);
126 return promiseCapability.@promise;
130 const throwResult = throwMethod.@call(syncIterator, exception);
132 if (!@isObject(throwResult)) {
133 promiseCapability.@reject.@call(@undefined, new @TypeError('Iterator result interface is not an object.'));
134 return promiseCapability.@promise;
137 const { done: throwDone, value: throwValue } = throwResult;
138 const valueWrapperCapability = @newPromiseCapability(@Promise);
140 valueWrapperCapability.@resolve.@call(@undefined, throwValue);
141 valueWrapperCapability.@promise.@then(
142 function (result) { promiseCapability.@resolve.@call(@undefined, { done: throwDone, value: result }); },
143 function (error) { promiseCapability.@reject.@call(@undefined, error); });
145 promiseCapability.@reject.@call(@undefined, e);
148 return promiseCapability.@promise;
152 function createAsyncFromSyncIterator(syncIterator)
154 if (!@isObject(syncIterator))
155 @throwTypeError('Only objects can be wrapped by async-from-sync wrapper');
157 return new @AsyncFromSyncIteratorConstructor(syncIterator)
162 function AsyncFromSyncIteratorConstructor(syncIterator) {
163 this.@syncIterator = syncIterator;