Chromium Code Reviews| 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 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 320 throw MakeTypeError(kCalledOnNonObject, PromiseCast); | 320 throw MakeTypeError(kCalledOnNonObject, PromiseCast); |
| 321 } | 321 } |
| 322 if (IsPromise(x) && x.constructor === this) { | 322 if (IsPromise(x) && x.constructor === this) { |
| 323 return x; | 323 return x; |
| 324 } else { | 324 } else { |
| 325 return new this(function(resolve, reject) { resolve(x) }); | 325 return new this(function(resolve, reject) { resolve(x) }); |
| 326 } | 326 } |
| 327 } | 327 } |
| 328 | 328 |
| 329 function PromiseAll(iterable) { | 329 function PromiseAll(iterable) { |
| 330 if (!IS_RECEIVER(this)) { | |
| 331 throw MakeTypeError(kCalledOnNonObject, "Promise.all"); | |
| 332 } | |
| 333 | |
| 330 var deferred = NewPromiseCapability(this); | 334 var deferred = NewPromiseCapability(this); |
| 331 var resolutions = []; | 335 var resolutions = new InternalArray(); |
| 332 try { | 336 try { |
| 333 var count = 0; | 337 var count = 1; |
| 334 var i = 0; | 338 var i = 0; |
| 335 for (var value of iterable) { | 339 for (var value of iterable) { |
| 336 var reject = function(r) { deferred.reject(r) }; | 340 resolutions[i] = UNDEFINED; |
| 337 this.resolve(value).then( | 341 var nextPromise = this.resolve(value); |
| 338 // Nested scope to get closure over current i. | 342 ++count; |
| 339 // TODO(arv): Use an inner let binding once available. | 343 nextPromise.then( |
| 340 (function(i) { | 344 CreateResolveElementFunction(i, resolutions, deferred), |
| 341 return function(x) { | 345 deferred.reject); |
| 342 resolutions[i] = x; | 346 SET_PRIVATE(deferred.reject, promiseCombinedDeferredSymbol, deferred); |
| 343 if (--count === 0) deferred.resolve(resolutions); | |
| 344 } | |
| 345 })(i), reject); | |
| 346 SET_PRIVATE(reject, promiseCombinedDeferredSymbol, deferred); | |
| 347 ++i; | 347 ++i; |
| 348 ++count; | |
| 349 } | 348 } |
| 350 | 349 |
| 351 if (count === 0) { | 350 // 6.d |
| 352 deferred.resolve(resolutions); | 351 if (--count === 0) { |
| 352 var valuesArray = []; | |
| 353 %MoveArrayContents(resolutions, valuesArray); | |
| 354 %_Call(deferred.resolve, UNDEFINED, valuesArray); | |
| 353 } | 355 } |
| 354 | 356 |
| 355 } catch (e) { | 357 } catch (e) { |
| 356 deferred.reject(e) | 358 %_Call(deferred.reject, UNDEFINED, e); |
| 357 } | 359 } |
| 358 return deferred.promise; | 360 return deferred.promise; |
| 361 | |
| 362 function CreateResolveElementFunction(index, values, promiseCapability) { | |
|
Dan Ehrenberg
2016/01/04 18:18:39
Does this need to be a nested function? Our js cod
caitp (gmail)
2016/01/04 18:20:08
It doesn't, but the function isn't really needed b
caitp (gmail)
2016/01/04 19:26:52
Actually, I'm wrong --- `count` is captured, so it
| |
| 363 var alreadyCalled = false; | |
| 364 return function(x) { | |
| 365 if (alreadyCalled === true) return; | |
| 366 alreadyCalled = true; | |
| 367 values[index] = x; | |
| 368 if (--count === 0) { | |
| 369 var valuesArray = []; | |
| 370 %MoveArrayContents(values, valuesArray); | |
| 371 %_Call(promiseCapability.resolve, UNDEFINED, valuesArray); | |
| 372 } | |
| 373 }; | |
| 374 } | |
| 359 } | 375 } |
| 360 | 376 |
| 361 function PromiseRace(iterable) { | 377 function PromiseRace(iterable) { |
| 362 var deferred = NewPromiseCapability(this); | 378 var deferred = NewPromiseCapability(this); |
| 363 try { | 379 try { |
| 364 for (var value of iterable) { | 380 for (var value of iterable) { |
| 365 var reject = function(r) { deferred.reject(r) }; | 381 var reject = function(r) { deferred.reject(r) }; |
| 366 this.resolve(value).then(function(x) { deferred.resolve(x) }, reject); | 382 this.resolve(value).then(function(x) { deferred.resolve(x) }, reject); |
| 367 SET_PRIVATE(reject, promiseCombinedDeferredSymbol, deferred); | 383 SET_PRIVATE(reject, promiseCombinedDeferredSymbol, deferred); |
| 368 } | 384 } |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 443 [PromiseChain, PromiseDeferred, PromiseResolved].forEach( | 459 [PromiseChain, PromiseDeferred, PromiseResolved].forEach( |
| 444 fn => %FunctionRemovePrototype(fn)); | 460 fn => %FunctionRemovePrototype(fn)); |
| 445 | 461 |
| 446 utils.Export(function(to) { | 462 utils.Export(function(to) { |
| 447 to.PromiseChain = PromiseChain; | 463 to.PromiseChain = PromiseChain; |
| 448 to.PromiseDeferred = PromiseDeferred; | 464 to.PromiseDeferred = PromiseDeferred; |
| 449 to.PromiseResolved = PromiseResolved; | 465 to.PromiseResolved = PromiseResolved; |
| 450 }); | 466 }); |
| 451 | 467 |
| 452 }) | 468 }) |
| OLD | NEW |