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

Unified Diff: sdk/lib/_internal/compiler/js_lib/js_helper.dart

Issue 839323003: Implementation of async-await transformation on js ast. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Implement new ssa-nodes in ssa-tracer. Created 5 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 side-by-side diff with in-line comments
Download patch
Index: sdk/lib/_internal/compiler/js_lib/js_helper.dart
diff --git a/sdk/lib/_internal/compiler/js_lib/js_helper.dart b/sdk/lib/_internal/compiler/js_lib/js_helper.dart
index 97b1a9d9ef1a2dcf9162f8dd4af58573679c137d..38e94d539a22b0ead30c11d9969c0ff605bcd6a9 100644
--- a/sdk/lib/_internal/compiler/js_lib/js_helper.dart
+++ b/sdk/lib/_internal/compiler/js_lib/js_helper.dart
@@ -25,7 +25,8 @@ import 'dart:_isolate_helper' show
enterJsAsync,
isWorker;
-import 'dart:async' show Future, DeferredLoadException, Completer;
+import 'dart:async'
+ show Future, DeferredLoadException, Completer, StreamController;
import 'dart:_foreign_helper' show
DART_CLOSURE_TO_JS,
@@ -3456,3 +3457,173 @@ void badMain() {
void mainHasTooManyParameters() {
throw new MainError("'main' expects too many parameters.");
}
+
+/// Runtime support for async-await transformation.
+// If helperCallback is null we complete the completer with object.
floitsch 2015/02/02 22:00:12 Explain more. Is errorCallback necessary?...
sigurdm 2015/02/03 16:59:32 The error callback will redirect the control flow
floitsch 2015/02/04 12:31:27 Yes. I was talking about another implementation. F
+// If helperCallback or errorCallback throws we complete the completer with
+// the error.
+thenHelper(object,
floitsch 2015/02/02 22:00:11 Types.
sigurdm 2015/02/03 16:59:32 Done.
+ helperCallback,
+ Completer completer,
+ errorCallback) {
+ if (helperCallback == null) {
+ completer.complete(object);
+ return;
+ }
+ Future future = object is Future ? object : new Future.value(object);
+ future.then(new WrappedJsFunction(helperCallback, completer),
+ onError: new WrappedJsFunction(errorCallback, completer));
+ return completer.future;
+}
+
+// Used to avoid creating two identical closure classes in [thenHelper].
+class WrappedJsFunction {
floitsch 2015/02/02 22:00:11 I don't understand this. Why not: Function _wrapJ
sigurdm 2015/02/03 16:59:32 That is better, thanks
+ final function;
+ final Completer completer;
+
+ WrappedJsFunction(this.function, this.completer);
+
+ call(result) {
+ try {
+ JS('', '#(#)', function, result);
+ } catch (e, st) {
+ completer.completeError(e, st);
+ }
+ }
+}
+
+// If helperCallback is null we close the stream.
+// If helperCallback or errorCallback throws we add the error to the stream
floitsch 2015/02/02 22:00:11 Add more documentation what exactly is expected an
sigurdm 2015/02/03 16:59:32 Done.
+// If the object is a YIELD_SINGLE we add the object to the stream.
+streamHelper(object,
floitsch 2015/02/02 22:00:12 add real dartdoc. types.
sigurdm 2015/02/03 16:59:32 Done.
+ helperCallback,
+ StreamController controller,
+ errorCallback) {
+ print("Called with $controller");
floitsch 2015/02/02 22:00:11 debug line.
sigurdm 2015/02/03 16:59:32 Done.
+ if (helperCallback == null) {
+ // This happens on return from the async* function.
+ controller.close();
+ return;
+ }
+
+ if (object is IterationMarker) {
+ if (object.state == IterationMarker.YIELD_SINGLE) {
+ controller.add(object.value);
+ } else if (object.state == IterationMarker.YIELD_STAR) {
+ // TODO(sigurdm): Handle yield star from async*.
floitsch 2015/02/02 22:00:11 Don't silently ignore the value.
sigurdm 2015/02/03 16:59:32 Done.
+ }
+ if (controller.isPaused) {
+ return;
+ } else if (controller.isCanceled) {
+ // TODO(sigurdm): Handle cancelled streams.
+ }
+ object = null;
+ }
+
+ Future future = object is Future ? object : new Future.value(object);
+ future.then(new WrappedJsFunctionForStream(helperCallback, controller),
+ onError: errorCallback = null
+ ? null
+ : new WrappedJsFunctionForStream(errorCallback,
+ controller));
+ return controller.stream;
+}
+
+
+makeAsyncStarController(helperCallBack) {
+ StreamControllor c;
+ c = new StreamController(
+ onResume: () {
+ // TODO(sigurdm): The errorCallback should not be null.
+ streamHelper(null, helperCallBack, c, null);
+ });
+ return c;
+}
+
+// Used to avoid creating two identical closure classes in [streamHelper].
floitsch 2015/02/02 22:00:12 Ditto: I don't like "call" classes. Never sure if
sigurdm 2015/02/03 16:59:32 Done.
+class WrappedJsFunctionForStream {
+ final function;
+ final StreamController controller;
+
+ WrappedJsFunctionForStream(this.function, this.controller);
+
+ call(result) {
+ print(controller);
floitsch 2015/02/02 22:00:11 debugprint.
sigurdm 2015/02/03 16:59:32 Done.
+ try {
+ JS('', "#(#)", function, result);
+ } catch (e, st) {
+ controller.addError(e, st);
+ }
+ }
+}
+
+class IterationMarker {
+ static const YIELD_SINGLE = 0;
+ static const YIELD_STAR = 1;
+ static const ITERATION_ENDED = 2;
+
+ final value;
+ final int state;
+
+ IterationMarker._(this.state, this.value);
+
+ static yieldStar(Iterable iterable) {
+ return new IterationMarker._(YIELD_STAR, iterable);
+ }
+
+ static endOfIteration() {
+ return new IterationMarker._(ITERATION_ENDED, null);
+ }
+
+ static yieldSingle(value) {
+ return new IterationMarker._(YIELD_SINGLE, value);
+ }
+
+ toString() => "IterationMarker($state, $value)";
+}
+
+class SyncStarIterator implements Iterator {
+ final helper;
floitsch 2015/02/02 22:00:11 should not be public.
sigurdm 2015/02/03 16:59:32 Done.
+
+ var _current = null;
+ bool stillRunning = true;
floitsch 2015/02/02 22:00:11 Should not be public.
floitsch 2015/02/02 22:00:12 I don't think we use "stillRunning" in other itera
sigurdm 2015/02/03 16:59:32 Done.
sigurdm 2015/02/03 16:59:32 None of the other Iterators I could find maintains
+ bool runningNested = false;
floitsch 2015/02/02 22:00:12 should not be public.
sigurdm 2015/02/03 16:59:33 Done.
+
+ get current => runningNested ? _current.current : _current;
+
+ SyncStarIterator(helper)
+ : helper = ((arg) => JS('', '#(#)', helper, arg));
floitsch 2015/02/02 22:00:11 don't call them the same. Call the argument jsHel
sigurdm 2015/02/03 16:59:33 Done.
+
+ bool moveNext() {
+ if (!stillRunning) return false;
+ if (runningNested) {
+ if (_current.moveNext()) {
+ return true;
+ } else {
+ runningNested = false;
+ }
+ }
+ _current = helper(null);
+ if (_current is IterationMarker) {
+ if (_current.state == IterationMarker.ITERATION_ENDED) {
+ _current = null;
+ stillRunning = false;
+ } else {
+ assert(_current.state == IterationMarker.YIELD_STAR);
+ _current = _current.value.iterator;
+ runningNested = true;
+ return moveNext();
+ }
+ }
+ return stillRunning;
+ }
+}
+
+class SyncStarIterable extends IterableBase {
+ final outerHelper;
floitsch 2015/02/02 22:00:11 should not be public.
sigurdm 2015/02/03 16:59:33 Done.
+
+ SyncStarIterable(this.outerHelper);
floitsch 2015/02/02 22:00:12 Document what this is.
sigurdm 2015/02/03 16:59:32 Done.
+
+ Iterator get iterator => new SyncStarIterator(JS('', '#()', outerHelper));
+}
+

Powered by Google App Engine
This is Rietveld 408576698