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 "use strict"; | 5 "use strict"; |
| 6 | 6 |
| 7 // This file relies on the fact that the following declaration has been made | 7 // This file relies on the fact that the following declaration has been made |
| 8 // in runtime.js: | 8 // in runtime.js: |
| 9 // var $Object = global.Object | 9 // var $Object = global.Object |
| 10 // var $WeakMap = global.WeakMap | 10 // var $WeakMap = global.WeakMap |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 28 return IS_SPEC_OBJECT(x) && %HasLocalProperty(x, promiseStatus); | 28 return IS_SPEC_OBJECT(x) && %HasLocalProperty(x, promiseStatus); |
| 29 } | 29 } |
| 30 | 30 |
| 31 function Promise(resolver) { | 31 function Promise(resolver) { |
| 32 if (resolver === promiseRaw) return; | 32 if (resolver === promiseRaw) return; |
| 33 if (!%_IsConstructCall()) throw MakeTypeError('not_a_promise', [this]); | 33 if (!%_IsConstructCall()) throw MakeTypeError('not_a_promise', [this]); |
| 34 if (typeof resolver !== 'function') | 34 if (typeof resolver !== 'function') |
| 35 throw MakeTypeError('resolver_not_a_function', [resolver]); | 35 throw MakeTypeError('resolver_not_a_function', [resolver]); |
| 36 var promise = PromiseInit(this); | 36 var promise = PromiseInit(this); |
| 37 try { | 37 try { |
| 38 %DebugPromiseHandlePrologue(function() { return promise }); | |
| 38 resolver(function(x) { PromiseResolve(promise, x) }, | 39 resolver(function(x) { PromiseResolve(promise, x) }, |
| 39 function(r) { PromiseReject(promise, r) }); | 40 function(r) { PromiseReject(promise, r) }); |
| 40 } catch (e) { | 41 } catch (e) { |
| 41 PromiseReject(promise, e); | 42 PromiseReject(promise, e); |
| 42 } | 43 } |
| 44 %DebugPromiseHandleEpilogue(); | |
|
rossberg
2014/04/30 12:55:17
Put his in 'finally' clause (also below).
Yang
2014/04/30 13:20:14
Done.
| |
| 43 } | 45 } |
| 44 | 46 |
| 45 function PromiseSet(promise, status, value, onResolve, onReject) { | 47 function PromiseSet(promise, status, value, onResolve, onReject) { |
| 46 SET_PRIVATE(promise, promiseStatus, status); | 48 SET_PRIVATE(promise, promiseStatus, status); |
| 47 SET_PRIVATE(promise, promiseValue, value); | 49 SET_PRIVATE(promise, promiseValue, value); |
| 48 SET_PRIVATE(promise, promiseOnResolve, onResolve); | 50 SET_PRIVATE(promise, promiseOnResolve, onResolve); |
| 49 SET_PRIVATE(promise, promiseOnReject, onReject); | 51 SET_PRIVATE(promise, promiseOnReject, onReject); |
| 50 return promise; | 52 return promise; |
| 51 } | 53 } |
| 52 | 54 |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 154 for (var i = 0; i < tasks.length; i += 2) { | 156 for (var i = 0; i < tasks.length; i += 2) { |
| 155 PromiseHandle(value, tasks[i], tasks[i + 1]) | 157 PromiseHandle(value, tasks[i], tasks[i + 1]) |
| 156 } | 158 } |
| 157 }); | 159 }); |
| 158 | 160 |
| 159 %SetMicrotaskPending(true); | 161 %SetMicrotaskPending(true); |
| 160 } | 162 } |
| 161 | 163 |
| 162 function PromiseHandle(value, handler, deferred) { | 164 function PromiseHandle(value, handler, deferred) { |
| 163 try { | 165 try { |
| 166 %DebugPromiseHandlePrologue( | |
| 167 function() { | |
| 168 var queue = GET_PRIVATE(deferred.promise, promiseOnReject); | |
| 169 return (queue && queue.length == 0) ? deferred.promise : UNDEFINED; | |
| 170 }); | |
| 164 var result = handler(value); | 171 var result = handler(value); |
| 165 if (result === deferred.promise) | 172 if (result === deferred.promise) |
| 166 throw MakeTypeError('promise_cyclic', [result]); | 173 throw MakeTypeError('promise_cyclic', [result]); |
| 167 else if (IsPromise(result)) | 174 else if (IsPromise(result)) |
| 168 %_CallFunction(result, deferred.resolve, deferred.reject, PromiseChain); | 175 %_CallFunction(result, deferred.resolve, deferred.reject, PromiseChain); |
| 169 else | 176 else |
| 170 deferred.resolve(result); | 177 deferred.resolve(result); |
| 171 } catch (exception) { | 178 } catch (exception) { |
| 172 var uncaught = false; | |
| 173 var reject_queue = GET_PRIVATE(deferred.promise, promiseOnReject); | |
| 174 if (reject_queue && reject_queue.length == 0) { | |
| 175 // The deferred promise may get a reject handler attached later. | |
| 176 // For now, we consider the exception to be (for the moment) uncaught. | |
| 177 uncaught = true; | |
| 178 } | |
| 179 try { | 179 try { |
| 180 %DebugPromiseHandlePrologue(function() { return deferred.promise }); | |
|
rossberg
2014/04/30 12:55:17
It's a bit weird that the prologue is executed twi
Yang
2014/04/30 13:20:14
Done.
| |
| 180 deferred.reject(exception); | 181 deferred.reject(exception); |
| 181 } catch (e) { | 182 } catch (e) { } |
| 182 // The reject handler can only throw for a custom deferred promise. | |
| 183 // We consider the original exception to be uncaught. | |
| 184 uncaught = true; | |
| 185 } | |
| 186 if (uncaught) %DebugPendingExceptionInPromise(exception, deferred.promise); | |
| 187 } | 183 } |
| 184 %DebugPromiseHandleEpilogue(); | |
| 188 } | 185 } |
| 189 | 186 |
| 190 | 187 |
| 191 // Multi-unwrapped chaining with thenable coercion. | 188 // Multi-unwrapped chaining with thenable coercion. |
| 192 | 189 |
| 193 function PromiseThen(onResolve, onReject) { | 190 function PromiseThen(onResolve, onReject) { |
| 194 onResolve = | 191 onResolve = |
| 195 IS_NULL_OR_UNDEFINED(onResolve) ? PromiseIdResolveHandler : onResolve; | 192 IS_NULL_OR_UNDEFINED(onResolve) ? PromiseIdResolveHandler : onResolve; |
| 196 onReject = | 193 onReject = |
| 197 IS_NULL_OR_UNDEFINED(onReject) ? PromiseIdRejectHandler : onReject; | 194 IS_NULL_OR_UNDEFINED(onReject) ? PromiseIdRejectHandler : onReject; |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 308 "resolve", PromiseCast | 305 "resolve", PromiseCast |
| 309 ]); | 306 ]); |
| 310 InstallFunctions($Promise.prototype, DONT_ENUM, [ | 307 InstallFunctions($Promise.prototype, DONT_ENUM, [ |
| 311 "chain", PromiseChain, | 308 "chain", PromiseChain, |
| 312 "then", PromiseThen, | 309 "then", PromiseThen, |
| 313 "catch", PromiseCatch | 310 "catch", PromiseCatch |
| 314 ]); | 311 ]); |
| 315 } | 312 } |
| 316 | 313 |
| 317 SetUpPromise(); | 314 SetUpPromise(); |
| 318 | |
| 319 // Functions to expose promise details to the debugger. | |
| 320 function GetPromiseStatus(promise) { | |
|
rossberg
2014/04/30 12:55:17
As discussed offline, I'd prefer to keep the acces
Yang
2014/04/30 13:20:14
Done.
| |
| 321 return GET_PRIVATE(promise, promiseStatus); | |
| 322 } | |
| 323 | |
| 324 function GetPromiseOnResolve(promise) { | |
| 325 return GET_PRIVATE(promise, promiseOnResolve); | |
| 326 } | |
| 327 | |
| 328 function GetPromiseOnReject(promise) { | |
| 329 return GET_PRIVATE(promise, promiseOnReject); | |
| 330 } | |
| 331 | |
| 332 function GetPromiseValue(promise) { | |
| 333 return GET_PRIVATE(promise, promiseValue); | |
| 334 } | |
| OLD | NEW |