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

Side by Side Diff: third_party/pkg/angular/lib/core/scope.dart

Issue 148453003: Updating Angular version (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 10 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 | Annotate | Revision Log
OLDNEW
1 part of angular.core; 1 part of angular.core;
2 2
3 3
4 /** 4 /**
5 * Used by [Scope.$on] to notify the listeners of events. 5 * Injected into the listener function within [Scope.$on] to provide event-speci fic
6 * details to the scope listener.
6 */ 7 */
7 class ScopeEvent { 8 class ScopeEvent {
9
10 /**
11 * The name of the intercepted scope event.
12 */
8 String name; 13 String name;
14
15 /**
16 * The origin scope that triggered the event (via $broadcast or $emit).
17 */
9 Scope targetScope; 18 Scope targetScope;
19
20 /**
21 * The destination scope that intercepted the event.
22 */
10 Scope currentScope; 23 Scope currentScope;
24
25 /**
26 * true or false depending on if stopPropagation() was executed.
27 */
11 bool propagationStopped = false; 28 bool propagationStopped = false;
29
30 /**
31 * true or false depending on if preventDefault() was executed.
32 */
12 bool defaultPrevented = false; 33 bool defaultPrevented = false;
13 34
35 /**
36 ** [name] - The name of the scope event.
37 ** [targetScope] - The destination scope that is listening on the event.
38 */
14 ScopeEvent(this.name, this.targetScope); 39 ScopeEvent(this.name, this.targetScope);
15 40
41 /**
42 * Prevents the intercepted event from propagating further to successive scope s.
43 */
16 stopPropagation () => propagationStopped = true; 44 stopPropagation () => propagationStopped = true;
45
46 /**
47 * Sets the defaultPrevented flag to true.
48 */
17 preventDefault() => defaultPrevented = true; 49 preventDefault() => defaultPrevented = true;
18 } 50 }
19 51
20 /** 52 /**
21 * Allows the configuration of [Scope.$digest] iteration maximum time-to-live 53 * Allows the configuration of [Scope.$digest] iteration maximum time-to-live
22 * value. Digest keeps checking the state of the watcher getters until it 54 * value. Digest keeps checking the state of the watcher getters until it
23 * can execute one full iteration with no watchers triggering. TTL is used 55 * can execute one full iteration with no watchers triggering. TTL is used
24 * to prevent an infinite loop where watch A triggers watch B which in turn 56 * to prevent an infinite loop where watch A triggers watch B which in turn
25 * triggers watch A. If the system does not stabilize in TTL iteration then 57 * triggers watch A. If the system does not stabilize in TTL iteration then
26 * an digest is stop an an exception is thrown. 58 * an digest is stop an an exception is thrown.
(...skipping 16 matching lines...) Expand all
43 final ExceptionHandler _exceptionHandler; 75 final ExceptionHandler _exceptionHandler;
44 final Parser _parser; 76 final Parser _parser;
45 final NgZone _zone; 77 final NgZone _zone;
46 final num _ttl; 78 final num _ttl;
47 final Map<String, Object> _properties = {}; 79 final Map<String, Object> _properties = {};
48 final _WatchList _watchers = new _WatchList(); 80 final _WatchList _watchers = new _WatchList();
49 final Map<String, List<Function>> _listeners = {}; 81 final Map<String, List<Function>> _listeners = {};
50 final bool _isolate; 82 final bool _isolate;
51 final bool _lazy; 83 final bool _lazy;
52 final Profiler _perf; 84 final Profiler _perf;
85
86 /**
87 * The direct parent scope that created this scope (this can also be the $root Scope)
88 */
53 final Scope $parent; 89 final Scope $parent;
54 90
91 /**
92 * The auto-incremented ID of the scope
93 */
55 String $id; 94 String $id;
95
96 /**
97 * The topmost scope of the application (same as $rootScope).
98 */
56 Scope $root; 99 Scope $root;
57 num _nextId = 0; 100 num _nextId = 0;
58 String _phase; 101 String _phase;
59 List _innerAsyncQueue; 102 List _innerAsyncQueue;
60 List _outerAsyncQueue; 103 List _outerAsyncQueue;
61 Scope _nextSibling, _prevSibling, _childHead, _childTail; 104 Scope _nextSibling, _prevSibling, _childHead, _childTail;
62 bool _skipAutoDigest = false; 105 bool _skipAutoDigest = false;
63 bool _disabled = false; 106 bool _disabled = false;
64 107
108 _set$Properties() {
109 _properties[r'this'] = this;
110 _properties[r'$id'] = this.$id;
111 _properties[r'$parent'] = this.$parent;
112 _properties[r'$root'] = this.$root;
113 }
114
65 Scope(this._exceptionHandler, this._parser, ScopeDigestTTL ttl, 115 Scope(this._exceptionHandler, this._parser, ScopeDigestTTL ttl,
66 this._zone, this._perf): 116 this._zone, this._perf):
67 $parent = null, _isolate = false, _lazy = false, _ttl = ttl.ttl { 117 $parent = null, _isolate = false, _lazy = false, _ttl = ttl.ttl {
68 _properties[r'this']= this;
69 $root = this; 118 $root = this;
70 $id = '_${$root._nextId++}'; 119 $id = '_${$root._nextId++}';
71 _innerAsyncQueue = []; 120 _innerAsyncQueue = [];
72 _outerAsyncQueue = []; 121 _outerAsyncQueue = [];
73 122
74 // Set up the zone to auto digest this scope. 123 // Set up the zone to auto digest this scope.
75 _zone.onTurnDone = _autoDigestOnTurnDone; 124 _zone.onTurnDone = _autoDigestOnTurnDone;
76 _zone.onError = (e, s, ls) => _exceptionHandler(e, s); 125 _zone.onError = (e, s, ls) => _exceptionHandler(e, s);
126 _set$Properties();
77 } 127 }
78 128
79 Scope._child(Scope parent, bool this._isolate, bool this._lazy, Profiler this. _perf): 129 Scope._child(Scope parent, bool this._isolate, bool this._lazy, Profiler this. _perf):
80 $parent = parent, _ttl = parent._ttl, _parser = parent._parser, 130 $parent = parent, _ttl = parent._ttl, _parser = parent._parser,
81 _exceptionHandler = parent._exceptionHandler, _zone = parent._zone { 131 _exceptionHandler = parent._exceptionHandler, _zone = parent._zone {
82 _properties[r'this'] = this;
83 $root = $parent.$root; 132 $root = $parent.$root;
84 $id = '_${$root._nextId++}'; 133 $id = '_${$root._nextId++}';
85 _innerAsyncQueue = $parent._innerAsyncQueue; 134 _innerAsyncQueue = $parent._innerAsyncQueue;
86 _outerAsyncQueue = $parent._outerAsyncQueue; 135 _outerAsyncQueue = $parent._outerAsyncQueue;
87 136
88 _prevSibling = $parent._childTail; 137 _prevSibling = $parent._childTail;
89 if ($parent._childHead != null) { 138 if ($parent._childHead != null) {
90 $parent._childTail._nextSibling = this; 139 $parent._childTail._nextSibling = this;
91 $parent._childTail = this; 140 $parent._childTail = this;
92 } else { 141 } else {
93 $parent._childHead = $parent._childTail = this; 142 $parent._childHead = $parent._childTail = this;
94 } 143 }
144 _set$Properties();
95 } 145 }
96 146
97 _autoDigestOnTurnDone() { 147 _autoDigestOnTurnDone() {
98 if (_skipAutoDigest) { 148 if ($root._skipAutoDigest) {
99 _skipAutoDigest = false; 149 $root._skipAutoDigest = false;
100 } else { 150 } else {
101 $digest(); 151 $digest();
102 } 152 }
103 } 153 }
104 154
105 _identical(a, b) => 155 _identical(a, b) =>
106 identical(a, b) || 156 identical(a, b) ||
107 (a is String && b is String && a == b) || 157 (a is String && b is String && a == b) ||
108 (a is num && b is num && a.isNaN && b.isNaN); 158 (a is num && b is num && a.isNaN && b.isNaN);
109 159
110 containsKey(String name) => this[name] != null; 160 containsKey(String name) {
161 for (var scope = this; scope != null; scope = scope.$parent) {
162 if (scope._properties.containsKey(name)) {
163 return true;
164 } else if(scope._isolate) {
165 break;
166 }
167 }
168 return false;
169 }
170
111 remove(String name) => this._properties.remove(name); 171 remove(String name) => this._properties.remove(name);
112 operator []=(String name, value) => _properties[name] = value; 172 operator []=(String name, value) => _properties[name] = value;
113 operator [](String name) { 173 operator [](String name) {
114 if (name == r'$id') return this.$id; 174 for (var scope = this; scope != null; scope = scope.$parent) {
115 if (name == r'$parent') return this.$parent;
116 if (name == r'$root') return this.$root;
117 var scope = this;
118 do {
119 if (scope._properties.containsKey(name)) { 175 if (scope._properties.containsKey(name)) {
120 return scope._properties[name]; 176 return scope._properties[name];
121 } else if (!scope._isolate) { 177 } else if(scope._isolate) {
122 scope = scope.$parent; 178 break;
123 } else {
124 return null;
125 } 179 }
126 } while(scope != null); 180 }
127 return null; 181 return null;
128 } 182 }
129 183
130 noSuchMethod(Invocation invocation) { 184 noSuchMethod(Invocation invocation) {
131 var name = MirrorSystem.getName(invocation.memberName); 185 var name = MirrorSystem.getName(invocation.memberName);
132 if (invocation.isGetter) { 186 if (invocation.isGetter) {
133 return this[name]; 187 return this[name];
134 } else if (invocation.isSetter) { 188 } else if (invocation.isSetter) {
135 var value = invocation.positionalArguments[0]; 189 var value = invocation.positionalArguments[0];
136 name = name.substring(0, name.length - 1); 190 name = name.substring(0, name.length - 1);
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after
375 } 429 }
376 430
377 431
378 /** 432 /**
379 * Add this function to your code if you want to add a $digest 433 * Add this function to your code if you want to add a $digest
380 * and want to assert that the digest will be called on this turn. 434 * and want to assert that the digest will be called on this turn.
381 * This method will be deleted when we are comfortable with 435 * This method will be deleted when we are comfortable with
382 * auto-digesting scope. 436 * auto-digesting scope.
383 */ 437 */
384 $$verifyDigestWillRun() { 438 $$verifyDigestWillRun() {
385 assert(!_skipAutoDigest); 439 assert(!$root._skipAutoDigest);
386 _zone.assertInTurn(); 440 _zone.assertInTurn();
387 } 441 }
388 442
389 /** 443 /**
390 * *EXPERIMENTAL:* This feature is experimental. We reserve the right to chang e or delete it. 444 * *EXPERIMENTAL:* This feature is experimental. We reserve the right to chang e or delete it.
391 * 445 *
392 * Marks a scope as dirty. If the scope is lazy (see [$new]) then the scope wi ll be included 446 * Marks a scope as dirty. If the scope is lazy (see [$new]) then the scope wi ll be included
393 * in the next [$digest]. 447 * in the next [$digest].
394 * 448 *
395 * NOTE: This has no effect for non-lazy scopes. 449 * NOTE: This has no effect for non-lazy scopes.
396 */ 450 */
397 $dirty() { 451 $dirty() {
398 this._disabled = false; 452 this._disabled = false;
399 } 453 }
400 454
455 /**
456 * Processes all of the watchers of the current scope and its children.
457 * Because a watcher's listener can change the model, the `$digest()` operatio n keeps calling
458 * the watchers no further response data has changed. This means that it is po ssible to get
459 * into an infinite loop. This function will throw `'Maximum iteration limit e xceeded.'`
460 * if the number of iterations exceeds 10.
461 *
462 * There should really be no need to call $digest() in production code since e verything is
463 * handled behind the scenes with zones and object mutation events. However, i n testing
464 * both $digest and [$apply] are useful to control state and simulate the scop e life cycle in
465 * a step-by-step manner.
466 *
467 * Refer to [$watch], [$watchSet] or [$watchCollection] to see how to register watchers that
468 * are executed during the digest cycle.
469 */
401 $digest() { 470 $digest() {
402 try { 471 try {
403 _beginPhase('\$digest'); 472 _beginPhase('\$digest');
404 _digestWhileDirtyLoop(); 473 _digestWhileDirtyLoop();
405 } catch (e, s) { 474 } catch (e, s) {
406 _exceptionHandler(e, s); 475 _exceptionHandler(e, s);
407 } finally { 476 } finally {
408 _clearPhase(); 477 _clearPhase();
409 } 478 }
410 } 479 }
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
582 _digestUpdatePerfCounters(watcherCount, scopeCount); 651 _digestUpdatePerfCounters(watcherCount, scopeCount);
583 } 652 }
584 653
585 654
586 void _digestUpdatePerfCounters(int watcherCount, int scopeCount) { 655 void _digestUpdatePerfCounters(int watcherCount, int scopeCount) {
587 _perf.counters['ng.scope.watchers'] = watcherCount; 656 _perf.counters['ng.scope.watchers'] = watcherCount;
588 _perf.counters['ng.scopes'] = scopeCount; 657 _perf.counters['ng.scopes'] = scopeCount;
589 } 658 }
590 659
591 660
661 /**
662 * Removes the current scope (and all of its children) from the parent scope. Removal implies
663 * that calls to $digest() will no longer propagate to the current scope and i ts children.
664 * Removal also implies that the current scope is eligible for garbage collect ion.
665 *
666 * The `$destroy()` operation is usually used within directives that perform t ransclusion on
667 * multiple child elements (like ngRepeat) which create multiple child scopes.
668 *
669 * Just before a scope is destroyed, a `$destroy` event is broadcasted on this scope. This is
670 * a great way for child scopes (such as shared directives or controllers) to detect to and
671 * perform any necessary cleanup before the scope is removed from the applicat ion.
672 *
673 * Note that, in AngularDart, there is also a `$destroy` jQuery DOM event, whi ch can be used to
674 * clean up DOM bindings before an element is removed from the DOM.
675 */
592 $destroy() { 676 $destroy() {
593 if ($root == this) return; // we can't remove the root node; 677 if ($root == this) return; // we can't remove the root node;
594 678
595 $broadcast(r'$destroy'); 679 $broadcast(r'$destroy');
596 680
597 if ($parent._childHead == this) $parent._childHead = _nextSibling; 681 if ($parent._childHead == this) $parent._childHead = _nextSibling;
598 if ($parent._childTail == this) $parent._childTail = _prevSibling; 682 if ($parent._childTail == this) $parent._childTail = _prevSibling;
599 if (_prevSibling != null) _prevSibling._nextSibling = _nextSibling; 683 if (_prevSibling != null) _prevSibling._nextSibling = _nextSibling;
600 if (_nextSibling != null) _nextSibling._prevSibling = _prevSibling; 684 if (_nextSibling != null) _nextSibling._prevSibling = _prevSibling;
601 } 685 }
602 686
603 687
688 /**
689 * Evaluates the expression against the current scope and returns the result. Note that, the
690 * expression data is relative to the data within the scope. Therefore an expr ession such as
691 * `a + b` will deference variables `a` and `b` and return a result so long as `a` and `b`
692 * exist on the scope.
693 *
694 * * [expr] - The expression that will be evaluated. This can be both a Functi on or a String.
695 * * [locals] - An optional Map of key/value data that will override any match ing scope members
696 * for the purposes of the evaluation.
697 */
604 $eval(expr, [locals]) { 698 $eval(expr, [locals]) {
605 return relaxFnArgs(_compileToFn(expr))(locals == null ? this : new ScopeLoca ls(this, locals)); 699 return relaxFnArgs(_compileToFn(expr))(locals == null ? this : new ScopeLoca ls(this, locals));
606 } 700 }
607 701
608 702
703 /**
704 * Evaluates the expression against the current scope at a later point in time . The $evalAsync
705 * operation may not get run right away (depending if an existing digest cycle is going on) and
706 * may therefore be issued later on (by a follow-up digest cycle). Note that a t least one digest
707 * cycle will be performed after the expression is evaluated. However, If trig gering an additional
708 * digest cycle is not desired then this can be avoided by placing `{outsideDi gest: true}` as
709 * the 2nd parameter to the function.
710 *
711 * * [expr] - The expression that will be evaluated. This can be both a Functi on or a String.
712 * * [outsideDigest] - Whether or not to trigger a follow-up digest after eval uation.
713 */
609 $evalAsync(expr, {outsideDigest: false}) { 714 $evalAsync(expr, {outsideDigest: false}) {
610 if (outsideDigest) { 715 if (outsideDigest) {
611 _outerAsyncQueue.add(expr); 716 _outerAsyncQueue.add(expr);
612 } else { 717 } else {
613 _innerAsyncQueue.add(expr); 718 _innerAsyncQueue.add(expr);
614 } 719 }
615 } 720 }
616 721
617 722
618 /** 723 /**
619 * Skip running a $digest at the end of this turn. 724 * Skip running a $digest at the end of this turn.
620 * The primary use case is to skip the digest in the current VM turn because 725 * The primary use case is to skip the digest in the current VM turn because
621 * you just scheduled or are otherwise certain of an impending VM turn and the 726 * you just scheduled or are otherwise certain of an impending VM turn and the
622 * digest at the end of that turn is sufficient. You should be able to answer 727 * digest at the end of that turn is sufficient. You should be able to answer
623 * "No" to the question "Is there any other code that is aware that this VM 728 * "No" to the question "Is there any other code that is aware that this VM
624 * turn occured and therefore expected a digest?". If your answer is "Yes", 729 * turn occurred and therefore expected a digest?". If your answer is "Yes",
625 * then you run the risk that the very next VM turn is not for your event and 730 * then you run the risk that the very next VM turn is not for your event and
626 * now that other code runs in that turn and sees stale values. 731 * now that other code runs in that turn and sees stale values.
627 * 732 *
628 * You might call this function, for instance, from an event listener where, 733 * You might call this function, for instance, from an event listener where,
629 * though the event occured, you need to wait for another event before you can 734 * though the event occurred, you need to wait for another event before you ca n
630 * perform something meaningful. You might schedule that other event, 735 * perform something meaningful. You might schedule that other event,
631 * set a flag for the handler of the other event to recognize, etc. and then 736 * set a flag for the handler of the other event to recognize, etc. and then
632 * call this method to skip the digest this cycle. Note that you should call 737 * call this method to skip the digest this cycle. Note that you should call
633 * this function *after* you have successfully confirmed that the expected VM 738 * this function *after* you have successfully confirmed that the expected VM
634 * turn will occur (perhaps by scheduling it) to ensure that the digest 739 * turn will occur (perhaps by scheduling it) to ensure that the digest
635 * actually does take place on that turn. 740 * actually does take place on that turn.
636 */ 741 */
637 $skipAutoDigest() { 742 $skipAutoDigest() {
638 _zone.assertInTurn(); 743 _zone.assertInTurn();
639 _skipAutoDigest = true; 744 $root._skipAutoDigest = true;
640 } 745 }
641 746
642 747
748 /**
749 * Triggers a digest operation much like [$digest] does, however, also accepts an
750 * optional expression to evaluate alongside the digest operation. The result of that
751 * expression will be returned afterwards. Much like with $digest, $apply shou ld only be
752 * used within unit tests to simulate the life cycle of a scope. See [$digest] to learn
753 * more.
754 *
755 * * [expr] - optional expression which will be evaluated after the digest is performed. See [$eval]
756 * to learn more about expressions.
757 */
643 $apply([expr]) { 758 $apply([expr]) {
644 return _zone.run(() { 759 return _zone.run(() {
645 var timerId; 760 var timerId;
646 try { 761 try {
647 assert((timerId = _perf.startTimer('ng.\$apply', _source(expr))) != fals e); 762 assert((timerId = _perf.startTimer('ng.\$apply', _source(expr))) != fals e);
648 return $eval(expr); 763 return $eval(expr);
649 } catch (e, s) { 764 } catch (e, s) {
650 _exceptionHandler(e, s); 765 _exceptionHandler(e, s);
651 } finally { 766 } finally {
652 assert(_perf.stopTimer(timerId) != false); 767 assert(_perf.stopTimer(timerId) != false);
653 } 768 }
654 }); 769 });
655 } 770 }
656 771
657 772
773 /**
774 * Registers a scope-based event listener to intercept events triggered by
775 * [$broadcast] (from any parent scopes) or [$emit] (from child scopes) that
776 * match the given event name. $on accepts two arguments:
777 *
778 * * [name] - Refers to the event name that the scope will listen on.
779 * * [listener] - Refers to the callback function which is executed when the e vent
780 * is intercepted.
781 *
782 *
783 * When the listener function is executed, an instance of [ScopeEvent] will be passed
784 * as the first parameter to the function.
785 *
786 * Any additional parameters available within the listener callback function a re those that
787 * are set by the $broadcast or $emit scope methods (which are set by the orig in scope which
788 * is the scope that first triggered the scope event).
789 */
658 $on(name, listener) { 790 $on(name, listener) {
659 var namedListeners = _listeners[name]; 791 var namedListeners = _listeners[name];
660 if (!_listeners.containsKey(name)) { 792 if (!_listeners.containsKey(name)) {
661 _listeners[name] = namedListeners = []; 793 _listeners[name] = namedListeners = [];
662 } 794 }
663 namedListeners.add(listener); 795 namedListeners.add(listener);
664 796
665 return () { 797 return () {
666 namedListeners.remove(listener); 798 namedListeners.remove(listener);
667 }; 799 };
668 } 800 }
669 801
670 802
803 /**
804 * Triggers a scope event referenced by the [name] parameters upwards towards the root of the
805 * scope tree. If intercepted, by a parent scope containing a matching scope e vent listener
806 * (which is registered via the [$on] scope method), then the event listener c allback function
807 * will be executed.
808 *
809 * * [name] - The scope event name that will be triggered.
810 * * [args] - An optional list of arguments that will be fed into the listener callback function
811 * for any event listeners that are registered via [$on].
812 */
671 $emit(name, [List args]) { 813 $emit(name, [List args]) {
672 var empty = [], 814 var empty = [],
673 namedListeners, 815 namedListeners,
674 scope = this, 816 scope = this,
675 event = new ScopeEvent(name, this), 817 event = new ScopeEvent(name, this),
676 listenerArgs = [event], 818 listenerArgs = [event],
677 i; 819 i;
678 820
679 if (args != null) { 821 if (args != null) {
680 listenerArgs.addAll(args); 822 listenerArgs.addAll(args);
(...skipping 14 matching lines...) Expand all
695 } 837 }
696 } 838 }
697 //traverse upwards 839 //traverse upwards
698 scope = scope.$parent; 840 scope = scope.$parent;
699 } while (scope != null); 841 } while (scope != null);
700 842
701 return event; 843 return event;
702 } 844 }
703 845
704 846
847 /**
848 * Triggers a scope event referenced by the [name] parameters dowards towards the leaf nodes of the
849 * scope tree. If intercepted, by a child scope containing a matching scope ev ent listener
850 * (which is registered via the [$on] scope method), then the event listener c allback function
851 * will be executed.
852 *
853 * * [name] - The scope event name that will be triggered.
854 * * [listenerArgs] - An optional list of arguments that will be fed into the listener callback function
855 * for any event listeners that are registered via [$on].
856 */
705 $broadcast(String name, [List listenerArgs]) { 857 $broadcast(String name, [List listenerArgs]) {
706 var target = this, 858 var target = this,
707 current = target, 859 current = target,
708 next = target, 860 next = target,
709 event = new ScopeEvent(name, this); 861 event = new ScopeEvent(name, this);
710 862
711 //down while you can, then up and next sibling or up and next sibling until back at root 863 //down while you can, then up and next sibling or up and next sibling until back at root
712 if (listenerArgs == null) { 864 if (listenerArgs == null) {
713 listenerArgs = []; 865 listenerArgs = [];
714 } 866 }
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
760 912
761 _clearPhase() { 913 _clearPhase() {
762 assert(_perf.stopTimer('ng.phase.${$root._phase}') != false); 914 assert(_perf.stopTimer('ng.phase.${$root._phase}') != false);
763 $root._phase = null; 915 $root._phase = null;
764 } 916 }
765 917
766 Function _compileToFn(exp) { 918 Function _compileToFn(exp) {
767 if (exp == null) { 919 if (exp == null) {
768 return () => null; 920 return () => null;
769 } else if (exp is String) { 921 } else if (exp is String) {
770 return _parser(exp).eval; 922 Expression expression = _parser(exp);
923 return expression.eval;
771 } else if (exp is Function) { 924 } else if (exp is Function) {
772 return exp; 925 return exp;
773 } else { 926 } else {
774 throw 'Expecting String or Function'; 927 throw 'Expecting String or Function';
775 } 928 }
776 } 929 }
777 } 930 }
778 931
779 @proxy 932 @proxy
780 class ScopeLocals implements Scope, Map { 933 class ScopeLocals implements Scope, Map {
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
851 return JSON.encode(obj); 1004 return JSON.encode(obj);
852 } catch(e) { 1005 } catch(e) {
853 var ret = "NOT-JSONABLE"; 1006 var ret = "NOT-JSONABLE";
854 // Keep prod fast. 1007 // Keep prod fast.
855 assert((() { 1008 assert((() {
856 var mirror = reflect(obj); 1009 var mirror = reflect(obj);
857 if (mirror is ClosureMirror) { 1010 if (mirror is ClosureMirror) {
858 // work-around dartbug.com/14130 1011 // work-around dartbug.com/14130
859 try { 1012 try {
860 ret = mirror.function.source; 1013 ret = mirror.function.source;
861 } on NoSuchMethodError catch (e) {} 1014 } on NoSuchMethodError catch (e) {
1015 } on UnimplementedError catch (e) {
1016 }
862 } 1017 }
863 return true; 1018 return true;
864 })()); 1019 })());
865 return ret; 1020 return ret;
866 } 1021 }
867 } 1022 }
868 1023
869 String _source(obj) { 1024 String _source(obj) {
870 if (obj is Function) { 1025 if (obj is Function) {
871 var m = reflect(obj); 1026 var m = reflect(obj);
872 if (m is ClosureMirror) { 1027 if (m is ClosureMirror) {
873 // work-around dartbug.com/14130 1028 // work-around dartbug.com/14130
874 try { 1029 try {
875 return "FN: ${m.function.source}"; 1030 return "FN: ${m.function.source}";
876 } on NoSuchMethodError catch (e) { 1031 } on NoSuchMethodError catch (e) {
877 } on UnimplementedError catch (e) { 1032 } on UnimplementedError catch (e) {
878 } 1033 }
879 } 1034 }
880 } 1035 }
881 return '$obj'; 1036 return '$obj';
882 } 1037 }
OLDNEW
« no previous file with comments | « third_party/pkg/angular/lib/core/registry.dart ('k') | third_party/pkg/angular/lib/core_dom/block.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698