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

Unified 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, 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
« 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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 72637b8bf25d16e7127997a7de726ccb6fcd3678..18f6fa54df27aa8be48196d2ea15a3ae2ce74eed 100644
--- a/third_party/pkg/angular/lib/core/scope.dart
+++ b/third_party/pkg/angular/lib/core/scope.dart
@@ -2,18 +2,50 @@ part of angular.core;
/**
- * Used by [Scope.$on] to notify the listeners of events.
+ * Injected into the listener function within [Scope.$on] to provide event-specific
+ * details to the scope listener.
*/
class ScopeEvent {
+
+ /**
+ * The name of the intercepted scope event.
+ */
String name;
+
+ /**
+ * The origin scope that triggered the event (via $broadcast or $emit).
+ */
Scope targetScope;
+
+ /**
+ * The destination scope that intercepted the event.
+ */
Scope currentScope;
+
+ /**
+ * true or false depending on if stopPropagation() was executed.
+ */
bool propagationStopped = false;
+
+ /**
+ * true or false depending on if preventDefault() was executed.
+ */
bool defaultPrevented = false;
+ /**
+ ** [name] - The name of the scope event.
+ ** [targetScope] - The destination scope that is listening on the event.
+ */
ScopeEvent(this.name, this.targetScope);
+ /**
+ * Prevents the intercepted event from propagating further to successive scopes.
+ */
stopPropagation () => propagationStopped = true;
+
+ /**
+ * Sets the defaultPrevented flag to true.
+ */
preventDefault() => defaultPrevented = true;
}
@@ -50,9 +82,20 @@ class Scope implements Map {
final bool _isolate;
final bool _lazy;
final Profiler _perf;
+
+ /**
+ * The direct parent scope that created this scope (this can also be the $rootScope)
+ */
final Scope $parent;
+ /**
+ * The auto-incremented ID of the scope
+ */
String $id;
+
+ /**
+ * The topmost scope of the application (same as $rootScope).
+ */
Scope $root;
num _nextId = 0;
String _phase;
@@ -62,10 +105,16 @@ class Scope implements Map {
bool _skipAutoDigest = false;
bool _disabled = false;
+ _set$Properties() {
+ _properties[r'this'] = this;
+ _properties[r'$id'] = this.$id;
+ _properties[r'$parent'] = this.$parent;
+ _properties[r'$root'] = this.$root;
+ }
+
Scope(this._exceptionHandler, this._parser, ScopeDigestTTL ttl,
this._zone, this._perf):
$parent = null, _isolate = false, _lazy = false, _ttl = ttl.ttl {
- _properties[r'this']= this;
$root = this;
$id = '_${$root._nextId++}';
_innerAsyncQueue = [];
@@ -74,12 +123,12 @@ class Scope implements Map {
// Set up the zone to auto digest this scope.
_zone.onTurnDone = _autoDigestOnTurnDone;
_zone.onError = (e, s, ls) => _exceptionHandler(e, s);
+ _set$Properties();
}
Scope._child(Scope parent, bool this._isolate, bool this._lazy, Profiler this._perf):
$parent = parent, _ttl = parent._ttl, _parser = parent._parser,
_exceptionHandler = parent._exceptionHandler, _zone = parent._zone {
- _properties[r'this'] = this;
$root = $parent.$root;
$id = '_${$root._nextId++}';
_innerAsyncQueue = $parent._innerAsyncQueue;
@@ -92,11 +141,12 @@ class Scope implements Map {
} else {
$parent._childHead = $parent._childTail = this;
}
+ _set$Properties();
}
_autoDigestOnTurnDone() {
- if (_skipAutoDigest) {
- _skipAutoDigest = false;
+ if ($root._skipAutoDigest) {
+ $root._skipAutoDigest = false;
} else {
$digest();
}
@@ -107,23 +157,27 @@ class Scope implements Map {
(a is String && b is String && a == b) ||
(a is num && b is num && a.isNaN && b.isNaN);
- containsKey(String name) => this[name] != null;
+ containsKey(String name) {
+ for (var scope = this; scope != null; scope = scope.$parent) {
+ if (scope._properties.containsKey(name)) {
+ return true;
+ } else if(scope._isolate) {
+ break;
+ }
+ }
+ return false;
+ }
+
remove(String name) => this._properties.remove(name);
operator []=(String name, value) => _properties[name] = value;
operator [](String name) {
- if (name == r'$id') return this.$id;
- if (name == r'$parent') return this.$parent;
- if (name == r'$root') return this.$root;
- var scope = this;
- do {
+ for (var scope = this; scope != null; scope = scope.$parent) {
if (scope._properties.containsKey(name)) {
return scope._properties[name];
- } else if (!scope._isolate) {
- scope = scope.$parent;
- } else {
- return null;
+ } else if(scope._isolate) {
+ break;
}
- } while(scope != null);
+ }
return null;
}
@@ -382,7 +436,7 @@ class Scope implements Map {
* auto-digesting scope.
*/
$$verifyDigestWillRun() {
- assert(!_skipAutoDigest);
+ assert(!$root._skipAutoDigest);
_zone.assertInTurn();
}
@@ -398,6 +452,21 @@ class Scope implements Map {
this._disabled = false;
}
+ /**
+ * Processes all of the watchers of the current scope and its children.
+ * Because a watcher's listener can change the model, the `$digest()` operation keeps calling
+ * the watchers no further response data has changed. This means that it is possible to get
+ * into an infinite loop. This function will throw `'Maximum iteration limit exceeded.'`
+ * if the number of iterations exceeds 10.
+ *
+ * There should really be no need to call $digest() in production code since everything is
+ * handled behind the scenes with zones and object mutation events. However, in testing
+ * both $digest and [$apply] are useful to control state and simulate the scope life cycle in
+ * a step-by-step manner.
+ *
+ * Refer to [$watch], [$watchSet] or [$watchCollection] to see how to register watchers that
+ * are executed during the digest cycle.
+ */
$digest() {
try {
_beginPhase('\$digest');
@@ -589,6 +658,21 @@ class Scope implements Map {
}
+ /**
+ * Removes the current scope (and all of its children) from the parent scope. Removal implies
+ * that calls to $digest() will no longer propagate to the current scope and its children.
+ * Removal also implies that the current scope is eligible for garbage collection.
+ *
+ * The `$destroy()` operation is usually used within directives that perform transclusion on
+ * multiple child elements (like ngRepeat) which create multiple child scopes.
+ *
+ * Just before a scope is destroyed, a `$destroy` event is broadcasted on this scope. This is
+ * a great way for child scopes (such as shared directives or controllers) to detect to and
+ * perform any necessary cleanup before the scope is removed from the application.
+ *
+ * Note that, in AngularDart, there is also a `$destroy` jQuery DOM event, which can be used to
+ * clean up DOM bindings before an element is removed from the DOM.
+ */
$destroy() {
if ($root == this) return; // we can't remove the root node;
@@ -601,11 +685,32 @@ class Scope implements Map {
}
+ /**
+ * Evaluates the expression against the current scope and returns the result. Note that, the
+ * expression data is relative to the data within the scope. Therefore an expression such as
+ * `a + b` will deference variables `a` and `b` and return a result so long as `a` and `b`
+ * exist on the scope.
+ *
+ * * [expr] - The expression that will be evaluated. This can be both a Function or a String.
+ * * [locals] - An optional Map of key/value data that will override any matching scope members
+ * for the purposes of the evaluation.
+ */
$eval(expr, [locals]) {
return relaxFnArgs(_compileToFn(expr))(locals == null ? this : new ScopeLocals(this, locals));
}
+ /**
+ * Evaluates the expression against the current scope at a later point in time. The $evalAsync
+ * operation may not get run right away (depending if an existing digest cycle is going on) and
+ * may therefore be issued later on (by a follow-up digest cycle). Note that at least one digest
+ * cycle will be performed after the expression is evaluated. However, If triggering an additional
+ * digest cycle is not desired then this can be avoided by placing `{outsideDigest: true}` as
+ * the 2nd parameter to the function.
+ *
+ * * [expr] - The expression that will be evaluated. This can be both a Function or a String.
+ * * [outsideDigest] - Whether or not to trigger a follow-up digest after evaluation.
+ */
$evalAsync(expr, {outsideDigest: false}) {
if (outsideDigest) {
_outerAsyncQueue.add(expr);
@@ -621,12 +726,12 @@ class Scope implements Map {
* you just scheduled or are otherwise certain of an impending VM turn and the
* digest at the end of that turn is sufficient. You should be able to answer
* "No" to the question "Is there any other code that is aware that this VM
- * turn occured and therefore expected a digest?". If your answer is "Yes",
+ * turn occurred and therefore expected a digest?". If your answer is "Yes",
* then you run the risk that the very next VM turn is not for your event and
* now that other code runs in that turn and sees stale values.
*
* You might call this function, for instance, from an event listener where,
- * though the event occured, you need to wait for another event before you can
+ * though the event occurred, you need to wait for another event before you can
* perform something meaningful. You might schedule that other event,
* set a flag for the handler of the other event to recognize, etc. and then
* call this method to skip the digest this cycle. Note that you should call
@@ -636,10 +741,20 @@ class Scope implements Map {
*/
$skipAutoDigest() {
_zone.assertInTurn();
- _skipAutoDigest = true;
+ $root._skipAutoDigest = true;
}
+ /**
+ * Triggers a digest operation much like [$digest] does, however, also accepts an
+ * optional expression to evaluate alongside the digest operation. The result of that
+ * expression will be returned afterwards. Much like with $digest, $apply should only be
+ * used within unit tests to simulate the life cycle of a scope. See [$digest] to learn
+ * more.
+ *
+ * * [expr] - optional expression which will be evaluated after the digest is performed. See [$eval]
+ * to learn more about expressions.
+ */
$apply([expr]) {
return _zone.run(() {
var timerId;
@@ -655,6 +770,23 @@ class Scope implements Map {
}
+ /**
+ * Registers a scope-based event listener to intercept events triggered by
+ * [$broadcast] (from any parent scopes) or [$emit] (from child scopes) that
+ * match the given event name. $on accepts two arguments:
+ *
+ * * [name] - Refers to the event name that the scope will listen on.
+ * * [listener] - Refers to the callback function which is executed when the event
+ * is intercepted.
+ *
+ *
+ * When the listener function is executed, an instance of [ScopeEvent] will be passed
+ * as the first parameter to the function.
+ *
+ * Any additional parameters available within the listener callback function are those that
+ * are set by the $broadcast or $emit scope methods (which are set by the origin scope which
+ * is the scope that first triggered the scope event).
+ */
$on(name, listener) {
var namedListeners = _listeners[name];
if (!_listeners.containsKey(name)) {
@@ -668,6 +800,16 @@ class Scope implements Map {
}
+ /**
+ * Triggers a scope event referenced by the [name] parameters upwards towards the root of the
+ * scope tree. If intercepted, by a parent scope containing a matching scope event listener
+ * (which is registered via the [$on] scope method), then the event listener callback function
+ * will be executed.
+ *
+ * * [name] - The scope event name that will be triggered.
+ * * [args] - An optional list of arguments that will be fed into the listener callback function
+ * for any event listeners that are registered via [$on].
+ */
$emit(name, [List args]) {
var empty = [],
namedListeners,
@@ -702,6 +844,16 @@ class Scope implements Map {
}
+ /**
+ * Triggers a scope event referenced by the [name] parameters dowards towards the leaf nodes of the
+ * scope tree. If intercepted, by a child scope containing a matching scope event listener
+ * (which is registered via the [$on] scope method), then the event listener callback function
+ * will be executed.
+ *
+ * * [name] - The scope event name that will be triggered.
+ * * [listenerArgs] - An optional list of arguments that will be fed into the listener callback function
+ * for any event listeners that are registered via [$on].
+ */
$broadcast(String name, [List listenerArgs]) {
var target = this,
current = target,
@@ -767,7 +919,8 @@ class Scope implements Map {
if (exp == null) {
return () => null;
} else if (exp is String) {
- return _parser(exp).eval;
+ Expression expression = _parser(exp);
+ return expression.eval;
} else if (exp is Function) {
return exp;
} else {
@@ -858,7 +1011,9 @@ _toJson(obj) {
// work-around dartbug.com/14130
try {
ret = mirror.function.source;
- } on NoSuchMethodError catch (e) {}
+ } on NoSuchMethodError catch (e) {
+ } on UnimplementedError catch (e) {
+ }
}
return true;
})());
« 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