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 }); | |
39 resolver(function(x) { PromiseResolve(promise, x) }, | 38 resolver(function(x) { PromiseResolve(promise, x) }, |
40 function(r) { PromiseReject(promise, r) }); | 39 function(r) { PromiseReject(promise, r) }); |
41 } catch (e) { | 40 } catch (e) { |
42 PromiseReject(promise, e); | 41 PromiseReject(promise, e); |
43 } finally { | |
44 %DebugPromiseHandleEpilogue(); | |
45 } | 42 } |
46 } | 43 } |
47 | 44 |
48 function PromiseSet(promise, status, value, onResolve, onReject) { | 45 function PromiseSet(promise, status, value, onResolve, onReject) { |
49 SET_PRIVATE(promise, promiseStatus, status); | 46 SET_PRIVATE(promise, promiseStatus, status); |
50 SET_PRIVATE(promise, promiseValue, value); | 47 SET_PRIVATE(promise, promiseValue, value); |
51 SET_PRIVATE(promise, promiseOnResolve, onResolve); | 48 SET_PRIVATE(promise, promiseOnResolve, onResolve); |
52 SET_PRIVATE(promise, promiseOnReject, onReject); | 49 SET_PRIVATE(promise, promiseOnReject, onReject); |
53 return promise; | 50 return promise; |
54 } | 51 } |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
157 for (var i = 0; i < tasks.length; i += 2) { | 154 for (var i = 0; i < tasks.length; i += 2) { |
158 PromiseHandle(value, tasks[i], tasks[i + 1]) | 155 PromiseHandle(value, tasks[i], tasks[i + 1]) |
159 } | 156 } |
160 }); | 157 }); |
161 | 158 |
162 %SetMicrotaskPending(true); | 159 %SetMicrotaskPending(true); |
163 } | 160 } |
164 | 161 |
165 function PromiseHandle(value, handler, deferred) { | 162 function PromiseHandle(value, handler, deferred) { |
166 try { | 163 try { |
167 %DebugPromiseHandlePrologue( | |
168 function() { | |
169 var queue = GET_PRIVATE(deferred.promise, promiseOnReject); | |
170 return (queue && queue.length == 0) ? deferred.promise : UNDEFINED; | |
171 }); | |
172 var result = handler(value); | 164 var result = handler(value); |
173 if (result === deferred.promise) | 165 if (result === deferred.promise) |
174 throw MakeTypeError('promise_cyclic', [result]); | 166 throw MakeTypeError('promise_cyclic', [result]); |
175 else if (IsPromise(result)) | 167 else if (IsPromise(result)) |
176 %_CallFunction(result, deferred.resolve, deferred.reject, PromiseChain); | 168 %_CallFunction(result, deferred.resolve, deferred.reject, PromiseChain); |
177 else | 169 else |
178 deferred.resolve(result); | 170 deferred.resolve(result); |
179 } catch (exception) { | 171 } 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 } |
180 try { | 179 try { |
181 %DebugPromiseHandleEpilogue(); // Match the previous prologue. | |
182 %DebugPromiseHandlePrologue(function() { return deferred.promise }); | |
183 deferred.reject(exception); | 180 deferred.reject(exception); |
184 } catch (e) { } | 181 } catch (e) { |
185 } finally { | 182 // The reject handler can only throw for a custom deferred promise. |
186 %DebugPromiseHandleEpilogue(); | 183 // We consider the original exception to be uncaught. |
| 184 uncaught = true; |
| 185 } |
| 186 if (uncaught) %DebugPendingExceptionInPromise(exception, deferred.promise); |
187 } | 187 } |
188 } | 188 } |
189 | 189 |
190 | 190 |
191 // Multi-unwrapped chaining with thenable coercion. | 191 // Multi-unwrapped chaining with thenable coercion. |
192 | 192 |
193 function PromiseThen(onResolve, onReject) { | 193 function PromiseThen(onResolve, onReject) { |
194 onResolve = | 194 onResolve = |
195 IS_NULL_OR_UNDEFINED(onResolve) ? PromiseIdResolveHandler : onResolve; | 195 IS_NULL_OR_UNDEFINED(onResolve) ? PromiseIdResolveHandler : onResolve; |
196 onReject = | 196 onReject = |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
314 ]); | 314 ]); |
315 } | 315 } |
316 | 316 |
317 SetUpPromise(); | 317 SetUpPromise(); |
318 | 318 |
319 // Functions to expose promise details to the debugger. | 319 // Functions to expose promise details to the debugger. |
320 function GetPromiseStatus(promise) { | 320 function GetPromiseStatus(promise) { |
321 return GET_PRIVATE(promise, promiseStatus); | 321 return GET_PRIVATE(promise, promiseStatus); |
322 } | 322 } |
323 | 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 |
324 function GetPromiseValue(promise) { | 332 function GetPromiseValue(promise) { |
325 return GET_PRIVATE(promise, promiseValue); | 333 return GET_PRIVATE(promise, promiseValue); |
326 } | 334 } |
OLD | NEW |