| OLD | NEW |
| 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 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 95 | 95 |
| 96 function PromiseResolve(promise, x) { | 96 function PromiseResolve(promise, x) { |
| 97 PromiseDone(promise, +1, x, promiseOnResolve) | 97 PromiseDone(promise, +1, x, promiseOnResolve) |
| 98 } | 98 } |
| 99 | 99 |
| 100 function PromiseReject(promise, r) { | 100 function PromiseReject(promise, r) { |
| 101 PromiseDone(promise, -1, r, promiseOnReject) | 101 PromiseDone(promise, -1, r, promiseOnReject) |
| 102 } | 102 } |
| 103 | 103 |
| 104 | 104 |
| 105 // For API. |
| 106 |
| 107 function PromiseNopResolver() {} |
| 108 |
| 109 function PromiseCreate() { |
| 110 return new Promise(PromiseNopResolver) |
| 111 } |
| 112 |
| 113 |
| 105 // Convenience. | 114 // Convenience. |
| 106 | 115 |
| 107 function PromiseDeferred() { | 116 function PromiseDeferred() { |
| 108 if (this === $Promise) { | 117 if (this === $Promise) { |
| 109 // Optimized case, avoid extra closure. | 118 // Optimized case, avoid extra closure. |
| 110 var promise = PromiseInit(new Promise(promiseRaw)); | 119 var promise = PromiseInit(new Promise(promiseRaw)); |
| 111 return { | 120 return { |
| 112 promise: promise, | 121 promise: promise, |
| 113 resolve: function(x) { PromiseResolve(promise, x) }, | 122 resolve: function(x) { PromiseResolve(promise, x) }, |
| 114 reject: function(r) { PromiseReject(promise, r) } | 123 reject: function(r) { PromiseReject(promise, r) } |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 210 return x === that ? onReject(MakeTypeError('promise_cyclic', [x])) : | 219 return x === that ? onReject(MakeTypeError('promise_cyclic', [x])) : |
| 211 IsPromise(x) ? x.then(onResolve, onReject) : onResolve(x); | 220 IsPromise(x) ? x.then(onResolve, onReject) : onResolve(x); |
| 212 }, | 221 }, |
| 213 onReject | 222 onReject |
| 214 ); | 223 ); |
| 215 } | 224 } |
| 216 | 225 |
| 217 PromiseCoerce.table = new $WeakMap; | 226 PromiseCoerce.table = new $WeakMap; |
| 218 | 227 |
| 219 function PromiseCoerce(constructor, x) { | 228 function PromiseCoerce(constructor, x) { |
| 220 if (!(IsPromise(x) || IS_NULL_OR_UNDEFINED(x))) { | 229 if (!IsPromise(x) && IS_SPEC_OBJECT(x)) { |
| 221 var then = x.then; | 230 var then; |
| 231 try { |
| 232 then = x.then; |
| 233 } catch(e) { |
| 234 var deferred = %_CallFunction(constructor, PromiseDeferred); |
| 235 PromiseCoerce.table.set(x, deferred.promise); |
| 236 deferred.reject(e); |
| 237 return deferred.promise; |
| 238 } |
| 222 if (typeof then === 'function') { | 239 if (typeof then === 'function') { |
| 223 if (PromiseCoerce.table.has(x)) { | 240 if (PromiseCoerce.table.has(x)) { |
| 224 return PromiseCoerce.table.get(x); | 241 return PromiseCoerce.table.get(x); |
| 225 } else { | 242 } else { |
| 226 var deferred = %_CallFunction(constructor, PromiseDeferred); | 243 var deferred = %_CallFunction(constructor, PromiseDeferred); |
| 227 PromiseCoerce.table.set(x, deferred.promise); | 244 PromiseCoerce.table.set(x, deferred.promise); |
| 228 try { | 245 try { |
| 229 %_CallFunction(x, deferred.resolve, deferred.reject, then); | 246 %_CallFunction(x, deferred.resolve, deferred.reject, then); |
| 230 } catch(e) { | 247 } catch(e) { |
| 231 deferred.reject(e); | 248 deferred.reject(e); |
| 232 } | 249 } |
| 233 return deferred.promise; | 250 return deferred.promise; |
| 234 } | 251 } |
| 235 } | 252 } |
| 236 } | 253 } |
| 237 return x; | 254 return x; |
| 238 } | 255 } |
| 239 | 256 |
| 240 | 257 |
| 241 // Combinators. | 258 // Combinators. |
| 242 | 259 |
| 243 function PromiseCast(x) { | 260 function PromiseCast(x) { |
| 244 // TODO(rossberg): cannot do better until we support @@create. | 261 // TODO(rossberg): cannot do better until we support @@create. |
| 245 return IsPromise(x) ? x : this.resolve(x); | 262 return IsPromise(x) ? x : this.resolve(x); |
| 246 } | 263 } |
| 247 | 264 |
| 248 function PromiseAll(values) { | 265 function PromiseAll(values) { |
| 249 var deferred = %_CallFunction(this, PromiseDeferred); | 266 var deferred = %_CallFunction(this, PromiseDeferred); |
| 250 var resolutions = []; | 267 var resolutions = []; |
| 268 if (!%_IsArray(values)) { |
| 269 deferred.reject(MakeTypeError('invalid_argument')); |
| 270 return deferred.promise; |
| 271 } |
| 251 try { | 272 try { |
| 252 var count = values.length; | 273 var count = values.length; |
| 253 if (count === 0) { | 274 if (count === 0) { |
| 254 deferred.resolve(resolutions); | 275 deferred.resolve(resolutions); |
| 255 } else { | 276 } else { |
| 256 for (var i = 0; i < values.length; ++i) { | 277 for (var i = 0; i < values.length; ++i) { |
| 257 this.cast(values[i]).chain( | 278 this.cast(values[i]).then( |
| 258 function(i, x) { | 279 function(i, x) { |
| 259 resolutions[i] = x; | 280 resolutions[i] = x; |
| 260 if (--count === 0) deferred.resolve(resolutions); | 281 if (--count === 0) deferred.resolve(resolutions); |
| 261 }.bind(UNDEFINED, i), // TODO(rossberg): use let loop once available | 282 }.bind(UNDEFINED, i), // TODO(rossberg): use let loop once available |
| 262 function(r) { deferred.reject(r) } | 283 function(r) { deferred.reject(r) } |
| 263 ); | 284 ); |
| 264 } | 285 } |
| 265 } | 286 } |
| 266 } catch (e) { | 287 } catch (e) { |
| 267 deferred.reject(e) | 288 deferred.reject(e) |
| 268 } | 289 } |
| 269 return deferred.promise; | 290 return deferred.promise; |
| 270 } | 291 } |
| 271 | 292 |
| 272 function PromiseOne(values) { | 293 function PromiseOne(values) { |
| 273 var deferred = %_CallFunction(this, PromiseDeferred); | 294 var deferred = %_CallFunction(this, PromiseDeferred); |
| 295 if (!%_IsArray(values)) { |
| 296 deferred.reject(MakeTypeError('invalid_argument')); |
| 297 return deferred.promise; |
| 298 } |
| 274 try { | 299 try { |
| 275 for (var i = 0; i < values.length; ++i) { | 300 for (var i = 0; i < values.length; ++i) { |
| 276 this.cast(values[i]).chain( | 301 this.cast(values[i]).then( |
| 277 function(x) { deferred.resolve(x) }, | 302 function(x) { deferred.resolve(x) }, |
| 278 function(r) { deferred.reject(r) } | 303 function(r) { deferred.reject(r) } |
| 279 ); | 304 ); |
| 280 } | 305 } |
| 281 } catch (e) { | 306 } catch (e) { |
| 282 deferred.reject(e) | 307 deferred.reject(e) |
| 283 } | 308 } |
| 284 return deferred.promise; | 309 return deferred.promise; |
| 285 } | 310 } |
| 286 | 311 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 299 "cast", PromiseCast | 324 "cast", PromiseCast |
| 300 ]); | 325 ]); |
| 301 InstallFunctions($Promise.prototype, DONT_ENUM, [ | 326 InstallFunctions($Promise.prototype, DONT_ENUM, [ |
| 302 "chain", PromiseChain, | 327 "chain", PromiseChain, |
| 303 "then", PromiseThen, | 328 "then", PromiseThen, |
| 304 "catch", PromiseCatch | 329 "catch", PromiseCatch |
| 305 ]); | 330 ]); |
| 306 } | 331 } |
| 307 | 332 |
| 308 SetUpPromise(); | 333 SetUpPromise(); |
| OLD | NEW |