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

Side by Side Diff: src/promise.js

Issue 99573002: Promises: some adaptations to spec (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Throw on non-function resolver Created 6 years, 11 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 | Annotate | Revision Log
« no previous file with comments | « src/messages.js ('k') | src/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 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
55 var promiseOnResolve = NEW_PRIVATE("Promise#onResolve"); 55 var promiseOnResolve = NEW_PRIVATE("Promise#onResolve");
56 var promiseOnReject = NEW_PRIVATE("Promise#onReject"); 56 var promiseOnReject = NEW_PRIVATE("Promise#onReject");
57 var promiseRaw = NEW_PRIVATE("Promise#raw"); 57 var promiseRaw = NEW_PRIVATE("Promise#raw");
58 58
59 function IsPromise(x) { 59 function IsPromise(x) {
60 return IS_SPEC_OBJECT(x) && %HasLocalProperty(x, promiseStatus); 60 return IS_SPEC_OBJECT(x) && %HasLocalProperty(x, promiseStatus);
61 } 61 }
62 62
63 function Promise(resolver) { 63 function Promise(resolver) {
64 if (resolver === promiseRaw) return; 64 if (resolver === promiseRaw) return;
65 if (!%_IsConstructCall()) throw MakeTypeError('not_a_promise', [this]);
arv (Not doing code reviews) 2014/01/09 15:47:15 Doesn't this break sub classing? function SubProm
rossberg 2014/01/09 16:09:56 I agree, but it's what the spec says.
arv (Not doing code reviews) 2014/01/09 19:13:27 I think this is the right call for now. Once we su
66 if (typeof resolver !== 'function')
67 throw MakeTypeError('resolver_not_a_function', [resolver]);
65 var promise = PromiseInit(this); 68 var promise = PromiseInit(this);
66 resolver(function(x) { PromiseResolve(promise, x) }, 69 try {
67 function(r) { PromiseReject(promise, r) }); 70 resolver(function(x) { PromiseResolve(promise, x) },
68 // TODO(rossberg): current draft makes exception from this call asynchronous, 71 function(r) { PromiseReject(promise, r) });
69 // but that's probably a mistake. 72 } catch (e) {
73 PromiseReject(promise, e);
74 }
70 } 75 }
71 76
72 function PromiseSet(promise, status, value, onResolve, onReject) { 77 function PromiseSet(promise, status, value, onResolve, onReject) {
73 SET_PRIVATE(promise, promiseStatus, status); 78 SET_PRIVATE(promise, promiseStatus, status);
74 SET_PRIVATE(promise, promiseValue, value); 79 SET_PRIVATE(promise, promiseValue, value);
75 SET_PRIVATE(promise, promiseOnResolve, onResolve); 80 SET_PRIVATE(promise, promiseOnResolve, onResolve);
76 SET_PRIVATE(promise, promiseOnReject, onReject); 81 SET_PRIVATE(promise, promiseOnReject, onReject);
77 return promise; 82 return promise;
78 } 83 }
79 84
80 function PromiseInit(promise) { 85 function PromiseInit(promise) {
81 return PromiseSet(promise, 0, UNDEFINED, new InternalArray, new InternalArray) 86 return PromiseSet(promise, 0, UNDEFINED, new InternalArray, new InternalArray)
82 } 87 }
83 88
84 function PromiseDone(promise, status, value, promiseQueue) { 89 function PromiseDone(promise, status, value, promiseQueue) {
85 if (GET_PRIVATE(promise, promiseStatus) !== 0) return; 90 if (GET_PRIVATE(promise, promiseStatus) === 0) {
86 PromiseEnqueue(value, GET_PRIVATE(promise, promiseQueue)); 91 PromiseEnqueue(value, GET_PRIVATE(promise, promiseQueue));
87 PromiseSet(promise, status, value); 92 PromiseSet(promise, status, value);
93 }
88 } 94 }
89 95
90 function PromiseResolve(promise, x) { 96 function PromiseResolve(promise, x) {
91 PromiseDone(promise, +1, x, promiseOnResolve) 97 PromiseDone(promise, +1, x, promiseOnResolve)
92 } 98 }
93 99
94 function PromiseReject(promise, r) { 100 function PromiseReject(promise, r) {
95 PromiseDone(promise, -1, r, promiseOnReject) 101 PromiseDone(promise, -1, r, promiseOnReject)
96 } 102 }
97 103
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
212 return x === that ? onReject(MakeTypeError('promise_cyclic', [x])) : 218 return x === that ? onReject(MakeTypeError('promise_cyclic', [x])) :
213 IsPromise(x) ? x.then(onResolve, onReject) : onResolve(x); 219 IsPromise(x) ? x.then(onResolve, onReject) : onResolve(x);
214 }, 220 },
215 onReject 221 onReject
216 ); 222 );
217 } 223 }
218 224
219 PromiseCoerce.table = new $WeakMap; 225 PromiseCoerce.table = new $WeakMap;
220 226
221 function PromiseCoerce(constructor, x) { 227 function PromiseCoerce(constructor, x) {
222 var then; 228 if (!(IsPromise(x) || IS_NULL_OR_UNDEFINED(x))) {
223 if (IsPromise(x)) { 229 var then = x.then;
224 return x; 230 if (typeof then === 'function') {
225 } else if (!IS_NULL_OR_UNDEFINED(x) && %IsCallable(then = x.then)) { 231 if (PromiseCoerce.table.has(x)) {
226 if (PromiseCoerce.table.has(x)) { 232 return PromiseCoerce.table.get(x);
227 return PromiseCoerce.table.get(x); 233 } else {
228 } else { 234 var deferred = %_CallFunction(constructor, PromiseDeferred);
229 var deferred = constructor.deferred(); 235 PromiseCoerce.table.set(x, deferred.promise);
230 PromiseCoerce.table.set(x, deferred.promise); 236 try {
231 try { 237 %_CallFunction(x, deferred.resolve, deferred.reject, then);
232 %_CallFunction(x, deferred.resolve, deferred.reject, then); 238 } catch(e) {
233 } catch(e) { 239 deferred.reject(e);
234 deferred.reject(e); 240 }
241 return deferred.promise;
235 } 242 }
236 return deferred.promise;
237 } 243 }
238 } else {
239 return x;
240 } 244 }
245 return x;
241 } 246 }
242 247
243 248
244 // Combinators. 249 // Combinators.
245 250
246 function PromiseCast(x) { 251 function PromiseCast(x) {
247 // TODO(rossberg): cannot do better until we support @@create. 252 // TODO(rossberg): cannot do better until we support @@create.
248 return IsPromise(x) ? x : this.resolved(x); 253 return IsPromise(x) ? x : this.resolve(x);
249 } 254 }
250 255
251 function PromiseAll(values) { 256 function PromiseAll(values) {
252 var deferred = this.deferred(); 257 var deferred = %_CallFunction(this, PromiseDeferred);
253 var resolutions = []; 258 var resolutions = [];
254 var count = values.length; 259 try {
255 if (count === 0) { 260 var count = values.length;
256 deferred.resolve(resolutions); 261 if (count === 0) {
257 } else { 262 deferred.resolve(resolutions);
258 for (var i = 0; i < values.length; ++i) { 263 } else {
259 this.cast(values[i]).chain( 264 for (var i = 0; i < values.length; ++i) {
260 function(i, x) { 265 this.cast(values[i]).chain(
261 resolutions[i] = x; 266 function(i, x) {
262 if (--count === 0) deferred.resolve(resolutions); 267 resolutions[i] = x;
263 }.bind(UNDEFINED, i), // TODO(rossberg): use let loop once available 268 if (--count === 0) deferred.resolve(resolutions);
264 function(r) { 269 }.bind(UNDEFINED, i), // TODO(rossberg): use let loop once available
265 if (count > 0) { count = 0; deferred.reject(r) } 270 function(r) { deferred.reject(r) }
266 } 271 );
267 ); 272 }
268 } 273 }
274 } catch (e) {
275 deferred.reject(e)
269 } 276 }
270 return deferred.promise; 277 return deferred.promise;
271 } 278 }
272 279
273 function PromiseOne(values) { // a.k.a. race 280 function PromiseOne(values) {
arv (Not doing code reviews) 2014/01/09 15:47:15 Rename this to PromiseRace to match? Why isn't th
rossberg 2014/01/09 16:09:56 Because the resolve/reject functions at some point
274 var deferred = this.deferred(); 281 var deferred = %_CallFunction(this, PromiseDeferred);
275 var done = false; 282 try {
276 for (var i = 0; i < values.length; ++i) { 283 for (var i = 0; i < values.length; ++i) {
277 this.cast(values[i]).chain( 284 this.cast(values[i]).chain(
278 function(x) { if (!done) { done = true; deferred.resolve(x) } }, 285 function(x) { deferred.resolve(x) },
279 function(r) { if (!done) { done = true; deferred.reject(r) } } 286 function(r) { deferred.reject(r) }
280 ); 287 );
288 }
289 } catch (e) {
290 deferred.reject(e)
281 } 291 }
282 return deferred.promise; 292 return deferred.promise;
283 } 293 }
284 294
285 //------------------------------------------------------------------- 295 //-------------------------------------------------------------------
286 296
287 function SetUpPromise() { 297 function SetUpPromise() {
288 %CheckIsBootstrapping() 298 %CheckIsBootstrapping()
289 global.Promise = $Promise; 299 global.Promise = $Promise;
290 InstallFunctions($Promise, DONT_ENUM, [ 300 InstallFunctions($Promise, DONT_ENUM, [
291 "deferred", PromiseDeferred, 301 "defer", PromiseDeferred,
292 "resolved", PromiseResolved, 302 "resolve", PromiseResolved,
293 "rejected", PromiseRejected, 303 "reject", PromiseRejected,
294 "all", PromiseAll, 304 "all", PromiseAll,
295 "one", PromiseOne, 305 "race", PromiseOne,
296 "cast", PromiseCast 306 "cast", PromiseCast
297 ]); 307 ]);
298 InstallFunctions($Promise.prototype, DONT_ENUM, [ 308 InstallFunctions($Promise.prototype, DONT_ENUM, [
299 "chain", PromiseChain, 309 "chain", PromiseChain,
arv (Not doing code reviews) 2014/01/09 15:47:15 Any plan to upstream chain into the spec?
rossberg 2014/01/09 16:09:56 Yes, but current stakeholders refuse to consider i
300 "then", PromiseThen, 310 "then", PromiseThen,
301 "catch", PromiseCatch 311 "catch", PromiseCatch
302 ]); 312 ]);
303 } 313 }
304 314
305 SetUpPromise(); 315 SetUpPromise();
OLDNEW
« no previous file with comments | « src/messages.js ('k') | src/runtime.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698