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 (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 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 44 // ES#sec-createresolvingfunctions | 44 // ES#sec-createresolvingfunctions |
| 45 // CreateResolvingFunctions ( promise ) | 45 // CreateResolvingFunctions ( promise ) |
| 46 function CreateResolvingFunctions(promise) { | 46 function CreateResolvingFunctions(promise) { |
| 47 var alreadyResolved = false; | 47 var alreadyResolved = false; |
| 48 | 48 |
| 49 // ES#sec-promise-resolve-functions | 49 // ES#sec-promise-resolve-functions |
| 50 // Promise Resolve Functions | 50 // Promise Resolve Functions |
| 51 var resolve = value => { | 51 var resolve = value => { |
| 52 if (alreadyResolved === true) return; | 52 if (alreadyResolved === true) return; |
| 53 alreadyResolved = true; | 53 alreadyResolved = true; |
| 54 FulfillPromise(promise, value); | 54 ResolvePromise(promise, value); |
| 55 }; | 55 }; |
| 56 | 56 |
| 57 // ES#sec-promise-reject-functions | 57 // ES#sec-promise-reject-functions |
| 58 // Promise Reject Functions | 58 // Promise Reject Functions |
| 59 var reject = reason => { | 59 var reject = reason => { |
| 60 if (alreadyResolved === true) return; | 60 if (alreadyResolved === true) return; |
| 61 alreadyResolved = true; | 61 alreadyResolved = true; |
| 62 RejectPromise(promise, reason); | 62 RejectPromise(promise, reason); |
| 63 }; | 63 }; |
| 64 | 64 |
| 65 return { | 65 return { |
| 66 __proto__: null, | 66 __proto__: null, |
| 67 resolve: resolve, | 67 resolve: resolve, |
| 68 reject: reject | 68 reject: reject |
| 69 }; | 69 }; |
| 70 } | 70 } |
| 71 | 71 |
| 72 | 72 |
| 73 // ES#sec-promise-executor | 73 // ES#sec-promise-executor |
| 74 // Promise ( executor ) | 74 // Promise ( executor ) |
| 75 var GlobalPromise = function Promise(resolver) { | 75 var GlobalPromise = function Promise(executor) { |
| 76 if (resolver === promiseRawSymbol) { | 76 if (executor === promiseRawSymbol) { |
| 77 return %_NewObject(GlobalPromise, new.target); | 77 return %_NewObject(GlobalPromise, new.target); |
| 78 } | 78 } |
| 79 if (IS_UNDEFINED(new.target)) throw MakeTypeError(kNotAPromise, this); | 79 if (IS_UNDEFINED(new.target)) throw MakeTypeError(kNotAPromise, this); |
| 80 if (!IS_CALLABLE(resolver)) { | 80 if (!IS_CALLABLE(executor)) { |
| 81 throw MakeTypeError(kResolverNotAFunction, resolver); | 81 throw MakeTypeError(kResolverNotAFunction, executor); |
| 82 } | 82 } |
| 83 | 83 |
| 84 var promise = PromiseInit(%_NewObject(GlobalPromise, new.target)); | 84 var promise = PromiseInit(%_NewObject(GlobalPromise, new.target)); |
| 85 var callbacks = CreateResolvingFunctions(promise); | 85 var callbacks = CreateResolvingFunctions(promise); |
| 86 var debug_is_active = DEBUG_IS_ACTIVE; | 86 var debug_is_active = DEBUG_IS_ACTIVE; |
| 87 try { | 87 try { |
| 88 if (debug_is_active) %DebugPushPromise(promise, Promise); | 88 if (debug_is_active) %DebugPushPromise(promise, Promise); |
| 89 resolver(callbacks.resolve, callbacks.reject); | 89 executor(callbacks.resolve, callbacks.reject); |
| 90 } catch (e) { | 90 } catch (e) { |
| 91 %_Call(callbacks.reject, UNDEFINED, e); | 91 %_Call(callbacks.reject, UNDEFINED, e); |
| 92 } finally { | 92 } finally { |
| 93 if (debug_is_active) %DebugPopPromise(); | 93 if (debug_is_active) %DebugPopPromise(); |
| 94 } | 94 } |
| 95 | 95 |
| 96 return promise; | 96 return promise; |
| 97 } | 97 } |
| 98 | 98 |
| 99 // Core functionality. | 99 // Core functionality. |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 111 // If debug is active, notify about the newly created promise first. | 111 // If debug is active, notify about the newly created promise first. |
| 112 if (DEBUG_IS_ACTIVE) PromiseSet(promise, kPending, UNDEFINED); | 112 if (DEBUG_IS_ACTIVE) PromiseSet(promise, kPending, UNDEFINED); |
| 113 return PromiseSet(promise, status, value); | 113 return PromiseSet(promise, status, value); |
| 114 } | 114 } |
| 115 | 115 |
| 116 function PromiseInit(promise) { | 116 function PromiseInit(promise) { |
| 117 return PromiseSet( | 117 return PromiseSet( |
| 118 promise, kPending, UNDEFINED, new InternalArray, new InternalArray) | 118 promise, kPending, UNDEFINED, new InternalArray, new InternalArray) |
| 119 } | 119 } |
| 120 | 120 |
| 121 function PromiseDone(promise, status, value, promiseQueue) { | 121 function FulfillPromise(promise, status, value, promiseQueue) { |
| 122 if (GET_PRIVATE(promise, promiseStateSymbol) === kPending) { | 122 if (GET_PRIVATE(promise, promiseStateSymbol) === kPending) { |
| 123 var tasks = GET_PRIVATE(promise, promiseQueue); | 123 var tasks = GET_PRIVATE(promise, promiseQueue); |
| 124 if (tasks.length) PromiseEnqueue(value, tasks, status); | 124 if (tasks.length) PromiseEnqueue(value, tasks, status); |
| 125 PromiseSet(promise, status, value); | 125 PromiseSet(promise, status, value); |
| 126 } | 126 } |
| 127 } | 127 } |
| 128 | 128 |
| 129 function PromiseHandle(value, handler, deferred) { | 129 function PromiseHandle(value, handler, deferred) { |
| 130 var debug_is_active = DEBUG_IS_ACTIVE; | 130 var debug_is_active = DEBUG_IS_ACTIVE; |
| 131 try { | 131 try { |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 155 if (instrumenting) { | 155 if (instrumenting) { |
| 156 id = ++lastMicrotaskId; | 156 id = ++lastMicrotaskId; |
| 157 name = status === kFulfilled ? "Promise.resolve" : "Promise.reject"; | 157 name = status === kFulfilled ? "Promise.resolve" : "Promise.reject"; |
| 158 %DebugAsyncTaskEvent({ type: "enqueue", id: id, name: name }); | 158 %DebugAsyncTaskEvent({ type: "enqueue", id: id, name: name }); |
| 159 } | 159 } |
| 160 } | 160 } |
| 161 | 161 |
| 162 function PromiseIdResolveHandler(x) { return x } | 162 function PromiseIdResolveHandler(x) { return x } |
| 163 function PromiseIdRejectHandler(r) { throw r } | 163 function PromiseIdRejectHandler(r) { throw r } |
| 164 | 164 |
| 165 function PromiseNopResolver() {} | 165 function PromiseNoopResolver() {} |
|
adamk
2016/05/25 20:57:26
This one doesn't seem spec related?
gsathya
2016/05/25 23:09:24
Yeah, this isn't. I thought nop was a typo
adamk
2016/05/25 23:19:18
Ah, understood. I believe "nop" is an accepted spe
gsathya
2016/05/25 23:53:07
Done.
| |
| 166 | 166 |
| 167 // ------------------------------------------------------------------- | 167 // ------------------------------------------------------------------- |
| 168 // Define exported functions. | 168 // Define exported functions. |
| 169 | 169 |
| 170 // For bootstrapper. | 170 // For bootstrapper. |
| 171 | 171 |
| 172 // ES#sec-ispromise IsPromise ( x ) | 172 // ES#sec-ispromise IsPromise ( x ) |
| 173 function IsPromise(x) { | 173 function IsPromise(x) { |
| 174 return IS_RECEIVER(x) && HAS_DEFINED_PRIVATE(x, promiseStateSymbol); | 174 return IS_RECEIVER(x) && HAS_DEFINED_PRIVATE(x, promiseStateSymbol); |
| 175 } | 175 } |
| 176 | 176 |
| 177 function PromiseCreate() { | 177 function PromiseCreate() { |
| 178 return new GlobalPromise(PromiseNopResolver) | 178 return new GlobalPromise(PromiseNoopResolver) |
| 179 } | 179 } |
| 180 | 180 |
| 181 // ES#sec-fulfillpromise | 181 // ES#sec-resolvepromise |
|
adamk
2016/05/25 20:57:26
This section doesn't exist. The format of these is
gsathya
2016/05/25 23:09:24
Aha. Changed.
| |
| 182 // FulfillPromise ( promise, value) | 182 // ResolvePromise ( promise, value) |
|
adamk
2016/05/25 20:57:26
Nor does this abstract operation. What does it cor
gsathya
2016/05/25 23:09:24
Yeah, I've updated the anchor to link to this. Let
| |
| 183 function FulfillPromise(promise, x) { | 183 function ResolvePromise(promise, value) { |
| 184 if (x === promise) { | 184 if (value === promise) { |
| 185 return RejectPromise(promise, MakeTypeError(kPromiseCyclic, x)); | 185 return RejectPromise(promise, MakeTypeError(kPromiseCyclic, value)); |
| 186 } | 186 } |
| 187 if (IS_RECEIVER(x)) { | 187 if (IS_RECEIVER(value)) { |
| 188 // 25.4.1.3.2 steps 8-12 | 188 // 25.4.1.3.2 steps 8-12 |
| 189 try { | 189 try { |
| 190 var then = x.then; | 190 var then = value.then; |
| 191 } catch (e) { | 191 } catch (e) { |
| 192 return RejectPromise(promise, e); | 192 return RejectPromise(promise, e); |
| 193 } | 193 } |
| 194 if (IS_CALLABLE(then)) { | 194 if (IS_CALLABLE(then)) { |
| 195 // PromiseResolveThenableJob | 195 // PromiseResolveThenableJob |
| 196 var id, name, instrumenting = DEBUG_IS_ACTIVE; | 196 var id, name, instrumenting = DEBUG_IS_ACTIVE; |
| 197 %EnqueueMicrotask(function() { | 197 %EnqueueMicrotask(function() { |
| 198 if (instrumenting) { | 198 if (instrumenting) { |
| 199 %DebugAsyncTaskEvent({ type: "willHandle", id: id, name: name }); | 199 %DebugAsyncTaskEvent({ type: "willHandle", id: id, name: name }); |
| 200 } | 200 } |
| 201 var callbacks = CreateResolvingFunctions(promise); | 201 var callbacks = CreateResolvingFunctions(promise); |
| 202 try { | 202 try { |
| 203 %_Call(then, x, callbacks.resolve, callbacks.reject); | 203 %_Call(then, value, callbacks.resolve, callbacks.reject); |
| 204 } catch (e) { | 204 } catch (e) { |
| 205 %_Call(callbacks.reject, UNDEFINED, e); | 205 %_Call(callbacks.reject, UNDEFINED, e); |
| 206 } | 206 } |
| 207 if (instrumenting) { | 207 if (instrumenting) { |
| 208 %DebugAsyncTaskEvent({ type: "didHandle", id: id, name: name }); | 208 %DebugAsyncTaskEvent({ type: "didHandle", id: id, name: name }); |
| 209 } | 209 } |
| 210 }); | 210 }); |
| 211 if (instrumenting) { | 211 if (instrumenting) { |
| 212 id = ++lastMicrotaskId; | 212 id = ++lastMicrotaskId; |
| 213 name = "PromseResolveThenableJob"; | 213 name = "PromseResolveThenableJob"; |
| 214 %DebugAsyncTaskEvent({ type: "enqueue", id: id, name: name }); | 214 %DebugAsyncTaskEvent({ type: "enqueue", id: id, name: name }); |
| 215 } | 215 } |
| 216 return; | 216 return; |
| 217 } | 217 } |
| 218 } | 218 } |
| 219 PromiseDone(promise, kFulfilled, x, promiseFulfillReactionsSymbol); | 219 FulfillPromise(promise, kFulfilled, value, promiseFulfillReactionsSymbol); |
| 220 } | 220 } |
| 221 | 221 |
| 222 // ES#sec-rejectpromise | 222 // ES#sec-rejectpromise |
| 223 // RejectPromise ( promise, reason ) | 223 // RejectPromise ( promise, reason ) |
| 224 function RejectPromise(promise, r) { | 224 function RejectPromise(promise, reason) { |
| 225 // Check promise status to confirm that this reject has an effect. | 225 // Check promise status to confirm that this reject has an effect. |
| 226 // Call runtime for callbacks to the debugger or for unhandled reject. | 226 // Call runtime for callbacks to the debugger or for unhandled reject. |
| 227 if (GET_PRIVATE(promise, promiseStateSymbol) === kPending) { | 227 if (GET_PRIVATE(promise, promiseStateSymbol) === kPending) { |
| 228 var debug_is_active = DEBUG_IS_ACTIVE; | 228 var debug_is_active = DEBUG_IS_ACTIVE; |
| 229 if (debug_is_active || | 229 if (debug_is_active || |
| 230 !HAS_DEFINED_PRIVATE(promise, promiseHasHandlerSymbol)) { | 230 !HAS_DEFINED_PRIVATE(promise, promiseHasHandlerSymbol)) { |
| 231 %PromiseRejectEvent(promise, r, debug_is_active); | 231 %PromiseRejectEvent(promise, reason, debug_is_active); |
| 232 } | 232 } |
| 233 } | 233 } |
| 234 PromiseDone(promise, kRejected, r, promiseRejectReactionsSymbol) | 234 FulfillPromise(promise, kRejected, reason, promiseRejectReactionsSymbol) |
| 235 } | 235 } |
| 236 | 236 |
| 237 // ES#sec-newpromisecapability | 237 // ES#sec-newpromisecapability |
| 238 // NewPromiseCapability ( C ) | 238 // NewPromiseCapability ( C ) |
| 239 function NewPromiseCapability(C) { | 239 function NewPromiseCapability(C) { |
| 240 if (C === GlobalPromise) { | 240 if (C === GlobalPromise) { |
| 241 // Optimized case, avoid extra closure. | 241 // Optimized case, avoid extra closure. |
| 242 var promise = PromiseInit(new GlobalPromise(promiseRawSymbol)); | 242 var promise = PromiseInit(new GlobalPromise(promiseRawSymbol)); |
| 243 var callbacks = CreateResolvingFunctions(promise); | 243 var callbacks = CreateResolvingFunctions(promise); |
| 244 return { | 244 return { |
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 489 "then", PromiseThen, | 489 "then", PromiseThen, |
| 490 "catch", PromiseCatch | 490 "catch", PromiseCatch |
| 491 ]); | 491 ]); |
| 492 | 492 |
| 493 %InstallToContext([ | 493 %InstallToContext([ |
| 494 "promise_catch", PromiseCatch, | 494 "promise_catch", PromiseCatch, |
| 495 "promise_chain", PromiseChain, | 495 "promise_chain", PromiseChain, |
| 496 "promise_create", PromiseCreate, | 496 "promise_create", PromiseCreate, |
| 497 "promise_has_user_defined_reject_handler", PromiseHasUserDefinedRejectHandler, | 497 "promise_has_user_defined_reject_handler", PromiseHasUserDefinedRejectHandler, |
| 498 "promise_reject", RejectPromise, | 498 "promise_reject", RejectPromise, |
| 499 "promise_resolve", FulfillPromise, | 499 "promise_resolve", ResolvePromise, |
| 500 "promise_then", PromiseThen, | 500 "promise_then", PromiseThen, |
| 501 "promise_create_rejected", PromiseCreateRejected, | 501 "promise_create_rejected", PromiseCreateRejected, |
| 502 "promise_create_resolved", PromiseCreateResolved | 502 "promise_create_resolved", PromiseCreateResolved |
| 503 ]); | 503 ]); |
| 504 | 504 |
| 505 // This allows extras to create promises quickly without building extra | 505 // This allows extras to create promises quickly without building extra |
| 506 // resolve/reject closures, and allows them to later resolve and reject any | 506 // resolve/reject closures, and allows them to later resolve and reject any |
| 507 // promise without having to hold on to those closures forever. | 507 // promise without having to hold on to those closures forever. |
| 508 utils.InstallFunctions(extrasUtils, 0, [ | 508 utils.InstallFunctions(extrasUtils, 0, [ |
| 509 "createPromise", PromiseCreate, | 509 "createPromise", PromiseCreate, |
| 510 "resolvePromise", FulfillPromise, | 510 "resolvePromise", ResolvePromise, |
| 511 "rejectPromise", RejectPromise | 511 "rejectPromise", RejectPromise |
| 512 ]); | 512 ]); |
| 513 | 513 |
| 514 // TODO(v8:4567): Allow experimental natives to remove function prototype | 514 // TODO(v8:4567): Allow experimental natives to remove function prototype |
| 515 [PromiseChain, PromiseDefer, PromiseAccept].forEach( | 515 [PromiseChain, PromiseDefer, PromiseAccept].forEach( |
| 516 fn => %FunctionRemovePrototype(fn)); | 516 fn => %FunctionRemovePrototype(fn)); |
| 517 | 517 |
| 518 utils.Export(function(to) { | 518 utils.Export(function(to) { |
| 519 to.PromiseChain = PromiseChain; | 519 to.PromiseChain = PromiseChain; |
| 520 to.PromiseDefer = PromiseDefer; | 520 to.PromiseDefer = PromiseDefer; |
| 521 to.PromiseAccept = PromiseAccept; | 521 to.PromiseAccept = PromiseAccept; |
| 522 | 522 |
| 523 to.PromiseCreateRejected = PromiseCreateRejected; | 523 to.PromiseCreateRejected = PromiseCreateRejected; |
| 524 to.PromiseCreateResolved = PromiseCreateResolved; | 524 to.PromiseCreateResolved = PromiseCreateResolved; |
| 525 to.PromiseThen = PromiseThen; | 525 to.PromiseThen = PromiseThen; |
| 526 }); | 526 }); |
| 527 | 527 |
| 528 }) | 528 }) |
| OLD | NEW |