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

Unified Diff: third_party/pkg/angular/lib/core/scope.dart

Issue 256553002: Revert "Update all Angular libs (run update_all.sh)." (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 8 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: third_party/pkg/angular/lib/core/scope.dart
diff --git a/third_party/pkg/angular/lib/core/scope.dart b/third_party/pkg/angular/lib/core/scope.dart
index 128cf77e992708f299924df3eb814feb3b376eb9..db063051d69a2051c6777e647bceae0fcb717f71 100644
--- a/third_party/pkg/angular/lib/core/scope.dart
+++ b/third_party/pkg/angular/lib/core/scope.dart
@@ -1,4 +1,8 @@
-part of angular.core_internal;
+part of angular.core;
+
+NOT_IMPLEMENTED() {
+ throw new StateError('Not Implemented');
+}
typedef EvalFunction0();
typedef EvalFunction1(context);
@@ -77,7 +81,7 @@ class ScopeEvent {
* triggers watch A. If the system does not stabilize in TTL iterations then
* the digest is stopped and an exception is thrown.
*/
-@Injectable()
+@NgInjectableService()
class ScopeDigestTTL {
final int ttl;
ScopeDigestTTL(): ttl = 5;
@@ -98,8 +102,7 @@ class ScopeLocals implements Map {
_scope[name] = value;
}
dynamic operator [](String name) =>
- // as Map needed to clear Dart2js warning
- ((_locals.containsKey(name) ? _locals : _scope) as Map)[name];
+ (_locals.containsKey(name) ? _locals : _scope)[name];
bool get isEmpty => _scope.isEmpty && _locals.isEmpty;
bool get isNotEmpty => _scope.isNotEmpty || _locals.isNotEmpty;
@@ -125,13 +128,11 @@ class ScopeLocals implements Map {
/**
* [Scope] is represents a collection of [watch]es [observe]ers, and [context]
* for the watchers, observers and [eval]uations. Scopes structure loosely
- * mimics the DOM structure. Scopes and [View]s are bound to each other.
- * As scopes are created and destroyed by [ViewFactory] they are responsible
+ * mimics the DOM structure. Scopes and [Block]s are bound to each other.
+ * As scopes are created and destroyed by [BlockFactory] they are responsible
* for change detection, change processing and memory management.
*/
class Scope {
- final String id;
- int _childScopeNextId = 0;
/**
* The default execution context for [watch]es [observe]ers, and [eval]uation.
@@ -150,15 +151,13 @@ class Scope {
*/
Scope get parentScope => _parentScope;
- final ScopeStats _stats;
-
/**
* Return `true` if the scope has been destroyed. Once scope is destroyed
* No operations are allowed on it.
*/
bool get isDestroyed {
var scope = this;
- while (scope != null) {
+ while(scope != null) {
if (scope == rootScope) return false;
scope = scope._parentScope;
}
@@ -183,38 +182,24 @@ class Scope {
bool get hasOwnStreams => _streams != null && _streams._scope == this;
Scope(Object this.context, this.rootScope, this._parentScope,
- this._readWriteGroup, this._readOnlyGroup, this.id,
- this._stats);
+ this._readWriteGroup, this._readOnlyGroup);
/**
- * Use [watch] to set up change detection on an expression.
+ * A [watch] sets up a watch in the [digest] phase of the [apply] cycle.
*
- * * [expression]: The expression to watch for changes.
- * * [reactionFn]: The reaction function to execute when a change is detected in the watched
- * expression.
- * * [context]: The object against which the expression is evaluated. This defaults to the
- * [Scope.context] if no context is specified.
- * * [formatters]: If the watched expression contains formatters,
- * this map specifies the set of formatters that are used by the expression.
- * * [canChangeModel]: Specifies whether the [reactionFn] changes the model. Reaction
- * functions that change the model are processed as part of the [digest] cycle. Otherwise,
- * they are processed as part of the [flush] cycle.
- * * [collection]: If [:true:], then the expression points to a collection (a list or a map),
- * and the collection should be shallow watched. If [:false:] then the expression is watched
- * by reference. When watching a collection, the reaction function receives a
- * [CollectionChangeItem] that lists all the changes.
+ * Use [watch] if the reaction function can cause updates to model. In your
+ * controller code you will most likely use [watch].
*/
- Watch watch(String expression, ReactionFn reactionFn, {context,
- FormatterMap formatters, bool canChangeModel: true, bool collection: false}) {
+ Watch watch(expression, ReactionFn reactionFn,
+ {context, FilterMap filters, bool readOnly: false}) {
assert(isAttached);
- assert(expression is String);
- assert(canChangeModel is bool);
-
+ assert(expression != null);
+ AST ast;
Watch watch;
ReactionFn fn = reactionFn;
- if (expression.isEmpty) {
- expression = '""';
- } else {
+ if (expression is AST) {
+ ast = expression;
+ } else if (expression is String) {
if (expression.startsWith('::')) {
expression = expression.substring(2);
fn = (value, last) {
@@ -225,17 +210,13 @@ class Scope {
};
} else if (expression.startsWith(':')) {
expression = expression.substring(1);
- fn = (value, last) {
- if (value != null) reactionFn(value, last);
- };
+ fn = (value, last) => value == null ? null : reactionFn(value, last);
}
+ ast = rootScope._astParser(expression, context: context, filters: filters);
+ } else {
+ throw 'expressions must be String or AST got $expression.';
}
-
- AST ast = rootScope._astParser(expression, context: context,
- formatters: formatters, collection: collection);
-
- WatchGroup group = canChangeModel ? _readWriteGroup : _readOnlyGroup;
- return watch = group.watch(ast, fn);
+ return watch = (readOnly ? _readOnlyGroup : _readWriteGroup).watch(ast, fn);
}
dynamic eval(expression, [Map locals]) {
@@ -254,6 +235,9 @@ class Scope {
return null;
}
+ dynamic applyInZone([expression, Map locals]) =>
+ rootScope._zone.run(() => apply(expression, locals));
+
dynamic apply([expression, Map locals]) {
_assertInternalStateConsistency();
rootScope._transitionState(null, RootScope.STATE_APPLY);
@@ -262,9 +246,10 @@ class Scope {
} catch (e, s) {
rootScope._exceptionHandler(e, s);
} finally {
- rootScope.._transitionState(RootScope.STATE_APPLY, null)
- ..digest()
- ..flush();
+ rootScope
+ .._transitionState(RootScope.STATE_APPLY, null)
+ ..digest()
+ ..flush();
}
}
@@ -272,12 +257,10 @@ class Scope {
assert(isAttached);
return _Streams.emit(this, name, data);
}
-
ScopeEvent broadcast(String name, [data]) {
assert(isAttached);
return _Streams.broadcast(this, name, data);
}
-
ScopeStream on(String name) {
assert(isAttached);
return _Streams.on(this, rootScope._exceptionHandler, name);
@@ -287,14 +270,13 @@ class Scope {
assert(isAttached);
var child = new Scope(childContext, rootScope, this,
_readWriteGroup.newGroup(childContext),
- _readOnlyGroup.newGroup(childContext),
- '$id:${_childScopeNextId++}',
- _stats);
-
+ _readOnlyGroup.newGroup(childContext));
+ var next = null;
var prev = _childTail;
+ child._next = next;
child._prev = prev;
if (prev == null) _childHead = child; else prev._next = child;
- _childTail = child;
+ if (next == null) _childTail = child; else next._prev = child;
return child;
}
@@ -319,6 +301,7 @@ class Scope {
_readWriteGroup.remove();
_readOnlyGroup.remove();
_parentScope = null;
+ _assertInternalStateConsistency();
}
_assertInternalStateConsistency() {
@@ -343,7 +326,7 @@ class Scope {
});
}
var childScope = _childHead;
- while (childScope != null) {
+ while(childScope != null) {
childScope._verifyStreams(this, ' $prefix', log).forEach((k, v) {
counts[k] = v + (counts.containsKey(k) ? counts[k] : 0);
});
@@ -361,176 +344,70 @@ class Scope {
_mapEqual(Map a, Map b) => a.length == b.length &&
a.keys.every((k) => b.containsKey(k) && a[k] == b[k]);
-/**
- * ScopeStats collects and emits statistics about a [Scope].
- *
- * ScopeStats supports emitting the results. Result emission can be started or
- * stopped at runtime. The result emission can is configured by supplying a
- * [ScopeStatsEmitter].
- */
-@Injectable()
class ScopeStats {
- final fieldStopwatch = new AvgStopwatch();
- final evalStopwatch = new AvgStopwatch();
- final processStopwatch = new AvgStopwatch();
-
- List<int> _digestLoopTimes = [];
- int _flushPhaseDuration = 0 ;
- int _assertFlushPhaseDuration = 0;
+ bool report = true;
+ final nf = new NumberFormat.decimalPattern();
- int _loopNo = 0;
- ScopeStatsEmitter _emitter;
- ScopeStatsConfig _config;
+ final digestFieldStopwatch = new AvgStopwatch();
+ final digestEvalStopwatch = new AvgStopwatch();
+ final digestProcessStopwatch = new AvgStopwatch();
+ int _digestLoopNo = 0;
- /**
- * Construct a new instance of ScopeStats.
- */
- ScopeStats(this._emitter, this._config);
+ final flushFieldStopwatch = new AvgStopwatch();
+ final flushEvalStopwatch = new AvgStopwatch();
+ final flushProcessStopwatch = new AvgStopwatch();
- void digestStart() {
- _digestLoopTimes = [];
- _stopwatchReset();
- _loopNo = 0;
+ ScopeStats({this.report: false}) {
+ nf.maximumFractionDigits = 0;
}
- int _allStagesDuration() {
- return fieldStopwatch.elapsedMicroseconds +
- evalStopwatch.elapsedMicroseconds +
- processStopwatch.elapsedMicroseconds;
+ void digestStart() {
+ _digestStopwatchReset();
+ _digestLoopNo = 0;
}
- _stopwatchReset() {
- fieldStopwatch.reset();
- evalStopwatch.reset();
- processStopwatch.reset();
+ _digestStopwatchReset() {
+ digestFieldStopwatch.reset();
+ digestEvalStopwatch.reset();
+ digestProcessStopwatch.reset();
}
void digestLoop(int changeCount) {
- _loopNo++;
- if (_config.emit && _emitter != null) {
- _emitter.emit(_loopNo.toString(), fieldStopwatch, evalStopwatch,
- processStopwatch);
+ _digestLoopNo++;
+ if (report) {
+ print(this);
}
- _digestLoopTimes.add( _allStagesDuration() );
- _stopwatchReset();
+ _digestStopwatchReset();
}
- void digestEnd() {
- }
-
- void domWriteStart() {}
- void domWriteEnd() {}
- void domReadStart() {}
- void domReadEnd() {}
- void flushStart() {
- _stopwatchReset();
- }
- void flushEnd() {
- if (_config.emit && _emitter != null) {
- _emitter.emit(RootScope.STATE_FLUSH, fieldStopwatch, evalStopwatch,
- processStopwatch);
- }
- _flushPhaseDuration = _allStagesDuration();
- }
- void flushAssertStart() {
- _stopwatchReset();
- }
- void flushAssertEnd() {
- if (_config.emit && _emitter != null) {
- _emitter.emit(RootScope.STATE_FLUSH_ASSERT, fieldStopwatch, evalStopwatch,
- processStopwatch);
- }
- _assertFlushPhaseDuration = _allStagesDuration();
- }
-
- void cycleEnd() {
- }
-}
-
-/**
- * ScopeStatsEmitter is in charge of formatting the [ScopeStats] and outputting
- * a message.
- */
-@Injectable()
-class ScopeStatsEmitter {
- static String _PAD_ = ' ';
- static String _HEADER_ = pad('APPLY', 7) + ':'+
- pad('FIELD', 19) + pad('|', 20) +
- pad('EVAL', 19) + pad('|', 20) +
- pad('REACTION', 19) + pad('|', 20) +
- pad('TOTAL', 10) + '\n';
- final _nfDec = new NumberFormat("0.00", "en_US");
- final _nfInt = new NumberFormat("0", "en_US");
-
- static pad(String str, int size) => _PAD_.substring(0, max(size - str.length, 0)) + str;
-
- _ms(num value) => '${pad(_nfDec.format(value), 9)} ms';
- _us(num value) => _ms(value / 1000);
- _tally(num value) => '${pad(_nfInt.format(value), 6)}';
-
- /**
- * Emit a message based on the phase and state of stopwatches.
- */
- void emit(String phaseOrLoopNo, AvgStopwatch fieldStopwatch,
- AvgStopwatch evalStopwatch, AvgStopwatch processStopwatch) {
- var total = fieldStopwatch.elapsedMicroseconds +
- evalStopwatch.elapsedMicroseconds +
- processStopwatch.elapsedMicroseconds;
- print('${_formatPrefix(phaseOrLoopNo)} '
- '${_stat(fieldStopwatch)} | '
- '${_stat(evalStopwatch)} | '
- '${_stat(processStopwatch)} | '
- '${_ms(total/1000)}');
+ String _stat(AvgStopwatch s) {
+ return '${nf.format(s.count)}'
+ ' / ${nf.format(s.elapsedMicroseconds)} us'
+ ' = ${nf.format(s.ratePerMs)} #/ms';
}
- String _formatPrefix(String prefix) {
- if (prefix == RootScope.STATE_FLUSH) return ' flush:';
- if (prefix == RootScope.STATE_FLUSH_ASSERT) return ' assert:';
-
- return (prefix == '1' ? _HEADER_ : '') + ' #$prefix:';
+ void digestEnd() {
}
- String _stat(AvgStopwatch s) {
- return '${_tally(s.count)} / ${_us(s.elapsedMicroseconds)} @(${_tally(s.ratePerMs)} #/ms)';
- }
+ toString() =>
+ 'digest #$_digestLoopNo:'
+ 'Field: ${_stat(digestFieldStopwatch)} '
+ 'Eval: ${_stat(digestEvalStopwatch)} '
+ 'Process: ${_stat(digestProcessStopwatch)}';
}
-/**
- * ScopeStatsConfig is used to modify behavior of [ScopeStats]. You can use this
- * object to modify behavior at runtime too.
- */
-class ScopeStatsConfig {
- var emit = false;
- ScopeStatsConfig();
- ScopeStatsConfig.enabled() {
- emit = true;
- }
-}
-/**
- *
- * Every Angular application has exactly one RootScope. RootScope extends Scope, adding
- * services related to change detection, async unit-of-work processing, and DOM read/write queues.
- * The RootScope can not be destroyed.
- *
- * ## Lifecycle
- *
- * All work in Angular must be done within a context of a VmTurnZone. VmTurnZone detects the end
- * of the VM turn, and calls the Apply method to process the changes at the end of VM turn.
- *
- */
-@Injectable()
class RootScope extends Scope {
static final STATE_APPLY = 'apply';
static final STATE_DIGEST = 'digest';
- static final STATE_FLUSH = 'flush';
- static final STATE_FLUSH_ASSERT = 'assert';
+ static final STATE_FLUSH = 'digest';
final ExceptionHandler _exceptionHandler;
- final _AstParser _astParser;
+ final AstParser _astParser;
final Parser _parser;
final ScopeDigestTTL _ttl;
- final VmTurnZone _zone;
+ final ExpressionVisitor visitor = new ExpressionVisitor(); // TODO(misko): delete me
+ final NgZone _zone;
_FunctionChain _runAsyncHead, _runAsyncTail;
_FunctionChain _domWriteHead, _domWriteTail;
@@ -540,68 +417,13 @@ class RootScope extends Scope {
String _state;
- /**
- *
- * While processing data bindings, Angular passes through multiple states. When testing or
- * debugging, it can be useful to access the current `state`, which is one of the following:
- *
- * * null
- * * apply
- * * digest
- * * flush
- * * assert
- *
- * ##null
- *
- * Angular is not currently processing changes
- *
- * ##apply
- *
- * The apply state begins by executing the optional expression within the context of
- * angular change detection mechanism. Any exceptions are delegated to [ExceptionHandler]. At the
- * end of apply state RootScope enters the digest followed by flush phase (optionally if asserts
- * enabled run assert phase.)
- *
- * ##digest
- *
- * The apply state begins by processing the async queue,
- * followed by change detection
- * on non-DOM listeners. Any changes detected are process using the reaction function. The digest
- * phase is repeated as long as at least one change has been detected. By default, after 5
- * iterations the model is considered unstable and angular exists with an exception. (See
- * ScopeDigestTTL)
- *
- * ##flush
- *
- * The flush phase consists of these steps:
- *
- * 1. processing the DOM write queue
- * 2. change detection on DOM only updates (these are reaction functions which must
- * not change the model state and hence don't need stabilization as in digest phase).
- * 3. processing the DOM read queue
- * 4. repeat steps 1 and 3 (not 2) until queues are empty
- *
- * ##assert
- *
- * Optionally if Dart assert is on, verify that flush reaction functions did not make any changes
- * to model and throw error if changes detected.
- *
- */
- String get state => _state;
-
- RootScope(Object context, Parser parser, FieldGetterFactory fieldGetterFactory,
- FormatterMap formatters, this._exceptionHandler, this._ttl, this._zone,
- ScopeStats _scopeStats, ClosureMap closureMap)
- : _scopeStats = _scopeStats,
- _parser = parser,
- _astParser = new _AstParser(parser, closureMap),
- super(context, null, null,
- new RootWatchGroup(fieldGetterFactory,
- new DirtyCheckingChangeDetector(fieldGetterFactory), context),
- new RootWatchGroup(fieldGetterFactory,
- new DirtyCheckingChangeDetector(fieldGetterFactory), context),
- '',
- _scopeStats)
+ RootScope(Object context, this._astParser, this._parser,
+ GetterCache cacheGetter, FilterMap filterMap,
+ this._exceptionHandler, this._ttl, this._zone,
+ this._scopeStats)
+ : super(context, null, null,
+ new RootWatchGroup(new DirtyCheckingChangeDetector(cacheGetter), context),
+ new RootWatchGroup(new DirtyCheckingChangeDetector(cacheGetter), context))
{
_zone.onTurnDone = apply;
_zone.onError = (e, s, ls) => _exceptionHandler(e, s);
@@ -610,27 +432,10 @@ class RootScope extends Scope {
RootScope get rootScope => this;
bool get isAttached => true;
-/**
- * Propagates changes between different parts of the application model. Normally called by
- * [VMTurnZone] right before DOM rendering to initiate data binding. May also be called directly
- * for unit testing.
- *
- * Before each iteration of change detection, [digest] first processes the async queue. Any
- * work scheduled on the queue is executed before change detection. Since work scheduled on
- * the queue may generate more async calls, [digest] must process the queue multiple times before
- * it completes. The async queue must be empty before the model is considered stable.
- *
- * Next, [digest] collects the changes that have occurred in the model. For each change,
- * [digest] calls the associated [ReactionFn]. Since a [ReactionFn] may further change the model,
- * [digest] processes changes multiple times until no more changes are detected.
- *
- * If the model does not stabilize within 5 iterations, an exception is thrown. See
- * [ScopeDigestTTL].
- */
void digest() {
_transitionState(null, STATE_DIGEST);
try {
- var rootWatchGroup = _readWriteGroup as RootWatchGroup;
+ var rootWatchGroup = (_readWriteGroup as RootWatchGroup);
int digestTTL = _ttl.ttl;
const int LOG_COUNT = 3;
@@ -640,7 +445,7 @@ class RootScope extends Scope {
ChangeLog changeLog;
_scopeStats.digestStart();
do {
- while (_runAsyncHead != null) {
+ while(_runAsyncHead != null) {
try {
_runAsyncHead.fn();
} catch (e, s) {
@@ -648,15 +453,14 @@ class RootScope extends Scope {
}
_runAsyncHead = _runAsyncHead._next;
}
- _runAsyncTail = null;
digestTTL--;
count = rootWatchGroup.detectChanges(
exceptionHandler: _exceptionHandler,
changeLog: changeLog,
- fieldStopwatch: _scopeStats.fieldStopwatch,
- evalStopwatch: _scopeStats.evalStopwatch,
- processStopwatch: _scopeStats.processStopwatch);
+ fieldStopwatch: _scopeStats.digestFieldStopwatch,
+ evalStopwatch: _scopeStats.digestEvalStopwatch,
+ processStopwatch: _scopeStats.digestProcessStopwatch);
if (digestTTL <= LOG_COUNT) {
if (changeLog == null) {
@@ -681,69 +485,50 @@ class RootScope extends Scope {
}
void flush() {
- _stats.flushStart();
_transitionState(null, STATE_FLUSH);
- RootWatchGroup readOnlyGroup = this._readOnlyGroup as RootWatchGroup;
+ var observeGroup = this._readOnlyGroup as RootWatchGroup;
bool runObservers = true;
try {
do {
- if (_domWriteHead != null) _stats.domWriteStart();
- while (_domWriteHead != null) {
+ while(_domWriteHead != null) {
try {
_domWriteHead.fn();
} catch (e, s) {
_exceptionHandler(e, s);
}
_domWriteHead = _domWriteHead._next;
- if (_domWriteHead == null) _stats.domWriteEnd();
}
- _domWriteTail = null;
if (runObservers) {
runObservers = false;
- readOnlyGroup.detectChanges(exceptionHandler:_exceptionHandler,
- fieldStopwatch: _scopeStats.fieldStopwatch,
- evalStopwatch: _scopeStats.evalStopwatch,
- processStopwatch: _scopeStats.processStopwatch);
+ observeGroup.detectChanges(exceptionHandler:_exceptionHandler);
}
- if (_domReadHead != null) _stats.domReadStart();
- while (_domReadHead != null) {
+ while(_domReadHead != null) {
try {
_domReadHead.fn();
} catch (e, s) {
_exceptionHandler(e, s);
}
_domReadHead = _domReadHead._next;
- if (_domReadHead == null) _stats.domReadEnd();
}
- _domReadTail = null;
} while (_domWriteHead != null || _domReadHead != null);
- _stats.flushEnd();
assert((() {
- _stats.flushAssertStart();
- var digestLog = [];
- var flushLog = [];
+ var watchLog = [];
+ var observeLog = [];
(_readWriteGroup as RootWatchGroup).detectChanges(
- changeLog: (s, c, p) => digestLog.add('$s: $c <= $p'),
- fieldStopwatch: _scopeStats.fieldStopwatch,
- evalStopwatch: _scopeStats.evalStopwatch,
- processStopwatch: _scopeStats.processStopwatch);
- (_readOnlyGroup as RootWatchGroup).detectChanges(
- changeLog: (s, c, p) => flushLog.add('$s: $c <= $p'),
- fieldStopwatch: _scopeStats.fieldStopwatch,
- evalStopwatch: _scopeStats.evalStopwatch,
- processStopwatch: _scopeStats.processStopwatch);
- if (digestLog.isNotEmpty || flushLog.isNotEmpty) {
+ changeLog: (s, c, p) => watchLog.add('$s: $c <= $p'));
+ (observeGroup as RootWatchGroup).detectChanges(
+ changeLog: (s, c, p) => watchLog.add('$s: $c <= $p'));
+ if (watchLog.isNotEmpty || observeLog.isNotEmpty) {
throw 'Observer reaction functions should not change model. \n'
- 'These watch changes were detected: ${digestLog.join('; ')}\n'
- 'These observe changes were detected: ${flushLog.join('; ')}';
+ 'These watch changes were detected: ${watchLog.join('; ')}\n'
+ 'These observe changes were detected: ${observeLog.join('; ')}';
}
- _stats.flushAssertEnd();
return true;
})());
} finally {
- _stats.cycleEnd();
_transitionState(STATE_FLUSH, null);
}
+
}
// QUEUES
@@ -822,7 +607,7 @@ class _Streams {
static ScopeEvent emit(Scope scope, String name, data) {
var event = new ScopeEvent(name, scope, data);
var scopeCursor = scope;
- while (scopeCursor != null) {
+ while(scopeCursor != null) {
if (scopeCursor._streams != null &&
scopeCursor._streams._scope == scopeCursor) {
ScopeStream stream = scopeCursor._streams._streams[name];
@@ -853,7 +638,7 @@ class _Streams {
}
// Reverse traversal so that when the queue is read it is correct order.
var childScope = scope._childTail;
- while (childScope != null) {
+ while(childScope != null) {
scopeStreams = childScope._streams;
if (scopeStreams != null &&
scopeStreams._typeCounts.containsKey(name)) {
@@ -866,9 +651,9 @@ class _Streams {
return event;
}
- static async.Stream<ScopeEvent> on(Scope scope,
- ExceptionHandler _exceptionHandler,
- String name) {
+ static ScopeStream on(Scope scope,
+ ExceptionHandler _exceptionHandler,
+ String name) {
_forceNewScopeStream(scope, _exceptionHandler);
return scope._streams._get(scope, name);
}
@@ -877,7 +662,7 @@ class _Streams {
_Streams streams = scope._streams;
Scope scopeCursor = scope;
bool splitMode = false;
- while (scopeCursor != null) {
+ while(scopeCursor != null) {
_Streams cursorStreams = scopeCursor._streams;
var hasStream = cursorStreams != null;
var hasOwnStream = hasStream && cursorStreams._scope == scopeCursor;
@@ -949,9 +734,6 @@ class ScopeStream extends async.Stream<ScopeEvent> {
final _Streams _streams;
final String _name;
final subscriptions = <ScopeStreamSubscription>[];
- final List<Function> _work = <Function>[];
- bool _firing = false;
-
ScopeStream(this._streams, this._exceptionHandler, this._name);
@@ -959,46 +741,29 @@ class ScopeStream extends async.Stream<ScopeEvent> {
{ Function onError,
void onDone(),
bool cancelOnError }) {
+ if (subscriptions.isEmpty) _streams._addCount(_name, 1);
var subscription = new ScopeStreamSubscription(this, onData);
- _concurrentSafeWork(() {
- if (subscriptions.isEmpty) _streams._addCount(_name, 1);
- subscriptions.add(subscription);
- });
+ subscriptions.add(subscription);
return subscription;
}
- void _concurrentSafeWork([fn]) {
- if (fn != null) _work.add(fn);
- while(!_firing && _work.isNotEmpty) {
- _work.removeLast()();
- }
- }
-
void _fire(ScopeEvent event) {
- _firing = true;
- try {
- for (ScopeStreamSubscription subscription in subscriptions) {
- try {
- subscription._onData(event);
- } catch (e, s) {
- _exceptionHandler(e, s);
- }
+ for (ScopeStreamSubscription subscription in subscriptions) {
+ try {
+ subscription._onData(event);
+ } catch (e, s) {
+ _exceptionHandler(e, s);
}
- } finally {
- _firing = false;
- _concurrentSafeWork();
}
}
void _remove(ScopeStreamSubscription subscription) {
- _concurrentSafeWork(() {
- assert(subscription._scopeStream == this);
- if (subscriptions.remove(subscription)) {
- if (subscriptions.isEmpty) _streams._addCount(_name, -1);
- } else {
- throw new StateError('AlreadyCanceled');
- }
- });
+ assert(subscription._scopeStream == this);
+ if (subscriptions.remove(subscription)) {
+ if (subscriptions.isEmpty) _streams._addCount(_name, -1);
+ } else {
+ throw new StateError('AlreadyCanceled');
+ }
}
}
@@ -1007,74 +772,64 @@ class ScopeStreamSubscription implements async.StreamSubscription<ScopeEvent> {
final Function _onData;
ScopeStreamSubscription(this._scopeStream, this._onData);
- async.Future cancel() {
- _scopeStream._remove(this);
- return null;
- }
-
- void onData(void handleData(ScopeEvent data)) => _NOT_IMPLEMENTED();
- void onError(Function handleError) => _NOT_IMPLEMENTED();
- void onDone(void handleDone()) => _NOT_IMPLEMENTED();
- void pause([async.Future resumeSignal]) => _NOT_IMPLEMENTED();
- void resume() => _NOT_IMPLEMENTED();
- bool get isPaused => _NOT_IMPLEMENTED();
- async.Future asFuture([var futureValue]) => _NOT_IMPLEMENTED();
-}
+ // TODO(vbe) should return a Future
+ cancel() => _scopeStream._remove(this);
-_NOT_IMPLEMENTED() {
- throw new StateError('Not Implemented');
+ void onData(void handleData(ScopeEvent data)) => NOT_IMPLEMENTED();
+ void onError(Function handleError) => NOT_IMPLEMENTED();
+ void onDone(void handleDone()) => NOT_IMPLEMENTED();
+ void pause([async.Future resumeSignal]) => NOT_IMPLEMENTED();
+ void resume() => NOT_IMPLEMENTED();
+ bool get isPaused => NOT_IMPLEMENTED();
+ async.Future asFuture([var futureValue]) => NOT_IMPLEMENTED();
}
-
class _FunctionChain {
final Function fn;
_FunctionChain _next;
- _FunctionChain(fn()): fn = fn {
+ _FunctionChain(fn())
+ : fn = fn
+ {
assert(fn != null);
}
}
-class _AstParser {
+class AstParser {
final Parser _parser;
int _id = 0;
- final ExpressionVisitor _visitor;
+ ExpressionVisitor _visitor = new ExpressionVisitor();
- _AstParser(this._parser, ClosureMap closureMap)
- : _visitor = new ExpressionVisitor(closureMap);
+ AstParser(this._parser);
- AST call(String input, {FormatterMap formatters,
- bool collection: false,
- Object context: null }) {
- _visitor.formatters = formatters;
+ AST call(String exp, { FilterMap filters,
+ bool collection:false,
+ Object context:null }) {
+ _visitor.filters = filters;
AST contextRef = _visitor.contextRef;
try {
if (context != null) {
_visitor.contextRef = new ConstantAST(context, '#${_id++}');
}
- var exp = _parser(input);
- return collection ? _visitor.visitCollection(exp) : _visitor.visit(exp);
+ var ast = _parser(exp);
+ return collection ? _visitor.visitCollection(ast) : _visitor.visit(ast);
} finally {
_visitor.contextRef = contextRef;
- _visitor.formatters = null;
+ _visitor.filters = null;
}
}
}
class ExpressionVisitor implements Visitor {
static final ContextReferenceAST scopeContextRef = new ContextReferenceAST();
- final ClosureMap _closureMap;
AST contextRef = scopeContextRef;
-
- ExpressionVisitor(this._closureMap);
-
AST ast;
- FormatterMap formatters;
+ FilterMap filters;
AST visit(Expression exp) {
exp.accept(this);
- assert(ast != null);
+ assert(this.ast != null);
try {
return ast;
} finally {
@@ -1088,24 +843,11 @@ class ExpressionVisitor implements Visitor {
List<AST> _toAst(List<Expression> expressions) =>
expressions.map(_mapToAst).toList();
- Map<Symbol, AST> _toAstMap(Map<String, Expression> expressions) {
- if (expressions.isEmpty) return const {};
- Map<Symbol, AST> result = new Map<Symbol, AST>();
- expressions.forEach((String name, Expression expression) {
- result[_closureMap.lookupSymbol(name)] = _mapToAst(expression);
- });
- return result;
- }
-
void visitCallScope(CallScope exp) {
- List<AST> positionals = _toAst(exp.arguments.positionals);
- Map<Symbol, AST> named = _toAstMap(exp.arguments.named);
- ast = new MethodAST(contextRef, exp.name, positionals, named);
+ ast = new MethodAST(contextRef, exp.name, _toAst(exp.arguments));
}
void visitCallMember(CallMember exp) {
- List<AST> positionals = _toAst(exp.arguments.positionals);
- Map<Symbol, AST> named = _toAstMap(exp.arguments.named);
- ast = new MethodAST(visit(exp.object), exp.name, positionals, named);
+ ast = new MethodAST(visit(exp.object), exp.name, _toAst(exp.arguments));
}
visitAccessScope(AccessScope exp) {
ast = new FieldReadAST(contextRef, exp.name);
@@ -1129,7 +871,7 @@ class ExpressionVisitor implements Visitor {
visit(exp.no)]);
}
void visitAccessKeyed(AccessKeyed exp) {
- ast = new ClosureAST('[]', _operation_bracket,
+ ast = new PureFunctionAST('[]', _operation_bracket,
[visit(exp.object), visit(exp.key)]);
}
void visitLiteralPrimitive(LiteralPrimitive exp) {
@@ -1155,10 +897,7 @@ class ExpressionVisitor implements Visitor {
}
void visitFilter(Filter exp) {
- if (formatters == null) {
- throw new Exception("No formatters have been registered");
- }
- Function filterFunction = formatters(exp.name);
+ Function filterFunction = filters(exp.name);
List<AST> args = [visitCollection(exp.expression)];
args.addAll(_toAst(exp.arguments).map((ast) => new CollectionAST(ast)));
ast = new PureFunctionAST('|${exp.name}',
@@ -1212,19 +951,19 @@ Function _operationToFunction(String operation) {
_operation_negate(value) => !toBool(value);
_operation_add(left, right) => autoConvertAdd(left, right);
-_operation_subtract(left, right) => (left != null && right != null) ? left - right : (left != null ? left : (right != null ? 0 - right : 0));
-_operation_multiply(left, right) => (left == null || right == null) ? null : left * right;
-_operation_divide(left, right) => (left == null || right == null) ? null : left / right;
-_operation_divide_int(left, right) => (left == null || right == null) ? null : left ~/ right;
-_operation_remainder(left, right) => (left == null || right == null) ? null : left % right;
+_operation_subtract(left, right) => left - right;
+_operation_multiply(left, right) => left * right;
+_operation_divide(left, right) => left / right;
+_operation_divide_int(left, right) => left ~/ right;
+_operation_remainder(left, right) => left % right;
_operation_equals(left, right) => left == right;
_operation_not_equals(left, right) => left != right;
-_operation_less_then(left, right) => (left == null || right == null) ? null : left < right;
-_operation_greater_then(left, right) => (left == null || right == null) ? null : left > right;
-_operation_less_or_equals_then(left, right) => (left == null || right == null) ? null : left <= right;
-_operation_greater_or_equals_then(left, right) => (left == null || right == null) ? null : left >= right;
-_operation_power(left, right) => (left == null || right == null) ? null : left ^ right;
-_operation_bitwise_and(left, right) => (left == null || right == null) ? null : left & right;
+_operation_less_then(left, right) => left < right;
+_operation_greater_then(left, right) => (left == null || right == null) ? false : left > right;
+_operation_less_or_equals_then(left, right) => left <= right;
+_operation_greater_or_equals_then(left, right) => left >= right;
+_operation_power(left, right) => left ^ right;
+_operation_bitwise_and(left, right) => left & right;
// TODO(misko): these should short circuit the evaluation.
_operation_logical_and(left, right) => toBool(left) && toBool(right);
_operation_logical_or(left, right) => toBool(left) || toBool(right);
@@ -1242,7 +981,7 @@ class MapFn extends FunctionApply {
MapFn(this.keys);
- Map apply(List values) {
+ apply(List values) {
// TODO(misko): figure out why do we need to make a copy instead of reusing instance?
assert(values.length == keys.length);
return new Map.fromIterables(keys, values);
@@ -1264,8 +1003,6 @@ class _FilterWrapper extends FunctionApply {
if (!identical(value, lastValue)) {
if (value is CollectionChangeRecord) {
args[i] = (value as CollectionChangeRecord).iterable;
- } else if (value is MapChangeRecord) {
- args[i] = (value as MapChangeRecord).map;
} else {
args[i] = value;
}
@@ -1273,7 +1010,7 @@ class _FilterWrapper extends FunctionApply {
}
var value = Function.apply(filterFn, args);
if (value is Iterable) {
- // Since formatters are pure we can guarantee that this well never change.
+ // Since filters are pure we can guarantee that this well never change.
// By wrapping in UnmodifiableListView we can hint to the dirty checker
// and short circuit the iterator.
value = new UnmodifiableListView(value);
« no previous file with comments | « third_party/pkg/angular/lib/core/registry_static.dart ('k') | third_party/pkg/angular/lib/core/service.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698