| Index: pkg/polymer/lib/src/instance.dart
|
| diff --git a/pkg/polymer/lib/src/instance.dart b/pkg/polymer/lib/src/instance.dart
|
| index dc99d48e4a653db049634b5e123a44796d6a1e37..094b5000c5b106db4919091c1f2cd08754395b3a 100644
|
| --- a/pkg/polymer/lib/src/instance.dart
|
| +++ b/pkg/polymer/lib/src/instance.dart
|
| @@ -363,32 +363,34 @@ abstract class Polymer implements Element, Observable, NodeBindExtension {
|
| void attributeToProperty(String name, String value) {
|
| // try to match this attribute to a property (attributes are
|
| // all lower-case, so this is case-insensitive search)
|
| - var property = propertyForAttribute(name);
|
| - if (property == null) return;
|
| + var decl = propertyForAttribute(name);
|
| + if (decl == null) return;
|
|
|
| // filter out 'mustached' values, these are to be
|
| // replaced with bound-data and are not yet values
|
| // themselves.
|
| if (value == null || value.contains(Polymer.bindPattern)) return;
|
|
|
| - // get original value
|
| - final self = reflect(this);
|
| - final currentValue = self.getField(property.simpleName).reflectee;
|
| + final currentValue = smoke.read(this, decl.name);
|
|
|
| // deserialize Boolean or Number values from attribute
|
| - final newValue = deserializeValue(value, currentValue,
|
| - _inferPropertyType(currentValue, property));
|
| + var type = decl.type;
|
| + if ((type == Object || type == dynamic) && currentValue != null) {
|
| + // Attempt to infer field type from the current value.
|
| + type = currentValue.runtimeType;
|
| + }
|
| + final newValue = deserializeValue(value, currentValue, type);
|
|
|
| // only act if the value has changed
|
| if (!identical(newValue, currentValue)) {
|
| // install new value (has side-effects)
|
| - self.setField(property.simpleName, newValue);
|
| + smoke.write(this, decl.name, newValue);
|
| }
|
| }
|
|
|
| /** Return the published property matching name, or null. */
|
| // TODO(jmesserly): should we just return Symbol here?
|
| - DeclarationMirror propertyForAttribute(String name) {
|
| + smoke.Declaration propertyForAttribute(String name) {
|
| final publishLC = _declaration._publishLC;
|
| if (publishLC == null) return null;
|
| //console.log('propertyForAttribute:', name, 'matches', match);
|
| @@ -398,10 +400,7 @@ abstract class Polymer implements Element, Observable, NodeBindExtension {
|
| /**
|
| * Convert representation of [value] based on [type] and [currentValue].
|
| */
|
| - // TODO(jmesserly): this should probably take a ClassMirror instead of
|
| - // TypeMirror, but it is currently impossible to get from a TypeMirror to a
|
| - // ClassMirror.
|
| - Object deserializeValue(String value, Object currentValue, TypeMirror type) =>
|
| + Object deserializeValue(String value, Object currentValue, Type type) =>
|
| deserialize.deserializeValue(value, currentValue, type);
|
|
|
| String serializeValue(Object value) {
|
| @@ -458,15 +457,15 @@ abstract class Polymer implements Element, Observable, NodeBindExtension {
|
| // property changes that occur as a result of binding will be observed.
|
| if (!_elementPrepared) prepareElement();
|
|
|
| - var property = propertyForAttribute(name);
|
| - if (property == null) {
|
| + var decl = propertyForAttribute(name);
|
| + if (decl == null) {
|
| // Cannot call super.bind because template_binding is its own package
|
| return nodeBindFallback(this).bind(name, bindable, oneTime: oneTime);
|
| } else {
|
| // clean out the closets
|
| unbind(name);
|
| // use n-way Polymer binding
|
| - var observer = bindProperty(property.simpleName, bindable);
|
| + var observer = bindProperty(decl.name, bindable);
|
|
|
| // reflect bound property to attribute when binding
|
| // to ensure binding is not left on attribute if property
|
| @@ -476,7 +475,7 @@ abstract class Polymer implements Element, Observable, NodeBindExtension {
|
|
|
| // TODO(jmesserly): polymer has the path_ in their observer object, should
|
| // we use that too instead of allocating it here?
|
| - reflectPropertyToAttribute(new PropertyPath([property.simpleName]));
|
| + reflectPropertyToAttribute(new PropertyPath([decl.name]));
|
| return bindings[name] = observer;
|
| }
|
| }
|
| @@ -598,7 +597,8 @@ abstract class Polymer implements Element, Observable, NodeBindExtension {
|
| // observes the value if it is an array
|
| observeArrayValue(path, newValue, oldValue);
|
| // Dart note: JS passes "arguments", so we pass along our args.
|
| - invokeMethod(method, [oldValue, newValue, newValues, oldValues, paths]);
|
| + smoke.invoke(this, method,
|
| + [oldValue, newValue, newValues, oldValues, paths], adjust: true);
|
| }
|
| });
|
| }
|
| @@ -628,7 +628,7 @@ abstract class Polymer implements Element, Observable, NodeBindExtension {
|
| }
|
| var sub = value.listChanges.listen((changes) {
|
| for (var callback in callbacks) {
|
| - invokeMethod(callback, [old]);
|
| + smoke.invoke(this, callback, [old], adjust: true);
|
| }
|
| });
|
| registerObserver('${name}__array', sub);
|
| @@ -761,9 +761,16 @@ abstract class Polymer implements Element, Observable, NodeBindExtension {
|
| if (log) _eventsLog.fine('>>> [$localName]: dispatch $callbackOrMethod');
|
|
|
| if (callbackOrMethod is Function) {
|
| + int maxArgs = smoke.maxArgs(callbackOrMethod);
|
| + if (maxArgs == -1) {
|
| + _eventsLog.warning(
|
| + 'invalid callback: expected callback of 0, 1, 2, or 3 arguments');
|
| + }
|
| + args.length = maxArgs;
|
| Function.apply(callbackOrMethod, args);
|
| } else if (callbackOrMethod is String) {
|
| - _invokeMethod(object, new Symbol(callbackOrMethod), args);
|
| + smoke.invoke(object, smoke.nameToSymbol(callbackOrMethod), args,
|
| + adjust: true);
|
| } else {
|
| _eventsLog.warning('invalid callback');
|
| }
|
| @@ -799,31 +806,7 @@ abstract class Polymer implements Element, Observable, NodeBindExtension {
|
|
|
| /** Call [methodName] method on this object with [args]. */
|
| invokeMethod(Symbol methodName, List args) =>
|
| - _invokeMethod(this, methodName, args);
|
| -
|
| - /** Call [methodName] method on [receiver] with [args]. */
|
| - static _invokeMethod(receiver, Symbol methodName, List args) {
|
| - // TODO(jmesserly): use function type tests instead of mirrors for dispatch.
|
| - var receiverMirror = reflect(receiver);
|
| - var method = _findMethod(receiverMirror.type, methodName);
|
| - if (method != null) {
|
| - // This will either truncate the argument list or extend it with extra
|
| - // null arguments, so it will match the signature.
|
| - // TODO(sigmund): consider accepting optional arguments when we can tell
|
| - // them appart from named arguments (see http://dartbug.com/11334)
|
| - args.length = method.parameters.where((p) => !p.isOptional).length;
|
| - }
|
| - return receiverMirror.invoke(methodName, args).reflectee;
|
| - }
|
| -
|
| - static MethodMirror _findMethod(ClassMirror type, Symbol name) {
|
| - do {
|
| - var member = type.declarations[name];
|
| - if (member is MethodMirror) return member;
|
| - type = type.superclass;
|
| - } while (type != null);
|
| - return null; // unreachable
|
| - }
|
| + smoke.invoke(this, methodName, args, adjust: true);
|
|
|
| /**
|
| * Invokes a function asynchronously.
|
| @@ -1002,28 +985,26 @@ abstract class Polymer implements Element, Observable, NodeBindExtension {
|
| // TODO(jmesserly): our approach leads to race conditions in the bindings.
|
| // See http://code.google.com/p/dart/issues/detail?id=13567
|
| class _PolymerBinding extends Bindable {
|
| - final InstanceMirror _target;
|
| + final Polymer _target;
|
| final Symbol _property;
|
| final Bindable _bindable;
|
| StreamSubscription _sub;
|
| Object _lastValue;
|
|
|
| - _PolymerBinding(Polymer node, this._property, this._bindable)
|
| - : _target = reflect(node) {
|
| -
|
| - _sub = node.changes.listen(_propertyValueChanged);
|
| + _PolymerBinding(this._target, this._property, this._bindable) {
|
| + _sub = _target.changes.listen(_propertyValueChanged);
|
| _updateNode(open(_updateNode));
|
| }
|
|
|
| void _updateNode(newValue) {
|
| _lastValue = newValue;
|
| - _target.setField(_property, newValue);
|
| + smoke.write(_target, _property, newValue);
|
| }
|
|
|
| void _propertyValueChanged(List<ChangeRecord> records) {
|
| for (var record in records) {
|
| if (record is PropertyChangeRecord && record.name == _property) {
|
| - final newValue = _target.getField(_property).reflectee;
|
| + final newValue = smoke.read(_target, _property);
|
| if (!identical(_lastValue, newValue)) {
|
| this.value = newValue;
|
| }
|
| @@ -1047,35 +1028,6 @@ class _PolymerBinding extends Bindable {
|
|
|
| bool _toBoolean(value) => null != value && false != value;
|
|
|
| -TypeMirror _propertyType(DeclarationMirror property) =>
|
| - property is VariableMirror ? property.type
|
| - : (property as MethodMirror).returnType;
|
| -
|
| -TypeMirror _inferPropertyType(Object value, DeclarationMirror property) {
|
| - var type = _propertyType(property);
|
| - if (type.qualifiedName == #dart.core.Object ||
|
| - type.qualifiedName == #dynamic) {
|
| - // Attempt to infer field type from the default value.
|
| - if (value != null) {
|
| - Type t = _getCoreType(value);
|
| - if (t != null) return reflectClass(t);
|
| - return reflect(value).type;
|
| - }
|
| - }
|
| - return type;
|
| -}
|
| -
|
| -Type _getCoreType(Object value) {
|
| - if (value == null) return Null;
|
| - if (value is int) return int;
|
| - // Avoid "is double" to prevent warning that it won't work in dart2js.
|
| - if (value is num) return double;
|
| - if (value is bool) return bool;
|
| - if (value is String) return String;
|
| - if (value is DateTime) return DateTime;
|
| - return null;
|
| -}
|
| -
|
| final Logger _observeLog = new Logger('polymer.observe');
|
| final Logger _eventsLog = new Logger('polymer.events');
|
| final Logger _unbindLog = new Logger('polymer.unbind');
|
| @@ -1156,4 +1108,4 @@ class _EventBindable extends Bindable {
|
| _sub = null;
|
| }
|
| }
|
| -}
|
| +}
|
|
|