Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 /// This library adapts ES6 generators to implement Dart's async/await. | 5 /// This library adapts ES6 generators to implement Dart's async/await. |
| 6 /// It's designed to interact with Dart's Future/Stream and follow Dart | 6 /// It's designed to interact with Dart's Future/Stream and follow Dart |
| 7 /// async/await semantics. | 7 /// async/await semantics. |
| 8 /// See https://github.com/dart-lang/sdk/issues/27315 for ideas on | 8 /// See https://github.com/dart-lang/sdk/issues/27315 for ideas on |
| 9 /// reconciling Dart's Future and ES6 Promise. | 9 /// reconciling Dart's Future and ES6 Promise. |
| 10 /// Inspired by `co`: https://github.com/tj/co/blob/master/index.js, which is a | 10 /// Inspired by `co`: https://github.com/tj/co/blob/master/index.js, which is a |
| 11 /// stepping stone for proposed ES7 async/await, and uses ES6 Promises. | 11 /// stepping stone for proposed ES7 async/await, and uses ES6 Promises. |
| 12 part of dart._runtime; | 12 part of dart._runtime; |
| 13 | 13 |
| 14 final _jsIterator = JS('', 'Symbol("_jsIterator")'); | 14 final _jsIterator = JS('', 'Symbol("_jsIterator")'); |
| 15 final _current = JS('', 'Symbol("_current")'); | 15 final _current = JS('', 'Symbol("_current")'); |
| 16 | 16 |
| 17 syncStar(gen, E, @rest args) => JS( | 17 syncStar(gen, E, @rest args) => JS( |
| 18 '', | 18 '', |
| 19 '''(() => { | 19 '''(() => { |
| 20 const SyncIterable_E = ${getGenericClass(SyncIterable)}($E); | 20 const SyncIterable_E = ${getGenericClass(SyncIterable)}($E); |
| 21 return new SyncIterable_E($gen, $args); | 21 return new SyncIterable_E($gen, $args); |
| 22 })()'''); | 22 })()'''); |
| 23 | 23 |
| 24 @JSExportName('async') | 24 @JSExportName('async') |
| 25 async_(gen, T, @rest args) => JS( | 25 async_(gen, T, @rest args) => JS( |
| 26 '', | 26 '', |
| 27 '''(() => { | 27 '''(() => { |
| 28 let iter; | 28 let iter; |
| 29 let FutureT = ${getGenericClass(Future)}($T); | |
|
Jennifer Messerly
2017/04/06 20:01:52
const FutureT = ... ?
vsm
2017/04/06 21:31:32
Done.
| |
| 30 let _Future = $Future.new(() => null).runtimeType; | |
|
vsm
2017/04/06 19:45:05
Is there a better way to get this type?
Jennifer Messerly
2017/04/06 20:01:52
good question. I'd do it like this:
let _Futu
vsm
2017/04/06 21:31:32
Acknowledged.
| |
| 29 function onValue(res) { | 31 function onValue(res) { |
| 30 if (res === void 0) res = null; | 32 if (res === void 0) res = null; |
| 31 return next(iter.next(res)); | 33 return next(iter.next(res)); |
| 32 } | 34 } |
| 33 function onError(err) { | 35 function onError(err) { |
| 34 // If the awaited Future throws, we want to convert this to an exception | 36 // If the awaited Future throws, we want to convert this to an exception |
| 35 // thrown from the `yield` point, as if it was thrown there. | 37 // thrown from the `yield` point, as if it was thrown there. |
| 36 // | 38 // |
| 37 // If the exception is not caught inside `gen`, it will emerge here, which | 39 // If the exception is not caught inside `gen`, it will emerge here, which |
| 38 // will send it to anyone listening on this async function's Future<T>. | 40 // will send it to anyone listening on this async function's Future<T>. |
| 39 // | 41 // |
| 40 // In essence, we are giving the code inside the generator a chance to | 42 // In essence, we are giving the code inside the generator a chance to |
| 41 // use try-catch-finally. | 43 // use try-catch-finally. |
| 42 return next(iter.throw(err)); | 44 return next(iter.throw(err)); |
| 43 } | 45 } |
| 44 function next(ret) { | 46 function next(ret) { |
| 45 let future = ret.value; | 47 let future = ret.value; |
| 46 if (ret.done) { | 48 if (ret.done) { |
| 47 return ret.value; | 49 return ret.value; |
| 48 } | 50 } |
| 49 // Checks if the awaited value is a Future. | 51 // Wraps if future is not a native Future. |
| 50 if (!$instanceOf(future, $Future)) { | 52 if (!$instanceOf(future, _Future)) { |
|
Jennifer Messerly
2017/04/06 20:01:52
you could just match the exact runtime type here,
vsm
2017/04/06 21:31:32
I don't think that's quite right - _Future<int> !=
| |
| 51 future = $Future.value(future); | 53 future = $Future.value(future); |
| 52 } | 54 } |
| 53 // Chain the Future so `await` receives the Future's value. | 55 // Chain the Future so `await` receives the Future's value. |
| 54 return future.then($dynamic)(onValue, {onError: onError}); | 56 return future.then($dynamic)(onValue, {onError: onError}); |
| 55 } | 57 } |
| 56 let FutureT = ${getGenericClass(Future)(T)}; | |
| 57 return FutureT.microtask(function() { | 58 return FutureT.microtask(function() { |
|
Jennifer Messerly
2017/04/06 20:01:52
let result = FutureT.microtask(function() { ... })
vsm
2017/04/06 21:31:32
Clever! Done with some slight mods.
| |
| 58 iter = $gen.apply(null, $args)[Symbol.iterator](); | 59 iter = $gen.apply(null, $args)[Symbol.iterator](); |
| 59 var result = onValue(); | 60 var result = onValue(); |
| 60 if ($strongInstanceOf(result, FutureT) == null) { | 61 if ($strongInstanceOf(result, FutureT) == null) { |
| 61 // Chain the Future<dynamic> to a Future<T> to produce the correct | 62 // Chain the Future<dynamic> to a Future<T> to produce the correct |
| 62 // final type. | 63 // final type. |
| 63 return result.then($T)((x) => x, {onError: onError}); | 64 return result.then($T)((x) => x, {onError: onError}); |
| 64 } else { | 65 } else { |
| 65 return result; | 66 return result; |
| 66 } | 67 } |
| 67 }); | 68 }); |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 233 } | 234 } |
| 234 '''); | 235 '''); |
| 235 | 236 |
| 236 /// Returns a Stream of T implemented by an async* function. */ | 237 /// Returns a Stream of T implemented by an async* function. */ |
| 237 /// | 238 /// |
| 238 asyncStar(gen, T, @rest args) => JS( | 239 asyncStar(gen, T, @rest args) => JS( |
| 239 '', | 240 '', |
| 240 '''(() => { | 241 '''(() => { |
| 241 return new $_AsyncStarStreamController($gen, $T, $args).controller.stream; | 242 return new $_AsyncStarStreamController($gen, $T, $args).controller.stream; |
| 242 })()'''); | 243 })()'''); |
| OLD | NEW |