OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 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 |
11 // ------------------------------------------------------------------- | 11 // ------------------------------------------------------------------- |
12 // Imports | 12 // Imports |
13 | 13 |
14 var AsyncFunctionNext; | 14 var AsyncFunctionNext; |
15 var AsyncFunctionThrow; | 15 var AsyncFunctionThrow; |
16 var GlobalPromise; | 16 var GlobalPromise; |
17 var IsPromise; | 17 var IsPromise; |
18 var NewPromiseCapability; | 18 var NewPromiseCapability; |
19 var PerformPromiseThen; | 19 var PerformPromiseThen; |
20 var PromiseCreate; | 20 var PromiseCreate; |
| 21 var PromiseNextMicrotaskID; |
21 var RejectPromise; | 22 var RejectPromise; |
22 var ResolvePromise; | 23 var ResolvePromise; |
23 | 24 |
24 utils.Import(function(from) { | 25 utils.Import(function(from) { |
25 AsyncFunctionNext = from.AsyncFunctionNext; | 26 AsyncFunctionNext = from.AsyncFunctionNext; |
26 AsyncFunctionThrow = from.AsyncFunctionThrow; | 27 AsyncFunctionThrow = from.AsyncFunctionThrow; |
| 28 GlobalPromise = from.GlobalPromise; |
27 IsPromise = from.IsPromise; | 29 IsPromise = from.IsPromise; |
28 GlobalPromise = from.GlobalPromise; | |
29 NewPromiseCapability = from.NewPromiseCapability; | 30 NewPromiseCapability = from.NewPromiseCapability; |
| 31 PerformPromiseThen = from.PerformPromiseThen; |
30 PromiseCreate = from.PromiseCreate; | 32 PromiseCreate = from.PromiseCreate; |
31 PerformPromiseThen = from.PerformPromiseThen; | 33 PromiseNextMicrotaskID = from.PromiseNextMicrotaskID; |
32 RejectPromise = from.RejectPromise; | 34 RejectPromise = from.RejectPromise; |
33 ResolvePromise = from.ResolvePromise; | 35 ResolvePromise = from.ResolvePromise; |
34 }); | 36 }); |
35 | 37 |
| 38 var promiseAsyncStackIDSymbol = |
| 39 utils.ImportNow("promise_async_stack_id_symbol"); |
36 var promiseHandledBySymbol = | 40 var promiseHandledBySymbol = |
37 utils.ImportNow("promise_handled_by_symbol"); | 41 utils.ImportNow("promise_handled_by_symbol"); |
38 var promiseForwardingHandlerSymbol = | 42 var promiseForwardingHandlerSymbol = |
39 utils.ImportNow("promise_forwarding_handler_symbol"); | 43 utils.ImportNow("promise_forwarding_handler_symbol"); |
40 var promiseHandledHintSymbol = | 44 var promiseHandledHintSymbol = |
41 utils.ImportNow("promise_handled_hint_symbol"); | 45 utils.ImportNow("promise_handled_hint_symbol"); |
42 var promiseHasHandlerSymbol = | 46 var promiseHasHandlerSymbol = |
43 utils.ImportNow("promise_has_handler_symbol"); | 47 utils.ImportNow("promise_has_handler_symbol"); |
44 | 48 |
45 // ------------------------------------------------------------------- | 49 // ------------------------------------------------------------------- |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
87 return; | 91 return; |
88 } | 92 } |
89 | 93 |
90 // Just forwarding the exception, so no debugEvent for throwawayCapability | 94 // Just forwarding the exception, so no debugEvent for throwawayCapability |
91 var throwawayCapability = NewPromiseCapability(GlobalPromise, false); | 95 var throwawayCapability = NewPromiseCapability(GlobalPromise, false); |
92 | 96 |
93 // The Promise will be thrown away and not handled, but it shouldn't trigger | 97 // The Promise will be thrown away and not handled, but it shouldn't trigger |
94 // unhandled reject events as its work is done | 98 // unhandled reject events as its work is done |
95 SET_PRIVATE(throwawayCapability.promise, promiseHasHandlerSymbol, true); | 99 SET_PRIVATE(throwawayCapability.promise, promiseHasHandlerSymbol, true); |
96 | 100 |
97 PerformPromiseThen(promise, onFulfilled, onRejected, throwawayCapability); | 101 if (DEBUG_IS_ACTIVE) { |
98 | |
99 if (DEBUG_IS_ACTIVE && !IS_UNDEFINED(outerPromise)) { | |
100 if (IsPromise(awaited)) { | 102 if (IsPromise(awaited)) { |
101 // Mark the reject handler callback to be a forwarding edge, rather | 103 // Mark the reject handler callback to be a forwarding edge, rather |
102 // than a meaningful catch handler | 104 // than a meaningful catch handler |
103 SET_PRIVATE(onRejected, promiseForwardingHandlerSymbol, true); | 105 SET_PRIVATE(onRejected, promiseForwardingHandlerSymbol, true); |
104 } | 106 } |
105 | 107 |
106 // Mark the dependency to outerPromise in case the throwaway Promise is | 108 // Mark the dependency to outerPromise in case the throwaway Promise is |
107 // found on the Promise stack | 109 // found on the Promise stack |
108 SET_PRIVATE(throwawayCapability.promise, promiseHandledBySymbol, | 110 SET_PRIVATE(throwawayCapability.promise, promiseHandledBySymbol, |
109 outerPromise); | 111 outerPromise); |
110 } | 112 } |
| 113 |
| 114 PerformPromiseThen(promise, onFulfilled, onRejected, throwawayCapability); |
111 } | 115 } |
112 | 116 |
113 // Called by the parser from the desugaring of 'await' when catch | 117 // Called by the parser from the desugaring of 'await' when catch |
114 // prediction indicates no locally surrounding catch block | 118 // prediction indicates no locally surrounding catch block |
115 function AsyncFunctionAwaitUncaught(generator, awaited, outerPromise) { | 119 function AsyncFunctionAwaitUncaught(generator, awaited, outerPromise) { |
116 AsyncFunctionAwait(generator, awaited, outerPromise); | 120 AsyncFunctionAwait(generator, awaited, outerPromise); |
117 } | 121 } |
118 | 122 |
119 // Called by the parser from the desugaring of 'await' when catch | 123 // Called by the parser from the desugaring of 'await' when catch |
120 // prediction indicates that there is a locally surrounding catch block | 124 // prediction indicates that there is a locally surrounding catch block |
121 function AsyncFunctionAwaitCaught(generator, awaited, outerPromise) { | 125 function AsyncFunctionAwaitCaught(generator, awaited, outerPromise) { |
122 if (DEBUG_IS_ACTIVE && IsPromise(awaited)) { | 126 if (DEBUG_IS_ACTIVE && IsPromise(awaited)) { |
123 SET_PRIVATE(awaited, promiseHandledHintSymbol, true); | 127 SET_PRIVATE(awaited, promiseHandledHintSymbol, true); |
124 } | 128 } |
125 // Pass undefined for the outer Promise to not waste time setting up | 129 AsyncFunctionAwait(generator, awaited, outerPromise); |
126 // or following the dependency chain when this Promise is already marked | |
127 // as handled | |
128 AsyncFunctionAwait(generator, awaited, UNDEFINED); | |
129 } | 130 } |
130 | 131 |
131 // How the parser rejects promises from async/await desugaring | 132 // How the parser rejects promises from async/await desugaring |
132 function RejectPromiseNoDebugEvent(promise, reason) { | 133 function RejectPromiseNoDebugEvent(promise, reason) { |
133 return RejectPromise(promise, reason, false); | 134 return RejectPromise(promise, reason, false); |
134 } | 135 } |
135 | 136 |
| 137 function AsyncFunctionPromiseCreate() { |
| 138 var promise = PromiseCreate(); |
| 139 if (DEBUG_IS_ACTIVE) { |
| 140 // Push the Promise under construction in an async function on |
| 141 // the catch prediction stack to handle exceptions thrown before |
| 142 // the first await. |
| 143 %DebugPushPromise(promise); |
| 144 // Assign ID and create a recurring task to save stack for future |
| 145 // resumptions from await. |
| 146 var id = PromiseNextMicrotaskID(); |
| 147 SET_PRIVATE(promise, promiseAsyncStackIDSymbol, id); |
| 148 %DebugAsyncTaskEvent({ |
| 149 type: "enqueueRecurring", |
| 150 id: id, |
| 151 name: "async function", |
| 152 }); |
| 153 } |
| 154 return promise; |
| 155 } |
| 156 |
| 157 function AsyncFunctionPromiseRelease(promise) { |
| 158 if (DEBUG_IS_ACTIVE) { |
| 159 // Cancel |
| 160 var id = GET_PRIVATE(promise, promiseAsyncStackIDSymbol); |
| 161 %DebugAsyncTaskEvent({ |
| 162 type: "cancel", |
| 163 id: id, |
| 164 name: "async function", |
| 165 }); |
| 166 // Pop the Promise under construction in an async function on |
| 167 // from catch prediction stack. |
| 168 %DebugPopPromise(); |
| 169 } |
| 170 } |
| 171 |
136 %InstallToContext([ | 172 %InstallToContext([ |
137 "async_function_await_caught", AsyncFunctionAwaitCaught, | 173 "async_function_await_caught", AsyncFunctionAwaitCaught, |
138 "async_function_await_uncaught", AsyncFunctionAwaitUncaught, | 174 "async_function_await_uncaught", AsyncFunctionAwaitUncaught, |
139 "reject_promise_no_debug_event", RejectPromiseNoDebugEvent, | 175 "reject_promise_no_debug_event", RejectPromiseNoDebugEvent, |
| 176 "async_function_promise_create", AsyncFunctionPromiseCreate, |
| 177 "async_function_promise_release", AsyncFunctionPromiseRelease, |
140 ]); | 178 ]); |
141 | 179 |
142 }) | 180 }) |
OLD | NEW |