OLD | NEW |
---|---|
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:_js_embedded_names' show | 7 import 'dart:_js_embedded_names' show |
8 GET_TYPE_FROM_NAME, | 8 GET_TYPE_FROM_NAME, |
9 GET_ISOLATE_TAG, | 9 GET_ISOLATE_TAG, |
10 INTERCEPTED_NAMES, | 10 INTERCEPTED_NAMES, |
11 INTERCEPTORS_BY_TAG, | 11 INTERCEPTORS_BY_TAG, |
12 LEAF_TAGS, | 12 LEAF_TAGS, |
13 METADATA, | 13 METADATA, |
14 DEFERRED_LIBRARY_URIS, | 14 DEFERRED_LIBRARY_URIS, |
15 DEFERRED_LIBRARY_HASHES, | 15 DEFERRED_LIBRARY_HASHES, |
16 INITIALIZE_LOADED_HUNK, | 16 INITIALIZE_LOADED_HUNK, |
17 IS_HUNK_LOADED, | 17 IS_HUNK_LOADED, |
18 IS_HUNK_INITIALIZED, | 18 IS_HUNK_INITIALIZED, |
19 NATIVE_SUPERCLASS_TAG_NAME; | 19 NATIVE_SUPERCLASS_TAG_NAME; |
20 | 20 |
21 import 'dart:collection'; | 21 import 'dart:collection'; |
22 import 'dart:_isolate_helper' show | 22 import 'dart:_isolate_helper' show |
23 IsolateNatives, | 23 IsolateNatives, |
24 leaveJsAsync, | 24 leaveJsAsync, |
25 enterJsAsync, | 25 enterJsAsync, |
26 isWorker; | 26 isWorker; |
27 | 27 |
28 import 'dart:async' show Future, DeferredLoadException, Completer; | 28 import 'dart:async' |
29 show Future, DeferredLoadException, Completer, StreamController; | |
29 | 30 |
30 import 'dart:_foreign_helper' show | 31 import 'dart:_foreign_helper' show |
31 DART_CLOSURE_TO_JS, | 32 DART_CLOSURE_TO_JS, |
32 JS, | 33 JS, |
33 JS_CALL_IN_ISOLATE, | 34 JS_CALL_IN_ISOLATE, |
34 JS_CONST, | 35 JS_CONST, |
35 JS_CURRENT_ISOLATE, | 36 JS_CURRENT_ISOLATE, |
36 JS_CURRENT_ISOLATE_CONTEXT, | 37 JS_CURRENT_ISOLATE_CONTEXT, |
37 JS_DART_OBJECT_CONSTRUCTOR, | 38 JS_DART_OBJECT_CONSTRUCTOR, |
38 JS_EFFECT, | 39 JS_EFFECT, |
(...skipping 3410 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3449 throw new MainError("No top-level function named 'main'."); | 3450 throw new MainError("No top-level function named 'main'."); |
3450 } | 3451 } |
3451 | 3452 |
3452 void badMain() { | 3453 void badMain() { |
3453 throw new MainError("'main' is not a function."); | 3454 throw new MainError("'main' is not a function."); |
3454 } | 3455 } |
3455 | 3456 |
3456 void mainHasTooManyParameters() { | 3457 void mainHasTooManyParameters() { |
3457 throw new MainError("'main' expects too many parameters."); | 3458 throw new MainError("'main' expects too many parameters."); |
3458 } | 3459 } |
3460 | |
3461 /// Runtime support for async-await transformation. | |
3462 // 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
| |
3463 // If helperCallback or errorCallback throws we complete the completer with | |
3464 // the error. | |
3465 thenHelper(object, | |
floitsch
2015/02/02 22:00:11
Types.
sigurdm
2015/02/03 16:59:32
Done.
| |
3466 helperCallback, | |
3467 Completer completer, | |
3468 errorCallback) { | |
3469 if (helperCallback == null) { | |
3470 completer.complete(object); | |
3471 return; | |
3472 } | |
3473 Future future = object is Future ? object : new Future.value(object); | |
3474 future.then(new WrappedJsFunction(helperCallback, completer), | |
3475 onError: new WrappedJsFunction(errorCallback, completer)); | |
3476 return completer.future; | |
3477 } | |
3478 | |
3479 // Used to avoid creating two identical closure classes in [thenHelper]. | |
3480 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
| |
3481 final function; | |
3482 final Completer completer; | |
3483 | |
3484 WrappedJsFunction(this.function, this.completer); | |
3485 | |
3486 call(result) { | |
3487 try { | |
3488 JS('', '#(#)', function, result); | |
3489 } catch (e, st) { | |
3490 completer.completeError(e, st); | |
3491 } | |
3492 } | |
3493 } | |
3494 | |
3495 // If helperCallback is null we close the stream. | |
3496 // 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.
| |
3497 // If the object is a YIELD_SINGLE we add the object to the stream. | |
3498 streamHelper(object, | |
floitsch
2015/02/02 22:00:12
add real dartdoc.
types.
sigurdm
2015/02/03 16:59:32
Done.
| |
3499 helperCallback, | |
3500 StreamController controller, | |
3501 errorCallback) { | |
3502 print("Called with $controller"); | |
floitsch
2015/02/02 22:00:11
debug line.
sigurdm
2015/02/03 16:59:32
Done.
| |
3503 if (helperCallback == null) { | |
3504 // This happens on return from the async* function. | |
3505 controller.close(); | |
3506 return; | |
3507 } | |
3508 | |
3509 if (object is IterationMarker) { | |
3510 if (object.state == IterationMarker.YIELD_SINGLE) { | |
3511 controller.add(object.value); | |
3512 } else if (object.state == IterationMarker.YIELD_STAR) { | |
3513 // 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.
| |
3514 } | |
3515 if (controller.isPaused) { | |
3516 return; | |
3517 } else if (controller.isCanceled) { | |
3518 // TODO(sigurdm): Handle cancelled streams. | |
3519 } | |
3520 object = null; | |
3521 } | |
3522 | |
3523 Future future = object is Future ? object : new Future.value(object); | |
3524 future.then(new WrappedJsFunctionForStream(helperCallback, controller), | |
3525 onError: errorCallback = null | |
3526 ? null | |
3527 : new WrappedJsFunctionForStream(errorCallback, | |
3528 controller)); | |
3529 return controller.stream; | |
3530 } | |
3531 | |
3532 | |
3533 makeAsyncStarController(helperCallBack) { | |
3534 StreamControllor c; | |
3535 c = new StreamController( | |
3536 onResume: () { | |
3537 // TODO(sigurdm): The errorCallback should not be null. | |
3538 streamHelper(null, helperCallBack, c, null); | |
3539 }); | |
3540 return c; | |
3541 } | |
3542 | |
3543 // 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.
| |
3544 class WrappedJsFunctionForStream { | |
3545 final function; | |
3546 final StreamController controller; | |
3547 | |
3548 WrappedJsFunctionForStream(this.function, this.controller); | |
3549 | |
3550 call(result) { | |
3551 print(controller); | |
floitsch
2015/02/02 22:00:11
debugprint.
sigurdm
2015/02/03 16:59:32
Done.
| |
3552 try { | |
3553 JS('', "#(#)", function, result); | |
3554 } catch (e, st) { | |
3555 controller.addError(e, st); | |
3556 } | |
3557 } | |
3558 } | |
3559 | |
3560 class IterationMarker { | |
3561 static const YIELD_SINGLE = 0; | |
3562 static const YIELD_STAR = 1; | |
3563 static const ITERATION_ENDED = 2; | |
3564 | |
3565 final value; | |
3566 final int state; | |
3567 | |
3568 IterationMarker._(this.state, this.value); | |
3569 | |
3570 static yieldStar(Iterable iterable) { | |
3571 return new IterationMarker._(YIELD_STAR, iterable); | |
3572 } | |
3573 | |
3574 static endOfIteration() { | |
3575 return new IterationMarker._(ITERATION_ENDED, null); | |
3576 } | |
3577 | |
3578 static yieldSingle(value) { | |
3579 return new IterationMarker._(YIELD_SINGLE, value); | |
3580 } | |
3581 | |
3582 toString() => "IterationMarker($state, $value)"; | |
3583 } | |
3584 | |
3585 class SyncStarIterator implements Iterator { | |
3586 final helper; | |
floitsch
2015/02/02 22:00:11
should not be public.
sigurdm
2015/02/03 16:59:32
Done.
| |
3587 | |
3588 var _current = null; | |
3589 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
| |
3590 bool runningNested = false; | |
floitsch
2015/02/02 22:00:12
should not be public.
sigurdm
2015/02/03 16:59:33
Done.
| |
3591 | |
3592 get current => runningNested ? _current.current : _current; | |
3593 | |
3594 SyncStarIterator(helper) | |
3595 : 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.
| |
3596 | |
3597 bool moveNext() { | |
3598 if (!stillRunning) return false; | |
3599 if (runningNested) { | |
3600 if (_current.moveNext()) { | |
3601 return true; | |
3602 } else { | |
3603 runningNested = false; | |
3604 } | |
3605 } | |
3606 _current = helper(null); | |
3607 if (_current is IterationMarker) { | |
3608 if (_current.state == IterationMarker.ITERATION_ENDED) { | |
3609 _current = null; | |
3610 stillRunning = false; | |
3611 } else { | |
3612 assert(_current.state == IterationMarker.YIELD_STAR); | |
3613 _current = _current.value.iterator; | |
3614 runningNested = true; | |
3615 return moveNext(); | |
3616 } | |
3617 } | |
3618 return stillRunning; | |
3619 } | |
3620 } | |
3621 | |
3622 class SyncStarIterable extends IterableBase { | |
3623 final outerHelper; | |
floitsch
2015/02/02 22:00:11
should not be public.
sigurdm
2015/02/03 16:59:33
Done.
| |
3624 | |
3625 SyncStarIterable(this.outerHelper); | |
floitsch
2015/02/02 22:00:12
Document what this is.
sigurdm
2015/02/03 16:59:32
Done.
| |
3626 | |
3627 Iterator get iterator => new SyncStarIterator(JS('', '#()', outerHelper)); | |
3628 } | |
3629 | |
OLD | NEW |