| 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 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 AsyncFunctionThrow = from.AsyncFunctionThrow; | 26 AsyncFunctionThrow = from.AsyncFunctionThrow; |
| 27 IsPromise = from.IsPromise; | 27 IsPromise = from.IsPromise; |
| 28 GlobalPromise = from.GlobalPromise; | 28 GlobalPromise = from.GlobalPromise; |
| 29 NewPromiseCapability = from.NewPromiseCapability; | 29 NewPromiseCapability = from.NewPromiseCapability; |
| 30 PromiseCreate = from.PromiseCreate; | 30 PromiseCreate = from.PromiseCreate; |
| 31 PerformPromiseThen = from.PerformPromiseThen; | 31 PerformPromiseThen = from.PerformPromiseThen; |
| 32 RejectPromise = from.RejectPromise; | 32 RejectPromise = from.RejectPromise; |
| 33 ResolvePromise = from.ResolvePromise; | 33 ResolvePromise = from.ResolvePromise; |
| 34 }); | 34 }); |
| 35 | 35 |
| 36 var promiseAwaitHandlerSymbol = utils.ImportNow("promise_await_handler_symbol"); | 36 var promiseHandledBySymbol = |
| 37 utils.ImportNow("promise_handled_by_symbol"); |
| 38 var promiseForwardingHandlerSymbol = |
| 39 utils.ImportNow("promise_forwarding_handler_symbol"); |
| 37 var promiseHandledHintSymbol = | 40 var promiseHandledHintSymbol = |
| 38 utils.ImportNow("promise_handled_hint_symbol"); | 41 utils.ImportNow("promise_handled_hint_symbol"); |
| 39 var promiseHasHandlerSymbol = | 42 var promiseHasHandlerSymbol = |
| 40 utils.ImportNow("promise_has_handler_symbol"); | 43 utils.ImportNow("promise_has_handler_symbol"); |
| 41 | 44 |
| 42 // ------------------------------------------------------------------- | 45 // ------------------------------------------------------------------- |
| 43 | 46 |
| 44 function PromiseCastResolved(value) { | 47 function PromiseCastResolved(value) { |
| 45 if (IsPromise(value)) { | 48 if (IsPromise(value)) { |
| 46 return value; | 49 return value; |
| 47 } else { | 50 } else { |
| 48 var promise = PromiseCreate(); | 51 var promise = PromiseCreate(); |
| 49 ResolvePromise(promise, value); | 52 ResolvePromise(promise, value); |
| 50 return promise; | 53 return promise; |
| 51 } | 54 } |
| 52 } | 55 } |
| 53 | 56 |
| 54 // ES#abstract-ops-async-function-await | 57 // ES#abstract-ops-async-function-await |
| 55 // AsyncFunctionAwait ( value ) | 58 // AsyncFunctionAwait ( value ) |
| 56 // Shared logic for the core of await. The parser desugars | 59 // Shared logic for the core of await. The parser desugars |
| 57 // await awaited | 60 // await awaited |
| 58 // into | 61 // into |
| 59 // yield AsyncFunctionAwait{Caught,Uncaught}(.generator, awaited) | 62 // yield AsyncFunctionAwait{Caught,Uncaught}(.generator, awaited, .promise) |
| 60 // The 'awaited' parameter is the value; the generator stands in | 63 // The 'awaited' parameter is the value; the generator stands in |
| 61 // for the asyncContext, and mark is metadata for debugging | 64 // for the asyncContext, and .promise is the larger promise under |
| 62 function AsyncFunctionAwait(generator, awaited, mark) { | 65 // construction by the enclosing async function. |
| 66 function AsyncFunctionAwait(generator, awaited, outerPromise) { |
| 63 // Promise.resolve(awaited).then( | 67 // Promise.resolve(awaited).then( |
| 64 // value => AsyncFunctionNext(value), | 68 // value => AsyncFunctionNext(value), |
| 65 // error => AsyncFunctionThrow(error) | 69 // error => AsyncFunctionThrow(error) |
| 66 // ); | 70 // ); |
| 67 var promise = PromiseCastResolved(awaited); | 71 var promise = PromiseCastResolved(awaited); |
| 68 | 72 |
| 69 var onFulfilled = sentValue => { | 73 var onFulfilled = sentValue => { |
| 70 %_Call(AsyncFunctionNext, generator, sentValue); | 74 %_Call(AsyncFunctionNext, generator, sentValue); |
| 71 // The resulting Promise is a throwaway, so it doesn't matter what it | 75 // The resulting Promise is a throwaway, so it doesn't matter what it |
| 72 // resolves to. What is important is that we don't end up keeping the | 76 // resolves to. What is important is that we don't end up keeping the |
| 73 // whole chain of intermediate Promises alive by returning the value | 77 // whole chain of intermediate Promises alive by returning the value |
| 74 // of AsyncFunctionNext, as that would create a memory leak. | 78 // of AsyncFunctionNext, as that would create a memory leak. |
| 75 return; | 79 return; |
| 76 }; | 80 }; |
| 77 var onRejected = sentError => { | 81 var onRejected = sentError => { |
| 78 %_Call(AsyncFunctionThrow, generator, sentError); | 82 %_Call(AsyncFunctionThrow, generator, sentError); |
| 79 // Similarly, returning the huge Promise here would cause a long | 83 // Similarly, returning the huge Promise here would cause a long |
| 80 // resolution chain to find what the exception to throw is, and | 84 // resolution chain to find what the exception to throw is, and |
| 81 // create a similar memory leak, and it does not matter what | 85 // create a similar memory leak, and it does not matter what |
| 82 // sort of rejection this intermediate Promise becomes. | 86 // sort of rejection this intermediate Promise becomes. |
| 83 return; | 87 return; |
| 84 } | 88 } |
| 85 | 89 |
| 86 if (mark && DEBUG_IS_ACTIVE && IsPromise(awaited)) { | |
| 87 // Mark the reject handler callback such that it does not influence | |
| 88 // catch prediction. | |
| 89 SET_PRIVATE(onRejected, promiseAwaitHandlerSymbol, true); | |
| 90 } | |
| 91 | |
| 92 // Just forwarding the exception, so no debugEvent for throwawayCapability | 90 // Just forwarding the exception, so no debugEvent for throwawayCapability |
| 93 var throwawayCapability = NewPromiseCapability(GlobalPromise, false); | 91 var throwawayCapability = NewPromiseCapability(GlobalPromise, false); |
| 94 | 92 |
| 95 // The Promise will be thrown away and not handled, but it shouldn't trigger | 93 // The Promise will be thrown away and not handled, but it shouldn't trigger |
| 96 // unhandled reject events as its work is done | 94 // unhandled reject events as its work is done |
| 97 SET_PRIVATE(throwawayCapability.promise, promiseHasHandlerSymbol, true); | 95 SET_PRIVATE(throwawayCapability.promise, promiseHasHandlerSymbol, true); |
| 98 | 96 |
| 99 return PerformPromiseThen(promise, onFulfilled, onRejected, | 97 PerformPromiseThen(promise, onFulfilled, onRejected, throwawayCapability); |
| 100 throwawayCapability); | 98 |
| 99 if (DEBUG_IS_ACTIVE && !IS_UNDEFINED(outerPromise)) { |
| 100 if (IsPromise(awaited)) { |
| 101 // Mark the reject handler callback to be a forwarding edge, rather |
| 102 // than a meaningful catch handler |
| 103 SET_PRIVATE(onRejected, promiseForwardingHandlerSymbol, true); |
| 104 } |
| 105 |
| 106 // Mark the dependency to outerPromise in case the throwaway Promise is |
| 107 // found on the Promise stack |
| 108 SET_PRIVATE(throwawayCapability.promise, promiseHandledBySymbol, |
| 109 outerPromise); |
| 110 } |
| 101 } | 111 } |
| 102 | 112 |
| 103 // Called by the parser from the desugaring of 'await' when catch | 113 // Called by the parser from the desugaring of 'await' when catch |
| 104 // prediction indicates no locally surrounding catch block | 114 // prediction indicates no locally surrounding catch block |
| 105 function AsyncFunctionAwaitUncaught(generator, awaited) { | 115 function AsyncFunctionAwaitUncaught(generator, awaited, outerPromise) { |
| 106 // TODO(littledan): Install a dependency edge from awaited to outerPromise | 116 AsyncFunctionAwait(generator, awaited, outerPromise); |
| 107 return AsyncFunctionAwait(generator, awaited, true); | |
| 108 } | 117 } |
| 109 | 118 |
| 110 // Called by the parser from the desugaring of 'await' when catch | 119 // Called by the parser from the desugaring of 'await' when catch |
| 111 // prediction indicates that there is a locally surrounding catch block | 120 // prediction indicates that there is a locally surrounding catch block |
| 112 function AsyncFunctionAwaitCaught(generator, awaited) { | 121 function AsyncFunctionAwaitCaught(generator, awaited, outerPromise) { |
| 113 if (DEBUG_IS_ACTIVE && IsPromise(awaited)) { | 122 if (DEBUG_IS_ACTIVE && IsPromise(awaited)) { |
| 114 SET_PRIVATE(awaited, promiseHandledHintSymbol, true); | 123 SET_PRIVATE(awaited, promiseHandledHintSymbol, true); |
| 115 } | 124 } |
| 116 return AsyncFunctionAwait(generator, awaited, false); | 125 // Pass undefined for the outer Promise to not waste time setting up |
| 126 // or following the dependency chain when this Promise is already marked |
| 127 // as handled |
| 128 AsyncFunctionAwait(generator, awaited, UNDEFINED); |
| 117 } | 129 } |
| 118 | 130 |
| 119 // How the parser rejects promises from async/await desugaring | 131 // How the parser rejects promises from async/await desugaring |
| 120 function RejectPromiseNoDebugEvent(promise, reason) { | 132 function RejectPromiseNoDebugEvent(promise, reason) { |
| 121 return RejectPromise(promise, reason, false); | 133 return RejectPromise(promise, reason, false); |
| 122 } | 134 } |
| 123 | 135 |
| 124 %InstallToContext([ | 136 %InstallToContext([ |
| 125 "async_function_await_caught", AsyncFunctionAwaitCaught, | 137 "async_function_await_caught", AsyncFunctionAwaitCaught, |
| 126 "async_function_await_uncaught", AsyncFunctionAwaitUncaught, | 138 "async_function_await_uncaught", AsyncFunctionAwaitUncaught, |
| 127 "reject_promise_no_debug_event", RejectPromiseNoDebugEvent, | 139 "reject_promise_no_debug_event", RejectPromiseNoDebugEvent, |
| 128 ]); | 140 ]); |
| 129 | 141 |
| 130 }) | 142 }) |
| OLD | NEW |