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

Unified Diff: lib/templating.dart

Issue 5885170347409408: Add location information to watchers to make them more debuggable. (Closed) Base URL: git@github.com:dart-lang/web-ui.git@master
Patch Set: Created 7 years, 5 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 | « lib/src/compiler.dart ('k') | lib/testing/render_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/templating.dart
diff --git a/lib/templating.dart b/lib/templating.dart
index d6541fa4d4d0a3324b0b783cdc8dab3970be3163..8eb10382b9940da436ba1da96574c0d0a0ac9dc9 100644
--- a/lib/templating.dart
+++ b/lib/templating.dart
@@ -147,7 +147,8 @@ void changeCssClasses(elem, ChangeRecord change) {
* bindCssClasses(e, () => class1);
* bindCssClasses(e, () => class2);
*/
-ChangeUnobserver bindCssClasses(Element elem, dynamic exp()) {
+ChangeUnobserver bindCssClasses(Element elem, dynamic exp(),
+ [String debugLocation]) {
return watchAndInvoke(exp, (e) {
if (e.changes != null) {
for (var change in e.changes) changeCssClasses(elem, change);
@@ -155,13 +156,14 @@ ChangeUnobserver bindCssClasses(Element elem, dynamic exp()) {
updateCssClass(elem, false, e.oldValue);
updateCssClass(elem, true, e.newValue);
}
- }, 'css-class-bind');
+ }, 'css-class-bind', debugLocation);
}
/** Bind the result of [exp] to the style attribute in [elem]. */
-ChangeUnobserver bindStyle(Element elem, Map<String, String> exp()) {
+ChangeUnobserver bindStyle(Element elem, Map<String, String> exp(),
+ [String debugLocation]) {
return watchAndInvoke(exp, (e) => updateStyle(elem, e.oldValue, e.newValue),
- 'css-style-bind');
+ 'css-style-bind', debugLocation);
}
/**
@@ -249,22 +251,24 @@ class Listener extends TemplateItem {
}
}
-/** Represents a generic data binding and a corresponding action. */
-class Binding extends TemplateItem {
+/** Common logic for all bindings. */
+abstract class Binding extends TemplateItem {
final exp;
- final ChangeObserver action;
final bool isFinal;
+ final String debugLocation;
ChangeUnobserver stopper;
- Binding(this.exp, this.action, this.isFinal);
+ Binding(this.exp, this.isFinal)
+ : debugLocation = verboseDebugMessages && readCurrentStackTrace != null
+ ? readCurrentStackTrace() : null;
void insert() {
if (isFinal) {
- action(new ChangeNotification(null, exp()));
+ invokeCallback();
} else if (stopper != null) {
throw new StateError('binding already attached');
} else {
- stopper = watchAndInvoke(exp, action, 'generic-binding');
+ stopper = registerAndInvoke();
}
}
@@ -274,109 +278,81 @@ class Binding extends TemplateItem {
stopper = null;
}
}
+
+ /** Invokes the action associated with this binding. */
+ void invokeCallback();
+
+ /**
+ * Registers the watcher and invokes the action associated with this binding.
+ */
+ ChangeUnobserver registerAndInvoke();
+}
+
+/** Represents a generic data binding and a corresponding action. */
+class GenericBinding extends Binding {
+ final ChangeObserver action;
+
+ GenericBinding(exp, this.action, bool isFinal) : super(exp, isFinal);
+
+ void invokeCallback() => action(new ChangeNotification(null, exp()));
+
+ ChangeUnobserver registerAndInvoke() =>
+ watchAndInvoke(exp, action, 'generic-binding', debugLocation);
}
/** Represents a binding to a style attribute. */
-class StyleAttrBinding extends TemplateItem {
- final exp;
+class StyleAttrBinding extends Binding {
final Element elem;
- final bool isFinal;
- ChangeUnobserver stopper;
- StyleAttrBinding(this.elem, this.exp, this.isFinal);
+ StyleAttrBinding(this.elem, exp, bool isFinal) : super(exp, isFinal);
- void insert() {
- if (isFinal) {
- updateStyle(elem, null, exp());
- } else if (stopper != null) {
- throw new StateError('style binding already attached');
- } else {
- stopper = bindStyle(elem, exp);
- }
- }
+ void invokeCallback() => updateStyle(elem, null, exp());
- void remove() {
- if (!isFinal) {
- stopper();
- stopper = null;
- }
- }
+ ChangeUnobserver registerAndInvoke() => bindStyle(elem, exp, debugLocation);
}
/** Represents a binding to a class attribute. */
-class ClassAttrBinding extends TemplateItem {
+class ClassAttrBinding extends Binding {
final Element elem;
- final exp;
- final bool isFinal;
- ChangeUnobserver stopper;
- ClassAttrBinding(this.elem, this.exp, this.isFinal);
+ ClassAttrBinding(this.elem, exp, bool isFinal) : super(exp, isFinal);
- void insert() {
- if (isFinal) {
- updateCssClass(elem, true, exp());
- } else if (stopper != null) {
- throw new StateError('class binding already attached');
- } else {
- stopper = bindCssClasses(elem, exp);
- }
- }
+ void invokeCallback() => updateCssClass(elem, true, exp());
- void remove() {
- if (!isFinal) {
- stopper();
- stopper = null;
- }
- }
+ ChangeUnobserver registerAndInvoke() =>
+ bindCssClasses(elem, exp, debugLocation);
}
/**
* Represents a one-way binding between a dart getter expression and a DOM
* property, or conversely between a DOM property value and a dart property.
*/
-class DomPropertyBinding extends TemplateItem {
+class DomPropertyBinding extends Binding {
/** Value updated by this binding. */
final Setter setter;
/**
- * Getter that reads the value of the binding, either from a Dart expression
- * or from a DOM property (which is internally also a Dart expression).
- */
- final Getter getter;
-
- /**
* Whether this is a binding that assigns a DOM attribute accepting URL
* values. If so, the value assigned to the attribute needs to be sanitized.
*/
final bool isUrl;
- final bool isFinal;
-
- ChangeUnobserver stopper;
-
- DomPropertyBinding(this.getter, this.setter, this.isUrl, this.isFinal);
+ /**
+ * Creates a DOM property binding, where [getter] reads the value of the
+ * binding, either from a Dart expression or from a DOM property (which is
+ * internally also a Dart expression).
+ */
+ DomPropertyBinding(Getter getter, this.setter, this.isUrl, bool isFinal)
+ : super(getter, isFinal);
void _safeSetter(value) {
setter(isUrl ? sanitizeUri(value) : value);
}
+ void invokeCallback() => _safeSetter(exp());
- void insert() {
- if (isFinal) {
- _safeSetter(getter());
- } else if (stopper != null) {
- throw new StateError('data binding already attached.');
- } else {
- stopper = watchAndInvoke(getter, (e) => _safeSetter(e.newValue),
- 'dom-property-binding');
- }
- }
-
- void remove() {
- if (!isFinal) {
- stopper();
- stopper = null;
- }
- }
+ ChangeUnobserver registerAndInvoke() =>
+ watchAndInvoke(exp, (e) => _safeSetter(e.newValue),
+ 'dom-property-binding', debugLocation);
}
/** Represents a component added within a template. */
@@ -420,13 +396,13 @@ class Template extends TemplateItem {
/** Run [action] when [exp] changes (while this template is visible). */
void bind(exp, ChangeObserver action, bool isFinal) {
- children.add(new Binding(exp, action, isFinal));
+ children.add(new GenericBinding(exp, action, isFinal));
}
/** Create and bind a [Node] to [exp] while this template is visible. */
Node contentBind(Function exp, isFinal) {
var bindNode = new Text('');
- children.add(new Binding(() => '${exp()}', (e) {
+ children.add(new GenericBinding(() => '${exp()}', (e) {
bindNode = updateBinding(exp(), bindNode, e.newValue);
}, isFinal));
return bindNode;
« no previous file with comments | « lib/src/compiler.dart ('k') | lib/testing/render_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698