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 11 matching lines...) Expand all Loading... | |
22 // mirror-debugger.js currently uses builtins.promiseStatus. It would be nice | 22 // mirror-debugger.js currently uses builtins.promiseStatus. It would be nice |
23 // if we could move these property names into the closure below. | 23 // if we could move these property names into the closure below. |
24 // TODO(jkummerow/rossberg/yangguo): Find a better solution. | 24 // TODO(jkummerow/rossberg/yangguo): Find a better solution. |
25 | 25 |
26 // Status values: 0 = pending, +1 = resolved, -1 = rejected | 26 // Status values: 0 = pending, +1 = resolved, -1 = rejected |
27 var promiseStatus = GLOBAL_PRIVATE("Promise#status"); | 27 var promiseStatus = GLOBAL_PRIVATE("Promise#status"); |
28 var promiseValue = GLOBAL_PRIVATE("Promise#value"); | 28 var promiseValue = GLOBAL_PRIVATE("Promise#value"); |
29 var promiseOnResolve = GLOBAL_PRIVATE("Promise#onResolve"); | 29 var promiseOnResolve = GLOBAL_PRIVATE("Promise#onResolve"); |
30 var promiseOnReject = GLOBAL_PRIVATE("Promise#onReject"); | 30 var promiseOnReject = GLOBAL_PRIVATE("Promise#onReject"); |
31 var promiseRaw = GLOBAL_PRIVATE("Promise#raw"); | 31 var promiseRaw = GLOBAL_PRIVATE("Promise#raw"); |
32 var promiseDebug = GLOBAL_PRIVATE("Promise#debug"); | |
32 var lastMicrotaskId = 0; | 33 var lastMicrotaskId = 0; |
33 | 34 |
35 var PromiseHasRejectHandler; | |
rossberg
2014/08/05 13:35:08
Nit: move this up to the other Promise* vars.
Tho
Yang
2014/08/06 09:36:23
Done.
| |
36 | |
34 (function() { | 37 (function() { |
35 | 38 |
36 var $Promise = function Promise(resolver) { | 39 var $Promise = function Promise(resolver) { |
37 if (resolver === promiseRaw) return; | 40 if (resolver === promiseRaw) return; |
38 if (!%_IsConstructCall()) throw MakeTypeError('not_a_promise', [this]); | 41 if (!%_IsConstructCall()) throw MakeTypeError('not_a_promise', [this]); |
39 if (!IS_SPEC_FUNCTION(resolver)) | 42 if (!IS_SPEC_FUNCTION(resolver)) |
40 throw MakeTypeError('resolver_not_a_function', [resolver]); | 43 throw MakeTypeError('resolver_not_a_function', [resolver]); |
41 var promise = PromiseInit(this); | 44 var promise = PromiseInit(this); |
42 try { | 45 try { |
43 %DebugPromiseHandlePrologue(function() { return promise }); | 46 %DebugPushPromise(promise); |
44 resolver(function(x) { PromiseResolve(promise, x) }, | 47 resolver(function(x) { PromiseResolve(promise, x) }, |
45 function(r) { PromiseReject(promise, r) }); | 48 function(r) { PromiseReject(promise, r) }); |
46 } catch (e) { | 49 } catch (e) { |
47 PromiseReject(promise, e); | 50 PromiseReject(promise, e); |
48 } finally { | 51 } finally { |
49 %DebugPromiseHandleEpilogue(); | 52 %DebugPopPromise(); |
50 } | 53 } |
51 } | 54 } |
52 | 55 |
53 // Core functionality. | 56 // Core functionality. |
54 | 57 |
55 function PromiseSet(promise, status, value, onResolve, onReject) { | 58 function PromiseSet(promise, status, value, onResolve, onReject) { |
56 SET_PRIVATE(promise, promiseStatus, status); | 59 SET_PRIVATE(promise, promiseStatus, status); |
57 SET_PRIVATE(promise, promiseValue, value); | 60 SET_PRIVATE(promise, promiseValue, value); |
58 SET_PRIVATE(promise, promiseOnResolve, onResolve); | 61 SET_PRIVATE(promise, promiseOnResolve, onResolve); |
59 SET_PRIVATE(promise, promiseOnReject, onReject); | 62 SET_PRIVATE(promise, promiseOnReject, onReject); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
91 deferred.reject(r); | 94 deferred.reject(r); |
92 } | 95 } |
93 return deferred.promise; | 96 return deferred.promise; |
94 } | 97 } |
95 } | 98 } |
96 return x; | 99 return x; |
97 } | 100 } |
98 | 101 |
99 function PromiseHandle(value, handler, deferred) { | 102 function PromiseHandle(value, handler, deferred) { |
100 try { | 103 try { |
101 %DebugPromiseHandlePrologue( | 104 %DebugPushPromise(deferred.promise); |
102 function() { | |
103 var queue = GET_PRIVATE(deferred.promise, promiseOnReject); | |
104 return (queue && queue.length == 0) ? deferred.promise : UNDEFINED; | |
105 }); | |
106 var result = handler(value); | 105 var result = handler(value); |
107 if (result === deferred.promise) | 106 if (result === deferred.promise) |
108 throw MakeTypeError('promise_cyclic', [result]); | 107 throw MakeTypeError('promise_cyclic', [result]); |
109 else if (IsPromise(result)) | 108 else if (IsPromise(result)) |
110 %_CallFunction(result, deferred.resolve, deferred.reject, PromiseChain); | 109 %_CallFunction(result, deferred.resolve, deferred.reject, PromiseChain); |
111 else | 110 else |
112 deferred.resolve(result); | 111 deferred.resolve(result); |
113 } catch (exception) { | 112 } catch (exception) { |
114 try { | 113 try { deferred.reject(exception); } catch (e) { } |
115 %DebugPromiseHandlePrologue(function() { return deferred.promise }); | |
116 deferred.reject(exception); | |
117 } catch (e) { } finally { | |
118 %DebugPromiseHandleEpilogue(); | |
119 } | |
120 } finally { | 114 } finally { |
121 %DebugPromiseHandleEpilogue(); | 115 %DebugPopPromise(); |
122 } | 116 } |
123 } | 117 } |
124 | 118 |
125 function PromiseEnqueue(value, tasks, status) { | 119 function PromiseEnqueue(value, tasks, status) { |
126 var id, name, instrumenting = DEBUG_IS_ACTIVE; | 120 var id, name, instrumenting = DEBUG_IS_ACTIVE; |
127 %EnqueueMicrotask(function() { | 121 %EnqueueMicrotask(function() { |
128 if (instrumenting) { | 122 if (instrumenting) { |
129 %DebugAsyncTaskEvent({ type: "willHandle", id: id, name: name }); | 123 %DebugAsyncTaskEvent({ type: "willHandle", id: id, name: name }); |
130 } | 124 } |
131 for (var i = 0; i < tasks.length; i += 2) { | 125 for (var i = 0; i < tasks.length; i += 2) { |
(...skipping 26 matching lines...) Expand all Loading... | |
158 | 152 |
159 PromiseCreate = function PromiseCreate() { | 153 PromiseCreate = function PromiseCreate() { |
160 return new $Promise(PromiseNopResolver) | 154 return new $Promise(PromiseNopResolver) |
161 } | 155 } |
162 | 156 |
163 PromiseResolve = function PromiseResolve(promise, x) { | 157 PromiseResolve = function PromiseResolve(promise, x) { |
164 PromiseDone(promise, +1, x, promiseOnResolve) | 158 PromiseDone(promise, +1, x, promiseOnResolve) |
165 } | 159 } |
166 | 160 |
167 PromiseReject = function PromiseReject(promise, r) { | 161 PromiseReject = function PromiseReject(promise, r) { |
162 // Check promiseDebug property to avoid duplicate event. | |
163 if (DEBUG_IS_ACTIVE && !HAS_PRIVATE(promise, promiseDebug)) { | |
164 %DebugPromiseRejectEvent(promise, r); | |
165 } | |
168 PromiseDone(promise, -1, r, promiseOnReject) | 166 PromiseDone(promise, -1, r, promiseOnReject) |
169 } | 167 } |
170 | 168 |
171 // Convenience. | 169 // Convenience. |
172 | 170 |
173 function PromiseDeferred() { | 171 function PromiseDeferred() { |
174 if (this === $Promise) { | 172 if (this === $Promise) { |
175 // Optimized case, avoid extra closure. | 173 // Optimized case, avoid extra closure. |
176 var promise = PromiseInit(new $Promise(promiseRaw)); | 174 var promise = PromiseInit(new $Promise(promiseRaw)); |
177 return { | 175 return { |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
315 function(x) { deferred.resolve(x) }, | 313 function(x) { deferred.resolve(x) }, |
316 function(r) { deferred.reject(r) } | 314 function(r) { deferred.reject(r) } |
317 ); | 315 ); |
318 } | 316 } |
319 } catch (e) { | 317 } catch (e) { |
320 deferred.reject(e) | 318 deferred.reject(e) |
321 } | 319 } |
322 return deferred.promise; | 320 return deferred.promise; |
323 } | 321 } |
324 | 322 |
323 | |
324 // Utility for debugger | |
325 | |
326 PromiseHasRejectHandler = function PromiseHasRejectHandler() { | |
327 var queue = GET_PRIVATE(this, promiseOnReject); | |
rossberg
2014/08/05 13:35:08
Nit: move this line down by 2.
Yang
2014/08/06 09:36:23
Done.
| |
328 // Mark promise as already triggered a reject event. | |
329 SET_PRIVATE(this, promiseDebug, true); | |
330 // If already rejected/resolved, the handlers have already been fired. | |
rossberg
2014/08/05 13:35:08
If the status isn't 0 then the queue should be und
Yang
2014/08/06 09:36:23
Done.
| |
331 if (GET_PRIVATE(this, promiseStatus) !== 0) return true; | |
332 return queue && queue.length > 0; | |
333 }; | |
334 | |
325 // ------------------------------------------------------------------- | 335 // ------------------------------------------------------------------- |
326 // Install exported functions. | 336 // Install exported functions. |
327 | 337 |
328 %CheckIsBootstrapping(); | 338 %CheckIsBootstrapping(); |
329 %AddNamedProperty(global, 'Promise', $Promise, DONT_ENUM); | 339 %AddNamedProperty(global, 'Promise', $Promise, DONT_ENUM); |
330 InstallFunctions($Promise, DONT_ENUM, [ | 340 InstallFunctions($Promise, DONT_ENUM, [ |
331 "defer", PromiseDeferred, | 341 "defer", PromiseDeferred, |
332 "accept", PromiseResolved, | 342 "accept", PromiseResolved, |
333 "reject", PromiseRejected, | 343 "reject", PromiseRejected, |
334 "all", PromiseAll, | 344 "all", PromiseAll, |
335 "race", PromiseOne, | 345 "race", PromiseOne, |
336 "resolve", PromiseCast | 346 "resolve", PromiseCast |
337 ]); | 347 ]); |
338 InstallFunctions($Promise.prototype, DONT_ENUM, [ | 348 InstallFunctions($Promise.prototype, DONT_ENUM, [ |
339 "chain", PromiseChain, | 349 "chain", PromiseChain, |
340 "then", PromiseThen, | 350 "then", PromiseThen, |
341 "catch", PromiseCatch | 351 "catch", PromiseCatch |
342 ]); | 352 ]); |
343 | 353 |
344 })(); | 354 })(); |
OLD | NEW |