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 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
59 | 59 |
60 var GlobalPromise = function Promise(resolver) { | 60 var GlobalPromise = function Promise(resolver) { |
61 if (resolver === promiseRawSymbol) { | 61 if (resolver === promiseRawSymbol) { |
62 return %NewObject(GlobalPromise, new.target); | 62 return %NewObject(GlobalPromise, new.target); |
63 } | 63 } |
64 if (IS_UNDEFINED(new.target)) throw MakeTypeError(kNotAPromise, this); | 64 if (IS_UNDEFINED(new.target)) throw MakeTypeError(kNotAPromise, this); |
65 if (!IS_CALLABLE(resolver)) | 65 if (!IS_CALLABLE(resolver)) |
66 throw MakeTypeError(kResolverNotAFunction, resolver); | 66 throw MakeTypeError(kResolverNotAFunction, resolver); |
67 | 67 |
68 var promise = PromiseInit(%NewObject(GlobalPromise, new.target)); | 68 var promise = PromiseInit(%NewObject(GlobalPromise, new.target)); |
69 var callbacks = CreateResolvingFunctions(promise); | |
69 | 70 |
70 try { | 71 try { |
71 %DebugPushPromise(promise, Promise); | 72 %DebugPushPromise(promise, Promise); |
72 var callbacks = CreateResolvingFunctions(promise); | |
73 resolver(callbacks.resolve, callbacks.reject); | 73 resolver(callbacks.resolve, callbacks.reject); |
74 } catch (e) { | 74 } catch (e) { |
75 PromiseReject(promise, e); | 75 %_Call(callbacks.reject, UNDEFINED, e); |
76 } finally { | 76 } finally { |
77 %DebugPopPromise(); | 77 %DebugPopPromise(); |
78 } | 78 } |
79 | 79 |
80 return promise; | 80 return promise; |
81 } | 81 } |
82 | 82 |
83 // Core functionality. | 83 // Core functionality. |
84 | 84 |
85 function PromiseSet(promise, status, value, onResolve, onReject) { | 85 function PromiseSet(promise, status, value, onResolve, onReject) { |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
174 } catch (e) { | 174 } catch (e) { |
175 return PromiseReject(promise, e); | 175 return PromiseReject(promise, e); |
176 } | 176 } |
177 if (IS_CALLABLE(then)) { | 177 if (IS_CALLABLE(then)) { |
178 // PromiseResolveThenableJob | 178 // PromiseResolveThenableJob |
179 var id, name, instrumenting = DEBUG_IS_ACTIVE; | 179 var id, name, instrumenting = DEBUG_IS_ACTIVE; |
180 %EnqueueMicrotask(function() { | 180 %EnqueueMicrotask(function() { |
181 if (instrumenting) { | 181 if (instrumenting) { |
182 %DebugAsyncTaskEvent({ type: "willHandle", id: id, name: name }); | 182 %DebugAsyncTaskEvent({ type: "willHandle", id: id, name: name }); |
183 } | 183 } |
184 var callbacks = CreateResolvingFunctions(promise); | |
184 try { | 185 try { |
185 var callbacks = CreateResolvingFunctions(promise); | |
186 %_Call(then, x, callbacks.resolve, callbacks.reject); | 186 %_Call(then, x, callbacks.resolve, callbacks.reject); |
187 } catch (e) { | 187 } catch (e) { |
188 PromiseReject(promise, e); | 188 %_Call(callbacks.reject, UNDEFINED, e); |
189 } | 189 } |
190 if (instrumenting) { | 190 if (instrumenting) { |
191 %DebugAsyncTaskEvent({ type: "didHandle", id: id, name: name }); | 191 %DebugAsyncTaskEvent({ type: "didHandle", id: id, name: name }); |
192 } | 192 } |
193 }); | 193 }); |
194 if (instrumenting) { | 194 if (instrumenting) { |
195 id = ++lastMicrotaskId; | 195 id = ++lastMicrotaskId; |
196 name = "PromseResolveThenableJob"; | 196 name = "PromseResolveThenableJob"; |
197 %DebugAsyncTaskEvent({ type: "enqueue", id: id, name: name }); | 197 %DebugAsyncTaskEvent({ type: "enqueue", id: id, name: name }); |
198 } | 198 } |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
331 throw MakeTypeError(kCalledOnNonObject, PromiseCast); | 331 throw MakeTypeError(kCalledOnNonObject, PromiseCast); |
332 } | 332 } |
333 if (IsPromise(x) && x.constructor === this) return x; | 333 if (IsPromise(x) && x.constructor === this) return x; |
334 | 334 |
335 var promiseCapability = NewPromiseCapability(this); | 335 var promiseCapability = NewPromiseCapability(this); |
336 var resolveResult = %_Call(promiseCapability.resolve, UNDEFINED, x); | 336 var resolveResult = %_Call(promiseCapability.resolve, UNDEFINED, x); |
337 return promiseCapability.promise; | 337 return promiseCapability.promise; |
338 } | 338 } |
339 | 339 |
340 function PromiseAll(iterable) { | 340 function PromiseAll(iterable) { |
341 if (!IS_RECEIVER(this)) { | |
342 throw MakeTypeError(kCalledOnNonObject, "Promise.all"); | |
343 } | |
344 | |
341 var deferred = NewPromiseCapability(this); | 345 var deferred = NewPromiseCapability(this); |
342 var resolutions = []; | 346 var resolutions = new InternalArray(); |
343 try { | 347 try { |
344 var count = 0; | 348 var count = 1; |
345 var i = 0; | 349 var i = 0; |
346 for (var value of iterable) { | 350 for (var value of iterable) { |
347 var reject = function(r) { deferred.reject(r) }; | 351 resolutions[i] = UNDEFINED; |
adamk
2016/01/07 19:12:10
Why is this needed?
caitp (gmail)
2016/01/07 19:20:35
I _think_ the reason is to make sure `hasOwnProper
adamk
2016/01/07 19:29:30
Ah, ok. Can you just use .push()?
caitp (gmail)
2016/01/07 19:37:59
it seems to pass everything without it, presumably
| |
348 this.resolve(value).then( | 352 var nextPromise = this.resolve(value); |
349 // Nested scope to get closure over current i. | 353 ++count; |
350 // TODO(arv): Use an inner let binding once available. | 354 nextPromise.then( |
351 (function(i) { | 355 CreateResolveElementFunction(i, resolutions, deferred), |
352 return function(x) { | 356 deferred.reject); |
353 resolutions[i] = x; | 357 SET_PRIVATE(deferred.reject, promiseCombinedDeferredSymbol, deferred); |
354 if (--count === 0) deferred.resolve(resolutions); | |
355 } | |
356 })(i), reject); | |
357 SET_PRIVATE(reject, promiseCombinedDeferredSymbol, deferred); | |
358 ++i; | 358 ++i; |
359 ++count; | |
360 } | 359 } |
361 | 360 |
362 if (count === 0) { | 361 // 6.d |
363 deferred.resolve(resolutions); | 362 if (--count === 0) { |
363 var valuesArray = []; | |
364 %MoveArrayContents(resolutions, valuesArray); | |
365 %_Call(deferred.resolve, UNDEFINED, valuesArray); | |
364 } | 366 } |
365 | 367 |
366 } catch (e) { | 368 } catch (e) { |
367 deferred.reject(e) | 369 %_Call(deferred.reject, UNDEFINED, e); |
368 } | 370 } |
369 return deferred.promise; | 371 return deferred.promise; |
372 | |
373 function CreateResolveElementFunction(index, values, promiseCapability) { | |
adamk
2016/01/07 19:12:10
I think I agree with Dan that this would read bett
caitp (gmail)
2016/01/07 19:20:36
ok
caitp (gmail)
2016/01/07 19:37:59
Done.
| |
374 var alreadyCalled = false; | |
375 return function(x) { | |
376 if (alreadyCalled === true) return; | |
377 alreadyCalled = true; | |
378 values[index] = x; | |
379 if (--count === 0) { | |
380 var valuesArray = []; | |
381 %MoveArrayContents(values, valuesArray); | |
382 %_Call(promiseCapability.resolve, UNDEFINED, valuesArray); | |
383 } | |
384 }; | |
385 } | |
370 } | 386 } |
371 | 387 |
372 function PromiseRace(iterable) { | 388 function PromiseRace(iterable) { |
373 if (!IS_RECEIVER(this)) { | 389 if (!IS_RECEIVER(this)) { |
374 throw MakeTypeError(kCalledOnNonObject, PromiseRace); | 390 throw MakeTypeError(kCalledOnNonObject, PromiseRace); |
375 } | 391 } |
376 | 392 |
377 var deferred = NewPromiseCapability(this); | 393 var deferred = NewPromiseCapability(this); |
378 try { | 394 try { |
379 for (var value of iterable) { | 395 for (var value of iterable) { |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
458 [PromiseChain, PromiseDeferred, PromiseResolved].forEach( | 474 [PromiseChain, PromiseDeferred, PromiseResolved].forEach( |
459 fn => %FunctionRemovePrototype(fn)); | 475 fn => %FunctionRemovePrototype(fn)); |
460 | 476 |
461 utils.Export(function(to) { | 477 utils.Export(function(to) { |
462 to.PromiseChain = PromiseChain; | 478 to.PromiseChain = PromiseChain; |
463 to.PromiseDeferred = PromiseDeferred; | 479 to.PromiseDeferred = PromiseDeferred; |
464 to.PromiseResolved = PromiseResolved; | 480 to.PromiseResolved = PromiseResolved; |
465 }); | 481 }); |
466 | 482 |
467 }) | 483 }) |
OLD | NEW |