Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(474)

Side by Side Diff: src/promise.js

Issue 1293493004: Unify symbols sharing across native scripts and runtime. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: rebase Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/prologue.js ('k') | src/runtime/runtime.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 var $promiseHasUserDefinedRejectHandler;
6 var $promiseStatus;
7 var $promiseValue;
8
9 (function(global, utils) { 5 (function(global, utils) {
10 6
11 "use strict"; 7 "use strict";
12 8
13 %CheckIsBootstrapping(); 9 %CheckIsBootstrapping();
14 10
15 // ------------------------------------------------------------------- 11 // -------------------------------------------------------------------
16 // Imports 12 // Imports
17 13
18 var InternalArray = utils.InternalArray; 14 var InternalArray = utils.InternalArray;
15 var promiseHasHandlerSymbol =
16 utils.GetPrivateSymbol("promise_has_handler_symbol");
17 var promiseOnRejectSymbol = utils.GetPrivateSymbol("promise_on_reject_symbol");
18 var promiseOnResolveSymbol =
19 utils.GetPrivateSymbol("promise_on_resolve_symbol");
20 var promiseRawSymbol = utils.GetPrivateSymbol("promise_raw_symbol");
21 var promiseStatusSymbol = utils.GetPrivateSymbol("promise_status_symbol");
22 var promiseValueSymbol = utils.GetPrivateSymbol("promise_value_symbol");
19 23
20 // ------------------------------------------------------------------- 24 // -------------------------------------------------------------------
21 25
22 // Status values: 0 = pending, +1 = resolved, -1 = rejected 26 // Status values: 0 = pending, +1 = resolved, -1 = rejected
23 var promiseStatus = GLOBAL_PRIVATE("Promise#status");
24 var promiseValue = GLOBAL_PRIVATE("Promise#value");
25 var promiseOnResolve = GLOBAL_PRIVATE("Promise#onResolve");
26 var promiseOnReject = GLOBAL_PRIVATE("Promise#onReject");
27 var promiseRaw = GLOBAL_PRIVATE("Promise#raw");
28 var promiseHasHandler = %PromiseHasHandlerSymbol();
29 var lastMicrotaskId = 0; 27 var lastMicrotaskId = 0;
30 28
31 var GlobalPromise = function Promise(resolver) { 29 var GlobalPromise = function Promise(resolver) {
32 if (resolver === promiseRaw) return; 30 if (resolver === promiseRawSymbol) return;
33 if (!%_IsConstructCall()) throw MakeTypeError(kNotAPromise, this); 31 if (!%_IsConstructCall()) throw MakeTypeError(kNotAPromise, this);
34 if (!IS_SPEC_FUNCTION(resolver)) 32 if (!IS_SPEC_FUNCTION(resolver))
35 throw MakeTypeError(kResolverNotAFunction, resolver); 33 throw MakeTypeError(kResolverNotAFunction, resolver);
36 var promise = PromiseInit(this); 34 var promise = PromiseInit(this);
37 try { 35 try {
38 %DebugPushPromise(promise, Promise); 36 %DebugPushPromise(promise, Promise);
39 resolver(function(x) { PromiseResolve(promise, x) }, 37 resolver(function(x) { PromiseResolve(promise, x) },
40 function(r) { PromiseReject(promise, r) }); 38 function(r) { PromiseReject(promise, r) });
41 } catch (e) { 39 } catch (e) {
42 PromiseReject(promise, e); 40 PromiseReject(promise, e);
43 } finally { 41 } finally {
44 %DebugPopPromise(); 42 %DebugPopPromise();
45 } 43 }
46 } 44 }
47 45
48 // Core functionality. 46 // Core functionality.
49 47
50 function PromiseSet(promise, status, value, onResolve, onReject) { 48 function PromiseSet(promise, status, value, onResolve, onReject) {
51 SET_PRIVATE(promise, promiseStatus, status); 49 SET_PRIVATE(promise, promiseStatusSymbol, status);
52 SET_PRIVATE(promise, promiseValue, value); 50 SET_PRIVATE(promise, promiseValueSymbol, value);
53 SET_PRIVATE(promise, promiseOnResolve, onResolve); 51 SET_PRIVATE(promise, promiseOnResolveSymbol, onResolve);
54 SET_PRIVATE(promise, promiseOnReject, onReject); 52 SET_PRIVATE(promise, promiseOnRejectSymbol, onReject);
55 if (DEBUG_IS_ACTIVE) { 53 if (DEBUG_IS_ACTIVE) {
56 %DebugPromiseEvent({ promise: promise, status: status, value: value }); 54 %DebugPromiseEvent({ promise: promise, status: status, value: value });
57 } 55 }
58 return promise; 56 return promise;
59 } 57 }
60 58
61 function PromiseCreateAndSet(status, value) { 59 function PromiseCreateAndSet(status, value) {
62 var promise = new GlobalPromise(promiseRaw); 60 var promise = new GlobalPromise(promiseRawSymbol);
63 // If debug is active, notify about the newly created promise first. 61 // If debug is active, notify about the newly created promise first.
64 if (DEBUG_IS_ACTIVE) PromiseSet(promise, 0, UNDEFINED); 62 if (DEBUG_IS_ACTIVE) PromiseSet(promise, 0, UNDEFINED);
65 return PromiseSet(promise, status, value); 63 return PromiseSet(promise, status, value);
66 } 64 }
67 65
68 function PromiseInit(promise) { 66 function PromiseInit(promise) {
69 return PromiseSet( 67 return PromiseSet(
70 promise, 0, UNDEFINED, new InternalArray, new InternalArray) 68 promise, 0, UNDEFINED, new InternalArray, new InternalArray)
71 } 69 }
72 70
73 function PromiseDone(promise, status, value, promiseQueue) { 71 function PromiseDone(promise, status, value, promiseQueue) {
74 if (GET_PRIVATE(promise, promiseStatus) === 0) { 72 if (GET_PRIVATE(promise, promiseStatusSymbol) === 0) {
75 var tasks = GET_PRIVATE(promise, promiseQueue); 73 var tasks = GET_PRIVATE(promise, promiseQueue);
76 if (tasks.length) PromiseEnqueue(value, tasks, status); 74 if (tasks.length) PromiseEnqueue(value, tasks, status);
77 PromiseSet(promise, status, value); 75 PromiseSet(promise, status, value);
78 } 76 }
79 } 77 }
80 78
81 function PromiseCoerce(constructor, x) { 79 function PromiseCoerce(constructor, x) {
82 if (!IsPromise(x) && IS_SPEC_OBJECT(x)) { 80 if (!IsPromise(x) && IS_SPEC_OBJECT(x)) {
83 var then; 81 var then;
84 try { 82 try {
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
141 function PromiseIdRejectHandler(r) { throw r } 139 function PromiseIdRejectHandler(r) { throw r }
142 140
143 function PromiseNopResolver() {} 141 function PromiseNopResolver() {}
144 142
145 // ------------------------------------------------------------------- 143 // -------------------------------------------------------------------
146 // Define exported functions. 144 // Define exported functions.
147 145
148 // For bootstrapper. 146 // For bootstrapper.
149 147
150 function IsPromise(x) { 148 function IsPromise(x) {
151 return IS_SPEC_OBJECT(x) && HAS_DEFINED_PRIVATE(x, promiseStatus); 149 return IS_SPEC_OBJECT(x) && HAS_DEFINED_PRIVATE(x, promiseStatusSymbol);
152 } 150 }
153 151
154 function PromiseCreate() { 152 function PromiseCreate() {
155 return new GlobalPromise(PromiseNopResolver) 153 return new GlobalPromise(PromiseNopResolver)
156 } 154 }
157 155
158 function PromiseResolve(promise, x) { 156 function PromiseResolve(promise, x) {
159 PromiseDone(promise, +1, x, promiseOnResolve) 157 PromiseDone(promise, +1, x, promiseOnResolveSymbol)
160 } 158 }
161 159
162 function PromiseReject(promise, r) { 160 function PromiseReject(promise, r) {
163 // Check promise status to confirm that this reject has an effect. 161 // Check promise status to confirm that this reject has an effect.
164 // Call runtime for callbacks to the debugger or for unhandled reject. 162 // Call runtime for callbacks to the debugger or for unhandled reject.
165 if (GET_PRIVATE(promise, promiseStatus) == 0) { 163 if (GET_PRIVATE(promise, promiseStatusSymbol) == 0) {
166 var debug_is_active = DEBUG_IS_ACTIVE; 164 var debug_is_active = DEBUG_IS_ACTIVE;
167 if (debug_is_active || !HAS_DEFINED_PRIVATE(promise, promiseHasHandler)) { 165 if (debug_is_active ||
166 !HAS_DEFINED_PRIVATE(promise, promiseHasHandlerSymbol)) {
168 %PromiseRejectEvent(promise, r, debug_is_active); 167 %PromiseRejectEvent(promise, r, debug_is_active);
169 } 168 }
170 } 169 }
171 PromiseDone(promise, -1, r, promiseOnReject) 170 PromiseDone(promise, -1, r, promiseOnRejectSymbol)
172 } 171 }
173 172
174 // Convenience. 173 // Convenience.
175 174
176 function PromiseDeferred() { 175 function PromiseDeferred() {
177 if (this === GlobalPromise) { 176 if (this === GlobalPromise) {
178 // Optimized case, avoid extra closure. 177 // Optimized case, avoid extra closure.
179 var promise = PromiseInit(new GlobalPromise(promiseRaw)); 178 var promise = PromiseInit(new GlobalPromise(promiseRawSymbol));
180 return { 179 return {
181 promise: promise, 180 promise: promise,
182 resolve: function(x) { PromiseResolve(promise, x) }, 181 resolve: function(x) { PromiseResolve(promise, x) },
183 reject: function(r) { PromiseReject(promise, r) } 182 reject: function(r) { PromiseReject(promise, r) }
184 }; 183 };
185 } else { 184 } else {
186 var result = {promise: UNDEFINED, reject: UNDEFINED, resolve: UNDEFINED}; 185 var result = {promise: UNDEFINED, reject: UNDEFINED, resolve: UNDEFINED};
187 result.promise = new this(function(resolve, reject) { 186 result.promise = new this(function(resolve, reject) {
188 result.resolve = resolve; 187 result.resolve = resolve;
189 result.reject = reject; 188 result.reject = reject;
(...skipping 24 matching lines...) Expand all
214 } 213 }
215 return promise; 214 return promise;
216 } 215 }
217 216
218 // Simple chaining. 217 // Simple chaining.
219 218
220 function PromiseChain(onResolve, onReject) { // a.k.a. flatMap 219 function PromiseChain(onResolve, onReject) { // a.k.a. flatMap
221 onResolve = IS_UNDEFINED(onResolve) ? PromiseIdResolveHandler : onResolve; 220 onResolve = IS_UNDEFINED(onResolve) ? PromiseIdResolveHandler : onResolve;
222 onReject = IS_UNDEFINED(onReject) ? PromiseIdRejectHandler : onReject; 221 onReject = IS_UNDEFINED(onReject) ? PromiseIdRejectHandler : onReject;
223 var deferred = %_CallFunction(this.constructor, PromiseDeferred); 222 var deferred = %_CallFunction(this.constructor, PromiseDeferred);
224 switch (GET_PRIVATE(this, promiseStatus)) { 223 switch (GET_PRIVATE(this, promiseStatusSymbol)) {
225 case UNDEFINED: 224 case UNDEFINED:
226 throw MakeTypeError(kNotAPromise, this); 225 throw MakeTypeError(kNotAPromise, this);
227 case 0: // Pending 226 case 0: // Pending
228 GET_PRIVATE(this, promiseOnResolve).push(onResolve, deferred); 227 GET_PRIVATE(this, promiseOnResolveSymbol).push(onResolve, deferred);
229 GET_PRIVATE(this, promiseOnReject).push(onReject, deferred); 228 GET_PRIVATE(this, promiseOnRejectSymbol).push(onReject, deferred);
230 break; 229 break;
231 case +1: // Resolved 230 case +1: // Resolved
232 PromiseEnqueue(GET_PRIVATE(this, promiseValue), 231 PromiseEnqueue(GET_PRIVATE(this, promiseValueSymbol),
233 [onResolve, deferred], 232 [onResolve, deferred],
234 +1); 233 +1);
235 break; 234 break;
236 case -1: // Rejected 235 case -1: // Rejected
237 if (!HAS_DEFINED_PRIVATE(this, promiseHasHandler)) { 236 if (!HAS_DEFINED_PRIVATE(this, promiseHasHandlerSymbol)) {
238 // Promise has already been rejected, but had no handler. 237 // Promise has already been rejected, but had no handler.
239 // Revoke previously triggered reject event. 238 // Revoke previously triggered reject event.
240 %PromiseRevokeReject(this); 239 %PromiseRevokeReject(this);
241 } 240 }
242 PromiseEnqueue(GET_PRIVATE(this, promiseValue), 241 PromiseEnqueue(GET_PRIVATE(this, promiseValueSymbol),
243 [onReject, deferred], 242 [onReject, deferred],
244 -1); 243 -1);
245 break; 244 break;
246 } 245 }
247 // Mark this promise as having handler. 246 // Mark this promise as having handler.
248 SET_PRIVATE(this, promiseHasHandler, true); 247 SET_PRIVATE(this, promiseHasHandlerSymbol, true);
249 if (DEBUG_IS_ACTIVE) { 248 if (DEBUG_IS_ACTIVE) {
250 %DebugPromiseEvent({ promise: deferred.promise, parentPromise: this }); 249 %DebugPromiseEvent({ promise: deferred.promise, parentPromise: this });
251 } 250 }
252 return deferred.promise; 251 return deferred.promise;
253 } 252 }
254 253
255 function PromiseCatch(onReject) { 254 function PromiseCatch(onReject) {
256 return this.then(UNDEFINED, onReject); 255 return this.then(UNDEFINED, onReject);
257 } 256 }
258 257
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
333 } catch (e) { 332 } catch (e) {
334 deferred.reject(e) 333 deferred.reject(e)
335 } 334 }
336 return deferred.promise; 335 return deferred.promise;
337 } 336 }
338 337
339 338
340 // Utility for debugger 339 // Utility for debugger
341 340
342 function PromiseHasUserDefinedRejectHandlerRecursive(promise) { 341 function PromiseHasUserDefinedRejectHandlerRecursive(promise) {
343 var queue = GET_PRIVATE(promise, promiseOnReject); 342 var queue = GET_PRIVATE(promise, promiseOnRejectSymbol);
344 if (IS_UNDEFINED(queue)) return false; 343 if (IS_UNDEFINED(queue)) return false;
345 for (var i = 0; i < queue.length; i += 2) { 344 for (var i = 0; i < queue.length; i += 2) {
346 if (queue[i] != PromiseIdRejectHandler) return true; 345 if (queue[i] != PromiseIdRejectHandler) return true;
347 if (PromiseHasUserDefinedRejectHandlerRecursive(queue[i + 1].promise)) { 346 if (PromiseHasUserDefinedRejectHandlerRecursive(queue[i + 1].promise)) {
348 return true; 347 return true;
349 } 348 }
350 } 349 }
351 return false; 350 return false;
352 } 351 }
353 352
(...skipping 19 matching lines...) Expand all
373 "race", PromiseRace, 372 "race", PromiseRace,
374 "resolve", PromiseCast 373 "resolve", PromiseCast
375 ]); 374 ]);
376 375
377 utils.InstallFunctions(GlobalPromise.prototype, DONT_ENUM, [ 376 utils.InstallFunctions(GlobalPromise.prototype, DONT_ENUM, [
378 "chain", PromiseChain, 377 "chain", PromiseChain,
379 "then", PromiseThen, 378 "then", PromiseThen,
380 "catch", PromiseCatch 379 "catch", PromiseCatch
381 ]); 380 ]);
382 381
383 $promiseStatus = promiseStatus;
384 $promiseValue = promiseValue;
385
386 utils.ExportToRuntime(function(to) { 382 utils.ExportToRuntime(function(to) {
387 to.promiseStatus = promiseStatus;
388 to.promiseValue = promiseValue;
389 to.PromiseCreate = PromiseCreate; 383 to.PromiseCreate = PromiseCreate;
390 to.PromiseResolve = PromiseResolve; 384 to.PromiseResolve = PromiseResolve;
391 to.PromiseReject = PromiseReject; 385 to.PromiseReject = PromiseReject;
392 to.PromiseChain = PromiseChain; 386 to.PromiseChain = PromiseChain;
393 to.PromiseCatch = PromiseCatch; 387 to.PromiseCatch = PromiseCatch;
394 to.PromiseThen = PromiseThen; 388 to.PromiseThen = PromiseThen;
395 to.PromiseHasUserDefinedRejectHandler = PromiseHasUserDefinedRejectHandler; 389 to.PromiseHasUserDefinedRejectHandler = PromiseHasUserDefinedRejectHandler;
396 }); 390 });
397 391
398 }) 392 })
OLDNEW
« no previous file with comments | « src/prologue.js ('k') | src/runtime/runtime.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698