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

Unified Diff: pkg/polymer/lib/src/declaration.dart

Issue 132403010: big update to observe, template_binding, polymer (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
Index: pkg/polymer/lib/src/declaration.dart
diff --git a/pkg/polymer/lib/src/declaration.dart b/pkg/polymer/lib/src/declaration.dart
index 7eaf11a1a8bc19f5885ca6910398ec3eaf9e3ab2..8e14b058cb71d521f745a35a1dcfcd817355c119 100644
--- a/pkg/polymer/lib/src/declaration.dart
+++ b/pkg/polymer/lib/src/declaration.dart
@@ -41,23 +41,29 @@ class PolymerDeclaration extends HtmlElement {
PolymerDeclaration _super;
PolymerDeclaration get superDeclaration => _super;
+ String _extendsName;
+
String _name;
String get name => _name;
/**
* Map of publish properties. Can be a [VariableMirror] or a [MethodMirror]
* representing a getter. If it is a getter, there will also be a setter.
+ *
+ * Note: technically these are always single properties, so we could use
+ * a Symbol instead of a PropertyPath. However there are lookups between
+ * this map and [_observe] so it is easier to just track paths.
*/
- Map<Symbol, DeclarationMirror> _publish;
+ Map<PropertyPath, DeclarationMirror> _publish;
/** The names of published properties for this polymer-element. */
- Iterable<Symbol> get publishedProperties =>
- _publish != null ? _publish.keys : const [];
+ Iterable<String> get publishedProperties =>
+ _publish != null ? _publish.keys.map((p) => '$p') : const [];
/** Same as [_publish] but with lower case names. */
Map<String, DeclarationMirror> _publishLC;
- Map<Symbol, Symbol> _observe;
+ Map<PropertyPath, Symbol> _observe;
Map<String, Object> _instanceAttributes;
@@ -83,6 +89,8 @@ class PolymerDeclaration extends HtmlElement {
PolymerDeclaration.created() : super.created() {
// fetch the element name
_name = attributes['name'];
+ // fetch our extendee name
+ _extendsName = attributes['extends'];
// install element definition, if ready
registerWhenReady();
}
@@ -92,9 +100,7 @@ class PolymerDeclaration extends HtmlElement {
if (waitingForType(name)) {
return;
}
- // fetch our extendee name
- var extendee = attributes['extends'];
- if (waitingForExtendee(extendee)) {
+ if (waitingForExtendee(_extendsName)) {
//console.warn(name + ': waitingForExtendee:' + extendee);
return;
}
@@ -106,7 +112,7 @@ class PolymerDeclaration extends HtmlElement {
// finalizing elements in the main document
// TODO(jmesserly): Polymer.dart waits for HTMLImportsLoaded, so I've
// removed "whenImportsLoaded" for now. Restore the workaround if needed.
- _register(extendee);
+ _register(_extendsName);
}
void _register(extendee) {
@@ -188,10 +194,13 @@ class PolymerDeclaration extends HtmlElement {
// transcribe `attributes` declarations onto own prototype's `publish`
publishAttributes(cls, _super);
- publishProperties(type);
+ publishProperties(_type);
inferObservers(cls);
+ // desugar compound observer syntax, e.g. @ObserveProperty('a b c')
+ explodeObservers(cls);
+
// Skip the rest in Dart:
// chain various meta-data objects to inherited versions
// chain custom api to inherited
@@ -209,6 +218,8 @@ class PolymerDeclaration extends HtmlElement {
// install external stylesheets as if they are inline
installSheets();
+ adjustShadowElement();
+
// TODO(sorvell): install a helper method this.resolvePath to aid in
// setting resource paths. e.g.
// this.$.image.src = this.resolvePath('images/foo.png')
@@ -231,6 +242,22 @@ class PolymerDeclaration extends HtmlElement {
}
}
+ // TODO(sorvell): remove when spec addressed:
+ // https://www.w3.org/Bugs/Public/show_bug.cgi?id=22460
+ // make <shadow></shadow> be <shadow><content></content></shadow>
+ void adjustShadowElement() {
+ // TODO(sorvell): avoid under SD polyfill until this bug is addressed:
+ // https://github.com/Polymer/ShadowDOM/issues/297
+ if (!_hasShadowDomPolyfill) {
+ final content = templateContent;
+ if (content == null) return;
+
+ for (var s in content.querySelectorAll('shadow')) {
+ if (s.nodes.isEmpty) s.append(new ContentElement());
+ }
+ }
+ }
+
void registerType(String name) {
var baseTag;
var decl = this;
@@ -257,16 +284,19 @@ class PolymerDeclaration extends HtmlElement {
if (attrs != null) {
// names='a b c' or names='a,b,c'
// record each name for publishing
- for (var attr in attrs.split(attrs.contains(',') ? ',' : ' ')) {
+ for (var attr in attrs.split(_ATTRIBUTES_REGEX)) {
// remove excess ws
attr = attr.trim();
// do not override explicit entries
- if (attr != '' && _publish != null && _publish.containsKey(attr)) {
+ if (attr == '') continue;
+
+ var property = new Symbol(attr);
+ var path = new PropertyPath([property]);
+ if (_publish != null && _publish.containsKey(path)) {
continue;
}
- var property = new Symbol(attr);
var mirror = _getProperty(cls, property);
if (mirror == null) {
window.console.warn('property for attribute $attr of polymer-element '
@@ -274,7 +304,7 @@ class PolymerDeclaration extends HtmlElement {
continue;
}
if (_publish == null) _publish = {};
- _publish[property] = mirror;
+ _publish[path] = mirror;
}
}
@@ -378,7 +408,7 @@ class PolymerDeclaration extends HtmlElement {
var nodes = this.querySelectorAll(selector).toList();
var content = templateContent;
if (content != null) {
- nodes = nodes..addAll(content.queryAll(selector));
+ nodes = nodes..addAll(content.querySelectorAll(selector));
}
if (matcher != null) return nodes.where(matcher).toList();
return nodes;
@@ -408,7 +438,7 @@ class PolymerDeclaration extends HtmlElement {
}
// handle cached style elements
for (var style in styles.where(matcher)) {
- cssText..write(style.textContent)..write('\n\n');
Siggi Cherem (dart-lang) 2014/02/03 22:52:48 was this just broken before :/?
Jennifer Messerly 2014/02/04 00:33:06 apparently, yes :)
+ cssText..write(style.text)..write('\n\n');
}
return cssText.toString();
}
@@ -430,11 +460,8 @@ class PolymerDeclaration extends HtmlElement {
* fetch a list of all observable properties names in our inheritance chain
* above Polymer.
*/
- // TODO(sjmiles): perf: reflection is slow, relatively speaking
- // If an element may take 6us to create, getCustomPropertyNames might
- // cost 1.6us more.
void inferObservers(ClassMirror cls) {
- if (cls == _objectType) return;
+ if (cls == _htmlElementType) return;
inferObservers(cls.superclass);
for (var method in cls.declarations.values) {
if (method is! MethodMirror || method.isStatic
@@ -442,22 +469,43 @@ class PolymerDeclaration extends HtmlElement {
String name = MirrorSystem.getName(method.simpleName);
if (name.endsWith(_OBSERVE_SUFFIX) && name != 'attributeChanged') {
- if (_observe == null) _observe = new Map();
+ // TODO(jmesserly): now that we have a better system, should we
+ // deprecate *Changed methods?
+ if (_observe == null) _observe = new HashMap();
name = name.substring(0, name.length - 7);
- _observe[new Symbol(name)] = method.simpleName;
+ _observe[new PropertyPath(name)] = method.simpleName;
}
}
}
+ void explodeObservers(ClassMirror cls) {
Siggi Cherem (dart-lang) 2014/02/03 22:52:48 nit: consider adding a short doc here to point to
Jennifer Messerly 2014/02/04 00:33:06 sure. wish polymer-js would doc these :|
+ if (cls == _htmlElementType) return;
+
+ explodeObservers(cls.superclass);
+ for (var method in cls.declarations.values) {
+ if (method is! MethodMirror || method.isStatic
+ || !method.isRegularMethod) continue;
+
+ for (var meta in _safeGetMetadata(method)) {
+ if (meta.reflectee is! ObserveProperty) continue;
+
+ if (_observe == null) _observe = new HashMap();
+
+ for (String name in meta.reflectee.names) {
+ _observe[new PropertyPath(name)] = method.simpleName;
Siggi Cherem (dart-lang) 2014/02/03 22:52:48 what if 2 methods react on the same path? @Observ
Jennifer Messerly 2014/02/04 00:33:06 good catch. JS doesn't support this. Added support
+ }
+ }
+ }
+ }
void publishProperties(Type type) {
Siggi Cherem (dart-lang) 2014/02/03 22:52:48 nit: + empty line above
Jennifer Messerly 2014/02/04 00:33:06 Done.
// Dart note: _publish was already populated by publishAttributes
if (_publish != null) _publishLC = _lowerCaseMap(_publish);
}
- Map<String, dynamic> _lowerCaseMap(Map<Symbol, dynamic> properties) {
+ Map<String, dynamic> _lowerCaseMap(Map<PropertyPath, dynamic> properties) {
final map = new Map<String, dynamic>();
properties.forEach((name, value) {
- map[MirrorSystem.getName(name).toLowerCase()] = value;
+ map['$name'.toLowerCase()] = value;
Siggi Cherem (dart-lang) 2014/02/03 22:52:48 '$name' -> name ? or is this to protect from key b
Jennifer Messerly 2014/02/04 00:33:06 name is a PropertyPath, not a String. Clarified.
});
return map;
}
@@ -495,10 +543,10 @@ bool _isRegistered(String name) => _declarations.containsKey(name);
PolymerDeclaration _getDeclaration(String name) => _declarations[name];
final _objectType = reflectClass(Object);
-
+final _htmlElementType = reflectClass(HtmlElement);
Map _getPublishedProperties(ClassMirror cls, Map props) {
- if (cls == _objectType) return props;
+ if (cls == _htmlElementType) return props;
props = _getPublishedProperties(cls.superclass, props);
for (var member in cls.declarations.values) {
if (member.isStatic || member.isPrivate) continue;
@@ -512,7 +560,7 @@ Map _getPublishedProperties(ClassMirror cls, Map props) {
// it's a tad expensive.
if (member is! MethodMirror || _hasSetter(cls, member)) {
if (props == null) props = {};
- props[member.simpleName] = member;
+ props[new PropertyPath([member.simpleName])] = member;
}
break;
}
@@ -545,6 +593,19 @@ DeclarationMirror _getProperty(ClassMirror cls, Symbol property) {
return null;
}
+List _safeGetMetadata(MethodMirror method) {
+ // TODO(jmesserly): dart2js blows up getting metadata from methods in some
+ // cases. Why does this happen? It seems like the culprit might be named
+ // arguments. Unfortunately even calling method.parameters also
+ // triggers the bug in computeFunctionRti. For now we guard against it
+ // with this check.
+ try {
+ return method.metadata;
+ } catch (e) {
+ return [];
+ }
+}
+
bool _hasSetter(ClassMirror cls, MethodMirror getter) {
var setterName = new Symbol('${MirrorSystem.getName(getter.simpleName)}=');
var mirror = cls.declarations[setterName];
@@ -565,8 +626,7 @@ String _removeEventPrefix(String name) => name.substring(_EVENT_PREFIX.length);
*/
void _shimShadowDomStyling(DocumentFragment template, String name,
String extendee) {
- if (js.context == null || template == null) return;
- if (!js.context.hasProperty('ShadowDOMPolyfill')) return;
+ if (template == null || !_hasShadowDomPolyfill) return;
var platform = js.context['Platform'];
if (platform == null) return;
@@ -575,6 +635,9 @@ void _shimShadowDomStyling(DocumentFragment template, String name,
shadowCss.callMethod('shimStyling', [template, name, extendee]);
}
+final bool _hasShadowDomPolyfill = js.context != null &&
+ js.context.hasProperty('ShadowDOMPolyfill');
+
const _STYLE_SELECTOR = 'style';
const _SHEET_SELECTOR = '[rel=stylesheet]';
const _STYLE_GLOBAL_SCOPE = 'global';
@@ -627,6 +690,7 @@ final _eventTranslations = const {
'domfocusout': 'DOMFocusOut',
'domfocusin': 'DOMFocusIn',
+ 'dommousescroll': 'DOMMouseScroll',
// TODO(jmesserly): Dart specific renames. Reconcile with Polymer.js
'animationend': 'webkitAnimationEnd',
@@ -657,3 +721,5 @@ String _eventNameFromType(String eventType) {
final result = _reverseEventTranslations[eventType];
return result != null ? result : eventType;
}
+
+final _ATTRIBUTES_REGEX = new RegExp(r'\s|,');

Powered by Google App Engine
This is Rietveld 408576698