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: sdk/lib/_internal/compiler/js_lib/js_helper.dart

Issue 1163833002: Dart2js async-await. Bind the async-body to the current zone. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 5 years, 6 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 | « pkg/compiler/lib/src/ssa/builder.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 library _js_helper; 5 library _js_helper;
6 6
7 import 'dart:_async_await_error_codes' as async_error_codes; 7 import 'dart:_async_await_error_codes' as async_error_codes;
8 8
9 import 'dart:_js_embedded_names' show 9 import 'dart:_js_embedded_names' show
10 DEFERRED_LIBRARY_URIS, 10 DEFERRED_LIBRARY_URIS,
(...skipping 18 matching lines...) Expand all
29 isWorker, 29 isWorker,
30 leaveJsAsync; 30 leaveJsAsync;
31 31
32 import 'dart:async' show 32 import 'dart:async' show
33 Completer, 33 Completer,
34 DeferredLoadException, 34 DeferredLoadException,
35 Future, 35 Future,
36 StreamController, 36 StreamController,
37 Stream, 37 Stream,
38 StreamSubscription, 38 StreamSubscription,
39 scheduleMicrotask; 39 scheduleMicrotask,
40 Zone;
40 41
41 import 'dart:_foreign_helper' show 42 import 'dart:_foreign_helper' show
42 DART_CLOSURE_TO_JS, 43 DART_CLOSURE_TO_JS,
43 JS, 44 JS,
44 JS_BUILTIN, 45 JS_BUILTIN,
45 JS_CALL_IN_ISOLATE, 46 JS_CALL_IN_ISOLATE,
46 JS_CONST, 47 JS_CONST,
47 JS_CURRENT_ISOLATE, 48 JS_CURRENT_ISOLATE,
48 JS_CURRENT_ISOLATE_CONTEXT, 49 JS_CURRENT_ISOLATE_CONTEXT,
49 JS_EFFECT, 50 JS_EFFECT,
(...skipping 3683 matching lines...) Expand 10 before | Expand all | Expand 10 after
3733 /// If [asyncBody] is [async_error_codes.SUCCESS]/[async_error_codes.ERROR] it 3734 /// If [asyncBody] is [async_error_codes.SUCCESS]/[async_error_codes.ERROR] it
3734 /// indicates a return or throw from the async function, and 3735 /// indicates a return or throw from the async function, and
3735 /// complete/completeError is called on [completer] with [object]. 3736 /// complete/completeError is called on [completer] with [object].
3736 /// 3737 ///
3737 /// Otherwise [asyncBody] is set up to be called when the future is completed 3738 /// Otherwise [asyncBody] is set up to be called when the future is completed
3738 /// with a code [async_error_codes.SUCCESS]/[async_error_codes.ERROR] depending 3739 /// with a code [async_error_codes.SUCCESS]/[async_error_codes.ERROR] depending
3739 /// on the success of the future. 3740 /// on the success of the future.
3740 /// 3741 ///
3741 /// Returns the future of the completer for convenience of the first call. 3742 /// Returns the future of the completer for convenience of the first call.
3742 dynamic asyncHelper(dynamic object, 3743 dynamic asyncHelper(dynamic object,
3743 dynamic /* js function */ bodyFunctionOrErrorCode, 3744 dynamic /* int | WrappedAsyncBody */ bodyFunctionOrErrorCode,
3744 Completer completer) { 3745 Completer completer) {
3745 if (identical(bodyFunctionOrErrorCode, async_error_codes.SUCCESS)) { 3746 if (identical(bodyFunctionOrErrorCode, async_error_codes.SUCCESS)) {
3746 completer.complete(object); 3747 completer.complete(object);
3747 return; 3748 return;
3748 } else if (identical(bodyFunctionOrErrorCode, async_error_codes.ERROR)) { 3749 } else if (identical(bodyFunctionOrErrorCode, async_error_codes.ERROR)) {
3749 // The error is a js-error. 3750 // The error is a js-error.
3750 completer.completeError(unwrapException(object), 3751 completer.completeError(unwrapException(object),
3751 getTraceFromException(object)); 3752 getTraceFromException(object));
3752 return; 3753 return;
3753 } 3754 }
3754 Future future = object is Future ? object : new Future.value(object); 3755 Future future = object is Future ? object : new Future.value(object);
3755 future.then(_wrapJsFunctionForAsync(bodyFunctionOrErrorCode, 3756 future.then(
3756 async_error_codes.SUCCESS), 3757 (result) => bodyFunctionOrErrorCode(async_error_codes.SUCCESS, result),
3757 onError: (dynamic error, StackTrace stackTrace) { 3758 onError: (dynamic error, StackTrace stackTrace) {
3758 ExceptionAndStackTrace wrappedException = 3759 ExceptionAndStackTrace wrappedException =
3759 new ExceptionAndStackTrace(error, stackTrace); 3760 new ExceptionAndStackTrace(error, stackTrace);
3760 Function wrapped =_wrapJsFunctionForAsync(bodyFunctionOrErrorCode, 3761 bodyFunctionOrErrorCode(async_error_codes.ERROR, wrappedException);
3761 async_error_codes.ERROR);
3762 wrapped(wrappedException);
3763 }); 3762 });
3764 return completer.future; 3763 return completer.future;
3765 } 3764 }
3766 3765
3767 Function _wrapJsFunctionForAsync(dynamic /* js function */ function, 3766 typedef void WrappedAsyncBody(int errorCode, dynamic result);
3768 int errorCode) { 3767
3768 WrappedAsyncBody _wrapJsFunctionForAsync(dynamic /* js function */ function) {
3769 var protected = JS('', """ 3769 var protected = JS('', """
3770 // Invokes [function] with [errorCode] and [result]. 3770 // Invokes [function] with [errorCode] and [result].
3771 // 3771 //
3772 // If (and as long as) the invocation throws, calls [function] again, 3772 // If (and as long as) the invocation throws, calls [function] again,
3773 // with an error-code. 3773 // with an error-code.
3774 function(errorCode, result) { 3774 function(errorCode, result) {
3775 while (true) { 3775 while (true) {
3776 try { 3776 try {
3777 #(errorCode, result); 3777 #(errorCode, result);
3778 break; 3778 break;
3779 } catch (error) { 3779 } catch (error) {
3780 result = error; 3780 result = error;
3781 errorCode = #; 3781 errorCode = #;
3782 } 3782 }
3783 } 3783 }
3784 }""", function, async_error_codes.ERROR); 3784 }""", function, async_error_codes.ERROR);
3785 return (result) { 3785 return Zone.current.bindBinaryCallback((int errorCode, dynamic result) {
3786 JS('', '#(#, #)', protected, errorCode, result); 3786 JS('', '#(#, #)', protected, errorCode, result);
3787 }; 3787 });
3788 } 3788 }
3789 3789
3790 /// Implements the runtime support for async* functions. 3790 /// Implements the runtime support for async* functions.
3791 /// 3791 ///
3792 /// Called by the transformed function for each original return, await, yield, 3792 /// Called by the transformed function for each original return, await, yield,
3793 /// yield* and before starting the function. 3793 /// yield* and before starting the function.
3794 /// 3794 ///
3795 /// When the async* function wants to return it calls this function with 3795 /// When the async* function wants to return it calls this function with
3796 /// [asyncBody] == [async_error_codes.SUCCESS], the asyncStarHelper takes this 3796 /// [asyncBody] == [async_error_codes.SUCCESS], the asyncStarHelper takes this
3797 /// as signal to close the stream. 3797 /// as signal to close the stream.
(...skipping 19 matching lines...) Expand all
3817 /// yielded stream, and adds all events and errors to our own controller (taking 3817 /// yielded stream, and adds all events and errors to our own controller (taking
3818 /// care if the subscription has been paused or canceled) - when the sub-stream 3818 /// care if the subscription has been paused or canceled) - when the sub-stream
3819 /// is done, schedules [asyncBody] again. 3819 /// is done, schedules [asyncBody] again.
3820 /// 3820 ///
3821 /// If the async* function wants to do an await it calls this function with 3821 /// If the async* function wants to do an await it calls this function with
3822 /// [object] not and [IterationMarker]. 3822 /// [object] not and [IterationMarker].
3823 /// 3823 ///
3824 /// If [object] is not a [Future], it is wrapped in a `Future.value`. 3824 /// If [object] is not a [Future], it is wrapped in a `Future.value`.
3825 /// The [asyncBody] is called on completion of the future (see [asyncHelper]. 3825 /// The [asyncBody] is called on completion of the future (see [asyncHelper].
3826 void asyncStarHelper(dynamic object, 3826 void asyncStarHelper(dynamic object,
3827 dynamic /* int | js function */ bodyFunctionOrErrorCode, 3827 dynamic /* int | WrappedAsyncBody */ bodyFunctionOrErrorCode,
3828 AsyncStarStreamController controller) { 3828 AsyncStarStreamController controller) {
3829 if (identical(bodyFunctionOrErrorCode, async_error_codes.SUCCESS)) { 3829 if (identical(bodyFunctionOrErrorCode, async_error_codes.SUCCESS)) {
3830 // This happens on return from the async* function. 3830 // This happens on return from the async* function.
3831 if (controller.isCanceled) { 3831 if (controller.isCanceled) {
3832 controller.cancelationCompleter.complete(); 3832 controller.cancelationCompleter.complete();
3833 } else { 3833 } else {
3834 controller.close(); 3834 controller.close();
3835 } 3835 }
3836 return; 3836 return;
3837 } else if (identical(bodyFunctionOrErrorCode, async_error_codes.ERROR)) { 3837 } else if (identical(bodyFunctionOrErrorCode, async_error_codes.ERROR)) {
3838 // The error is a js-error. 3838 // The error is a js-error.
3839 if (controller.isCanceled) { 3839 if (controller.isCanceled) {
3840 controller.cancelationCompleter.completeError( 3840 controller.cancelationCompleter.completeError(
3841 unwrapException(object), 3841 unwrapException(object),
3842 getTraceFromException(object)); 3842 getTraceFromException(object));
3843 } else { 3843 } else {
3844 controller.addError(unwrapException(object), 3844 controller.addError(unwrapException(object),
3845 getTraceFromException(object)); 3845 getTraceFromException(object));
3846 controller.close(); 3846 controller.close();
3847 } 3847 }
3848 return; 3848 return;
3849 } 3849 }
3850 3850
3851 if (object is IterationMarker) { 3851 if (object is IterationMarker) {
3852 if (controller.isCanceled) { 3852 if (controller.isCanceled) {
3853 Function wrapped = _wrapJsFunctionForAsync(bodyFunctionOrErrorCode, 3853 bodyFunctionOrErrorCode(async_error_codes.STREAM_WAS_CANCELED, null);
3854 async_error_codes.STREAM_WAS_CANCELED);
3855 wrapped(null);
3856 return; 3854 return;
3857 } 3855 }
3858 if (object.state == IterationMarker.YIELD_SINGLE) { 3856 if (object.state == IterationMarker.YIELD_SINGLE) {
3859 controller.add(object.value); 3857 controller.add(object.value);
3860 3858
3861 scheduleMicrotask(() { 3859 scheduleMicrotask(() {
3862 if (controller.isPaused) { 3860 if (controller.isPaused) {
3863 // We only suspend the thread inside the microtask in order to allow 3861 // We only suspend the thread inside the microtask in order to allow
3864 // listeners on the output stream to pause in response to the just 3862 // listeners on the output stream to pause in response to the just
3865 // output value, and have the stream immediately stop producing. 3863 // output value, and have the stream immediately stop producing.
3866 controller.isSuspended = true; 3864 controller.isSuspended = true;
3867 return; 3865 return;
3868 } 3866 }
3869 Function wrapped = _wrapJsFunctionForAsync(bodyFunctionOrErrorCode, 3867 bodyFunctionOrErrorCode(null, async_error_codes.SUCCESS);
3870 async_error_codes.SUCCESS);
3871 wrapped(null);
3872 }); 3868 });
3873 return; 3869 return;
3874 } else if (object.state == IterationMarker.YIELD_STAR) { 3870 } else if (object.state == IterationMarker.YIELD_STAR) {
3875 Stream stream = object.value; 3871 Stream stream = object.value;
3876 // Errors of [stream] are passed though to the main stream. (see 3872 // Errors of [stream] are passed though to the main stream. (see
3877 // [AsyncStreamController.addStream]). 3873 // [AsyncStreamController.addStream]).
3878 // TODO(sigurdm): The spec is not very clear here. Clarify with Gilad. 3874 // TODO(sigurdm): The spec is not very clear here. Clarify with Gilad.
3879 controller.addStream(stream).then((_) { 3875 controller.addStream(stream).then((_) {
3880 // No check for isPaused here because the spec 17.16.2 only 3876 // No check for isPaused here because the spec 17.16.2 only
3881 // demands checks *before* each element in [stream] not after the last 3877 // demands checks *before* each element in [stream] not after the last
3882 // one. On the other hand we check for isCanceled, as that check happens 3878 // one. On the other hand we check for isCanceled, as that check happens
3883 // after insertion of each element. 3879 // after insertion of each element.
3884 int errorCode = controller.isCanceled 3880 int errorCode = controller.isCanceled
3885 ? async_error_codes.STREAM_WAS_CANCELED 3881 ? async_error_codes.STREAM_WAS_CANCELED
3886 : async_error_codes.SUCCESS; 3882 : async_error_codes.SUCCESS;
3887 Function wrapped = _wrapJsFunctionForAsync(bodyFunctionOrErrorCode, 3883 bodyFunctionOrErrorCode(errorCode, null);
3888 errorCode);
3889 wrapped(null);
3890 }); 3884 });
3891 return; 3885 return;
3892 } 3886 }
3893 } 3887 }
3894 3888
3895 Future future = object is Future ? object : new Future.value(object); 3889 Future future = object is Future ? object : new Future.value(object);
3896 future.then(_wrapJsFunctionForAsync(bodyFunctionOrErrorCode, 3890 future.then(
3897 async_error_codes.SUCCESS), 3891 (result) => bodyFunctionOrErrorCode(async_error_codes.SUCCESS, result),
3898 onError: (error, StackTrace stackTrace) { 3892 onError: (error, StackTrace stackTrace) {
3899 ExceptionAndStackTrace wrappedException = 3893 ExceptionAndStackTrace wrappedException =
3900 new ExceptionAndStackTrace(error, stackTrace); 3894 new ExceptionAndStackTrace(error, stackTrace);
3901 Function wrapped = _wrapJsFunctionForAsync( 3895 bodyFunctionOrErrorCode(async_error_codes.ERROR, wrappedException);
3902 bodyFunctionOrErrorCode, async_error_codes.ERROR); 3896 });
3903 return wrapped(wrappedException);
3904 });
3905 } 3897 }
3906 3898
3907 Stream streamOfController(AsyncStarStreamController controller) { 3899 Stream streamOfController(AsyncStarStreamController controller) {
3908 return controller.stream; 3900 return controller.stream;
3909 } 3901 }
3910 3902
3911 /// A wrapper around a [StreamController] that keeps track of the state of 3903 /// A wrapper around a [StreamController] that keeps track of the state of
3912 /// the execution of an async* function. 3904 /// the execution of an async* function.
3913 /// It can be in 1 of 3 states: 3905 /// It can be in 1 of 3 states:
3914 /// 3906 ///
(...skipping 25 matching lines...) Expand all
3940 add(event) => controller.add(event); 3932 add(event) => controller.add(event);
3941 3933
3942 addStream(Stream stream) { 3934 addStream(Stream stream) {
3943 return controller.addStream(stream, cancelOnError: false); 3935 return controller.addStream(stream, cancelOnError: false);
3944 } 3936 }
3945 3937
3946 addError(error, stackTrace) => controller.addError(error, stackTrace); 3938 addError(error, stackTrace) => controller.addError(error, stackTrace);
3947 3939
3948 close() => controller.close(); 3940 close() => controller.close();
3949 3941
3950 AsyncStarStreamController(body) { 3942 AsyncStarStreamController(WrappedAsyncBody body) {
3951 3943
3952 _resumeBody() { 3944 _resumeBody() {
3953 scheduleMicrotask(() { 3945 scheduleMicrotask(() {
3954 Function wrapped = 3946 body(async_error_codes.SUCCESS, null);
3955 _wrapJsFunctionForAsync(body, async_error_codes.SUCCESS);
3956 wrapped(null);
3957 }); 3947 });
3958 } 3948 }
3959 3949
3960 controller = new StreamController( 3950 controller = new StreamController(
3961 onListen: () { 3951 onListen: () {
3962 _resumeBody(); 3952 _resumeBody();
3963 }, onResume: () { 3953 }, onResume: () {
3964 // Only schedule again if the async* function actually is suspended. 3954 // Only schedule again if the async* function actually is suspended.
3965 // Resume directly instead of scheduling, so that the sequence 3955 // Resume directly instead of scheduling, so that the sequence
3966 // `pause-resume-pause` will result in one extra event produced. 3956 // `pause-resume-pause` will result in one extra event produced.
3967 if (isSuspended) { 3957 if (isSuspended) {
3968 isSuspended = false; 3958 isSuspended = false;
3969 _resumeBody(); 3959 _resumeBody();
3970 } 3960 }
3971 }, onCancel: () { 3961 }, onCancel: () {
3972 // If the async* is finished we ignore cancel events. 3962 // If the async* is finished we ignore cancel events.
3973 if (!controller.isClosed) { 3963 if (!controller.isClosed) {
3974 cancelationCompleter = new Completer(); 3964 cancelationCompleter = new Completer();
3975 if (isSuspended) { 3965 if (isSuspended) {
3976 // Resume the suspended async* function to run finalizers. 3966 // Resume the suspended async* function to run finalizers.
3977 isSuspended = false; 3967 isSuspended = false;
3978 scheduleMicrotask(() { 3968 scheduleMicrotask(() {
3979 Function wrapped =_wrapJsFunctionForAsync(body, 3969 body(async_error_codes.STREAM_WAS_CANCELED, null);
3980 async_error_codes.STREAM_WAS_CANCELED);
3981 wrapped(null);
3982 }); 3970 });
3983 } 3971 }
3984 return cancelationCompleter.future; 3972 return cancelationCompleter.future;
3985 } 3973 }
3986 }); 3974 });
3987 } 3975 }
3988 } 3976 }
3989 3977
3990 makeAsyncStarController(body) { 3978 makeAsyncStarController(body) {
3991 return new AsyncStarStreamController(body); 3979 return new AsyncStarStreamController(body);
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
4089 // This is a function that will return a helper function that does the 4077 // This is a function that will return a helper function that does the
4090 // iteration of the sync*. 4078 // iteration of the sync*.
4091 // 4079 //
4092 // Each invocation should give a body with fresh state. 4080 // Each invocation should give a body with fresh state.
4093 final dynamic /* js function */ _outerHelper; 4081 final dynamic /* js function */ _outerHelper;
4094 4082
4095 SyncStarIterable(this._outerHelper); 4083 SyncStarIterable(this._outerHelper);
4096 4084
4097 Iterator get iterator => new SyncStarIterator(JS('', '#()', _outerHelper)); 4085 Iterator get iterator => new SyncStarIterator(JS('', '#()', _outerHelper));
4098 } 4086 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/ssa/builder.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698