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

Side by Side 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, 10 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of polymer; 5 part of polymer;
6 6
7 /** 7 /**
8 * **Warning**: this class is experiental and subject to change. 8 * **Warning**: this class is experiental and subject to change.
9 * 9 *
10 * The implementation for the `polymer-element` element. 10 * The implementation for the `polymer-element` element.
(...skipping 23 matching lines...) Expand all
34 // TODO(jmesserly): this is a cache, because it's tricky in Dart to get from 34 // TODO(jmesserly): this is a cache, because it's tricky in Dart to get from
35 // Type -> Supertype. 35 // Type -> Supertype.
36 Type _supertype; 36 Type _supertype;
37 Type get supertype => _supertype; 37 Type get supertype => _supertype;
38 38
39 // TODO(jmesserly): this is also a cache, since we can't store .element on 39 // TODO(jmesserly): this is also a cache, since we can't store .element on
40 // each level of the __proto__ like JS does. 40 // each level of the __proto__ like JS does.
41 PolymerDeclaration _super; 41 PolymerDeclaration _super;
42 PolymerDeclaration get superDeclaration => _super; 42 PolymerDeclaration get superDeclaration => _super;
43 43
44 String _extendsName;
45
44 String _name; 46 String _name;
45 String get name => _name; 47 String get name => _name;
46 48
47 /** 49 /**
48 * Map of publish properties. Can be a [VariableMirror] or a [MethodMirror] 50 * Map of publish properties. Can be a [VariableMirror] or a [MethodMirror]
49 * representing a getter. If it is a getter, there will also be a setter. 51 * representing a getter. If it is a getter, there will also be a setter.
52 *
53 * Note: technically these are always single properties, so we could use
54 * a Symbol instead of a PropertyPath. However there are lookups between
55 * this map and [_observe] so it is easier to just track paths.
50 */ 56 */
51 Map<Symbol, DeclarationMirror> _publish; 57 Map<PropertyPath, DeclarationMirror> _publish;
52 58
53 /** The names of published properties for this polymer-element. */ 59 /** The names of published properties for this polymer-element. */
54 Iterable<Symbol> get publishedProperties => 60 Iterable<String> get publishedProperties =>
55 _publish != null ? _publish.keys : const []; 61 _publish != null ? _publish.keys.map((p) => '$p') : const [];
56 62
57 /** Same as [_publish] but with lower case names. */ 63 /** Same as [_publish] but with lower case names. */
58 Map<String, DeclarationMirror> _publishLC; 64 Map<String, DeclarationMirror> _publishLC;
59 65
60 Map<Symbol, Symbol> _observe; 66 Map<PropertyPath, Symbol> _observe;
61 67
62 Map<String, Object> _instanceAttributes; 68 Map<String, Object> _instanceAttributes;
63 69
64 List<Element> _sheets; 70 List<Element> _sheets;
65 List<Element> get sheets => _sheets; 71 List<Element> get sheets => _sheets;
66 72
67 List<Element> _styles; 73 List<Element> _styles;
68 List<Element> get styles => _styles; 74 List<Element> get styles => _styles;
69 75
70 DocumentFragment get templateContent { 76 DocumentFragment get templateContent {
71 final template = this.querySelector('template'); 77 final template = this.querySelector('template');
72 return template != null ? templateBind(template).content : null; 78 return template != null ? templateBind(template).content : null;
73 } 79 }
74 80
75 /** Maps event names and their associated method in the element class. */ 81 /** Maps event names and their associated method in the element class. */
76 final Map<String, String> _eventDelegates = {}; 82 final Map<String, String> _eventDelegates = {};
77 83
78 /** Expected events per element node. */ 84 /** Expected events per element node. */
79 // TODO(sigmund): investigate whether we need more than 1 set of local events 85 // TODO(sigmund): investigate whether we need more than 1 set of local events
80 // per element (why does the js implementation stores 1 per template node?) 86 // per element (why does the js implementation stores 1 per template node?)
81 Expando<Set<String>> _templateDelegates; 87 Expando<Set<String>> _templateDelegates;
82 88
83 PolymerDeclaration.created() : super.created() { 89 PolymerDeclaration.created() : super.created() {
84 // fetch the element name 90 // fetch the element name
85 _name = attributes['name']; 91 _name = attributes['name'];
92 // fetch our extendee name
93 _extendsName = attributes['extends'];
86 // install element definition, if ready 94 // install element definition, if ready
87 registerWhenReady(); 95 registerWhenReady();
88 } 96 }
89 97
90 void registerWhenReady() { 98 void registerWhenReady() {
91 // if we have no prototype, wait 99 // if we have no prototype, wait
92 if (waitingForType(name)) { 100 if (waitingForType(name)) {
93 return; 101 return;
94 } 102 }
95 // fetch our extendee name 103 if (waitingForExtendee(_extendsName)) {
96 var extendee = attributes['extends'];
97 if (waitingForExtendee(extendee)) {
98 //console.warn(name + ': waitingForExtendee:' + extendee); 104 //console.warn(name + ': waitingForExtendee:' + extendee);
99 return; 105 return;
100 } 106 }
101 // TODO(sjmiles): HTMLImports polyfill awareness: 107 // TODO(sjmiles): HTMLImports polyfill awareness:
102 // elements in the main document are likely to parse 108 // elements in the main document are likely to parse
103 // in advance of elements in imports because the 109 // in advance of elements in imports because the
104 // polyfill parser is simulated 110 // polyfill parser is simulated
105 // therefore, wait for imports loaded before 111 // therefore, wait for imports loaded before
106 // finalizing elements in the main document 112 // finalizing elements in the main document
107 // TODO(jmesserly): Polymer.dart waits for HTMLImportsLoaded, so I've 113 // TODO(jmesserly): Polymer.dart waits for HTMLImportsLoaded, so I've
108 // removed "whenImportsLoaded" for now. Restore the workaround if needed. 114 // removed "whenImportsLoaded" for now. Restore the workaround if needed.
109 _register(extendee); 115 _register(_extendsName);
110 } 116 }
111 117
112 void _register(extendee) { 118 void _register(extendee) {
113 //console.group('registering', name); 119 //console.group('registering', name);
114 register(name, extendee); 120 register(name, extendee);
115 //console.groupEnd(); 121 //console.groupEnd();
116 // subclasses may now register themselves 122 // subclasses may now register themselves
117 _notifySuper(name); 123 _notifySuper(name);
118 } 124 }
119 125
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 187
182 // get basal prototype 188 // get basal prototype
183 _supertype = _getRegisteredType(extendee); 189 _supertype = _getRegisteredType(extendee);
184 if (_supertype != null) _super = _getDeclaration(extendee); 190 if (_supertype != null) _super = _getDeclaration(extendee);
185 191
186 var cls = reflectClass(_type); 192 var cls = reflectClass(_type);
187 193
188 // transcribe `attributes` declarations onto own prototype's `publish` 194 // transcribe `attributes` declarations onto own prototype's `publish`
189 publishAttributes(cls, _super); 195 publishAttributes(cls, _super);
190 196
191 publishProperties(type); 197 publishProperties(_type);
192 198
193 inferObservers(cls); 199 inferObservers(cls);
194 200
201 // desugar compound observer syntax, e.g. @ObserveProperty('a b c')
202 explodeObservers(cls);
203
195 // Skip the rest in Dart: 204 // Skip the rest in Dart:
196 // chain various meta-data objects to inherited versions 205 // chain various meta-data objects to inherited versions
197 // chain custom api to inherited 206 // chain custom api to inherited
198 // build side-chained lists to optimize iterations 207 // build side-chained lists to optimize iterations
199 // inherit publishing meta-data 208 // inherit publishing meta-data
200 // x-platform fixup 209 // x-platform fixup
201 } 210 }
202 211
203 /** Implement various declarative features. */ 212 /** Implement various declarative features. */
204 void desugar(name, extendee) { 213 void desugar(name, extendee) {
205 // compile list of attributes to copy to instances 214 // compile list of attributes to copy to instances
206 accumulateInstanceAttributes(); 215 accumulateInstanceAttributes();
207 // parse on-* delegates declared on `this` element 216 // parse on-* delegates declared on `this` element
208 parseHostEvents(); 217 parseHostEvents();
209 // install external stylesheets as if they are inline 218 // install external stylesheets as if they are inline
210 installSheets(); 219 installSheets();
211 220
221 adjustShadowElement();
222
212 // TODO(sorvell): install a helper method this.resolvePath to aid in 223 // TODO(sorvell): install a helper method this.resolvePath to aid in
213 // setting resource paths. e.g. 224 // setting resource paths. e.g.
214 // this.$.image.src = this.resolvePath('images/foo.png') 225 // this.$.image.src = this.resolvePath('images/foo.png')
215 // Potentially remove when spec bug is addressed. 226 // Potentially remove when spec bug is addressed.
216 // https://www.w3.org/Bugs/Public/show_bug.cgi?id=21407 227 // https://www.w3.org/Bugs/Public/show_bug.cgi?id=21407
217 // TODO(jmesserly): resolvePath not ported, see first comment in this class. 228 // TODO(jmesserly): resolvePath not ported, see first comment in this class.
218 229
219 // under ShadowDOMPolyfill, transforms to approximate missing CSS features 230 // under ShadowDOMPolyfill, transforms to approximate missing CSS features
220 _shimShadowDomStyling(templateContent, name, extendee); 231 _shimShadowDomStyling(templateContent, name, extendee);
221 232
222 var cls = reflectClass(type); 233 var cls = reflectClass(type);
223 // TODO(jmesserly): this feels unnatrual in Dart. Since we have convenient 234 // TODO(jmesserly): this feels unnatrual in Dart. Since we have convenient
224 // lazy static initialization, can we get by without it? 235 // lazy static initialization, can we get by without it?
225 var registered = cls.declarations[#registerCallback]; 236 var registered = cls.declarations[#registerCallback];
226 if (registered != null && 237 if (registered != null &&
227 registered is MethodMirror && 238 registered is MethodMirror &&
228 registered.isStatic && 239 registered.isStatic &&
229 registered.isRegularMethod) { 240 registered.isRegularMethod) {
230 cls.invoke(#registerCallback, [this]); 241 cls.invoke(#registerCallback, [this]);
231 } 242 }
232 } 243 }
233 244
245 // TODO(sorvell): remove when spec addressed:
246 // https://www.w3.org/Bugs/Public/show_bug.cgi?id=22460
247 // make <shadow></shadow> be <shadow><content></content></shadow>
248 void adjustShadowElement() {
249 // TODO(sorvell): avoid under SD polyfill until this bug is addressed:
250 // https://github.com/Polymer/ShadowDOM/issues/297
251 if (!_hasShadowDomPolyfill) {
252 final content = templateContent;
253 if (content == null) return;
254
255 for (var s in content.querySelectorAll('shadow')) {
256 if (s.nodes.isEmpty) s.append(new ContentElement());
257 }
258 }
259 }
260
234 void registerType(String name) { 261 void registerType(String name) {
235 var baseTag; 262 var baseTag;
236 var decl = this; 263 var decl = this;
237 while (decl != null) { 264 while (decl != null) {
238 baseTag = decl.attributes['extends']; 265 baseTag = decl.attributes['extends'];
239 decl = decl.superDeclaration; 266 decl = decl.superDeclaration;
240 } 267 }
241 document.register(name, type, extendsTag: baseTag); 268 document.register(name, type, extendsTag: baseTag);
242 } 269 }
243 270
244 void publishAttributes(ClassMirror cls, PolymerDeclaration superDecl) { 271 void publishAttributes(ClassMirror cls, PolymerDeclaration superDecl) {
245 // get properties to publish 272 // get properties to publish
246 if (superDecl != null && superDecl._publish != null) { 273 if (superDecl != null && superDecl._publish != null) {
247 // Dart note: even though we walk the type hierarchy in 274 // Dart note: even though we walk the type hierarchy in
248 // _getPublishedProperties, this will additionally include any names 275 // _getPublishedProperties, this will additionally include any names
249 // published via the `attributes` attribute. 276 // published via the `attributes` attribute.
250 _publish = new Map.from(superDecl._publish); 277 _publish = new Map.from(superDecl._publish);
251 } 278 }
252 279
253 _publish = _getPublishedProperties(cls, _publish); 280 _publish = _getPublishedProperties(cls, _publish);
254 281
255 // merge names from 'attributes' attribute 282 // merge names from 'attributes' attribute
256 var attrs = attributes['attributes']; 283 var attrs = attributes['attributes'];
257 if (attrs != null) { 284 if (attrs != null) {
258 // names='a b c' or names='a,b,c' 285 // names='a b c' or names='a,b,c'
259 // record each name for publishing 286 // record each name for publishing
260 for (var attr in attrs.split(attrs.contains(',') ? ',' : ' ')) { 287 for (var attr in attrs.split(_ATTRIBUTES_REGEX)) {
261 // remove excess ws 288 // remove excess ws
262 attr = attr.trim(); 289 attr = attr.trim();
263 290
264 // do not override explicit entries 291 // do not override explicit entries
265 if (attr != '' && _publish != null && _publish.containsKey(attr)) { 292 if (attr == '') continue;
293
294 var property = new Symbol(attr);
295 var path = new PropertyPath([property]);
296 if (_publish != null && _publish.containsKey(path)) {
266 continue; 297 continue;
267 } 298 }
268 299
269 var property = new Symbol(attr);
270 var mirror = _getProperty(cls, property); 300 var mirror = _getProperty(cls, property);
271 if (mirror == null) { 301 if (mirror == null) {
272 window.console.warn('property for attribute $attr of polymer-element ' 302 window.console.warn('property for attribute $attr of polymer-element '
273 'name=$name not found.'); 303 'name=$name not found.');
274 continue; 304 continue;
275 } 305 }
276 if (_publish == null) _publish = {}; 306 if (_publish == null) _publish = {};
277 _publish[property] = mirror; 307 _publish[path] = mirror;
278 } 308 }
279 } 309 }
280 310
281 // NOTE: the following is not possible in Dart; fields must be declared. 311 // NOTE: the following is not possible in Dart; fields must be declared.
282 // install 'attributes' as properties on the prototype, 312 // install 'attributes' as properties on the prototype,
283 // but don't override 313 // but don't override
284 } 314 }
285 315
286 void accumulateInstanceAttributes() { 316 void accumulateInstanceAttributes() {
287 // inherit instance attributes 317 // inherit instance attributes
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 new StyleElement()..text = '$cssText', 401 new StyleElement()..text = '$cssText',
372 content.firstChild); 402 content.firstChild);
373 } 403 }
374 } 404 }
375 } 405 }
376 406
377 List<Element> findNodes(String selector, [bool matcher(Element e)]) { 407 List<Element> findNodes(String selector, [bool matcher(Element e)]) {
378 var nodes = this.querySelectorAll(selector).toList(); 408 var nodes = this.querySelectorAll(selector).toList();
379 var content = templateContent; 409 var content = templateContent;
380 if (content != null) { 410 if (content != null) {
381 nodes = nodes..addAll(content.queryAll(selector)); 411 nodes = nodes..addAll(content.querySelectorAll(selector));
382 } 412 }
383 if (matcher != null) return nodes.where(matcher).toList(); 413 if (matcher != null) return nodes.where(matcher).toList();
384 return nodes; 414 return nodes;
385 } 415 }
386 416
387 /** 417 /**
388 * Promotes external stylesheets and style elements with the attribute 418 * Promotes external stylesheets and style elements with the attribute
389 * polymer-scope='global' into global scope. 419 * polymer-scope='global' into global scope.
390 * This is particularly useful for defining @keyframe rules which 420 * This is particularly useful for defining @keyframe rules which
391 * currently do not function in scoped or shadow style elements. 421 * currently do not function in scoped or shadow style elements.
392 * (See wkb.ug/72462) 422 * (See wkb.ug/72462)
393 */ 423 */
394 // TODO(sorvell): remove when wkb.ug/72462 is addressed. 424 // TODO(sorvell): remove when wkb.ug/72462 is addressed.
395 void installGlobalStyles() { 425 void installGlobalStyles() {
396 var style = styleForScope(_STYLE_GLOBAL_SCOPE); 426 var style = styleForScope(_STYLE_GLOBAL_SCOPE);
397 Polymer.applyStyleToScope(style, document.head); 427 Polymer.applyStyleToScope(style, document.head);
398 } 428 }
399 429
400 String cssTextForScope(String scopeDescriptor) { 430 String cssTextForScope(String scopeDescriptor) {
401 var cssText = new StringBuffer(); 431 var cssText = new StringBuffer();
402 // handle stylesheets 432 // handle stylesheets
403 var selector = '[$_SCOPE_ATTR=$scopeDescriptor]'; 433 var selector = '[$_SCOPE_ATTR=$scopeDescriptor]';
404 matcher(s) => s.matches(selector); 434 matcher(s) => s.matches(selector);
405 435
406 for (var sheet in sheets.where(matcher)) { 436 for (var sheet in sheets.where(matcher)) {
407 cssText..write(_cssTextFromSheet(sheet))..write('\n\n'); 437 cssText..write(_cssTextFromSheet(sheet))..write('\n\n');
408 } 438 }
409 // handle cached style elements 439 // handle cached style elements
410 for (var style in styles.where(matcher)) { 440 for (var style in styles.where(matcher)) {
411 cssText..write(style.textContent)..write('\n\n'); 441 cssText..write(style.text)..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 :)
412 } 442 }
413 return cssText.toString(); 443 return cssText.toString();
414 } 444 }
415 445
416 StyleElement styleForScope(String scopeDescriptor) { 446 StyleElement styleForScope(String scopeDescriptor) {
417 var cssText = cssTextForScope(scopeDescriptor); 447 var cssText = cssTextForScope(scopeDescriptor);
418 return cssTextToScopeStyle(cssText, scopeDescriptor); 448 return cssTextToScopeStyle(cssText, scopeDescriptor);
419 } 449 }
420 450
421 StyleElement cssTextToScopeStyle(String cssText, String scopeDescriptor) { 451 StyleElement cssTextToScopeStyle(String cssText, String scopeDescriptor) {
422 if (cssText == '') return null; 452 if (cssText == '') return null;
423 453
424 return new StyleElement() 454 return new StyleElement()
425 ..text = cssText 455 ..text = cssText
426 ..attributes[_STYLE_SCOPE_ATTRIBUTE] = '$name-$scopeDescriptor'; 456 ..attributes[_STYLE_SCOPE_ATTRIBUTE] = '$name-$scopeDescriptor';
427 } 457 }
428 458
429 /** 459 /**
430 * fetch a list of all observable properties names in our inheritance chain 460 * fetch a list of all observable properties names in our inheritance chain
431 * above Polymer. 461 * above Polymer.
432 */ 462 */
433 // TODO(sjmiles): perf: reflection is slow, relatively speaking
434 // If an element may take 6us to create, getCustomPropertyNames might
435 // cost 1.6us more.
436 void inferObservers(ClassMirror cls) { 463 void inferObservers(ClassMirror cls) {
437 if (cls == _objectType) return; 464 if (cls == _htmlElementType) return;
438 inferObservers(cls.superclass); 465 inferObservers(cls.superclass);
439 for (var method in cls.declarations.values) { 466 for (var method in cls.declarations.values) {
440 if (method is! MethodMirror || method.isStatic 467 if (method is! MethodMirror || method.isStatic
441 || !method.isRegularMethod) continue; 468 || !method.isRegularMethod) continue;
442 469
443 String name = MirrorSystem.getName(method.simpleName); 470 String name = MirrorSystem.getName(method.simpleName);
444 if (name.endsWith(_OBSERVE_SUFFIX) && name != 'attributeChanged') { 471 if (name.endsWith(_OBSERVE_SUFFIX) && name != 'attributeChanged') {
445 if (_observe == null) _observe = new Map(); 472 // TODO(jmesserly): now that we have a better system, should we
473 // deprecate *Changed methods?
474 if (_observe == null) _observe = new HashMap();
446 name = name.substring(0, name.length - 7); 475 name = name.substring(0, name.length - 7);
447 _observe[new Symbol(name)] = method.simpleName; 476 _observe[new PropertyPath(name)] = method.simpleName;
448 } 477 }
449 } 478 }
450 } 479 }
451 480
481 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 :|
482 if (cls == _htmlElementType) return;
483
484 explodeObservers(cls.superclass);
485 for (var method in cls.declarations.values) {
486 if (method is! MethodMirror || method.isStatic
487 || !method.isRegularMethod) continue;
488
489 for (var meta in _safeGetMetadata(method)) {
490 if (meta.reflectee is! ObserveProperty) continue;
491
492 if (_observe == null) _observe = new HashMap();
493
494 for (String name in meta.reflectee.names) {
495 _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
496 }
497 }
498 }
499 }
452 void publishProperties(Type type) { 500 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.
453 // Dart note: _publish was already populated by publishAttributes 501 // Dart note: _publish was already populated by publishAttributes
454 if (_publish != null) _publishLC = _lowerCaseMap(_publish); 502 if (_publish != null) _publishLC = _lowerCaseMap(_publish);
455 } 503 }
456 504
457 Map<String, dynamic> _lowerCaseMap(Map<Symbol, dynamic> properties) { 505 Map<String, dynamic> _lowerCaseMap(Map<PropertyPath, dynamic> properties) {
458 final map = new Map<String, dynamic>(); 506 final map = new Map<String, dynamic>();
459 properties.forEach((name, value) { 507 properties.forEach((name, value) {
460 map[MirrorSystem.getName(name).toLowerCase()] = value; 508 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.
461 }); 509 });
462 return map; 510 return map;
463 } 511 }
464 } 512 }
465 513
466 /// maps tag names to prototypes 514 /// maps tag names to prototypes
467 final Map _typesByName = new Map<String, Type>(); 515 final Map _typesByName = new Map<String, Type>();
468 516
469 Type _getRegisteredType(String name) => _typesByName[name]; 517 Type _getRegisteredType(String name) => _typesByName[name];
470 518
(...skipping 17 matching lines...) Expand all
488 } 536 }
489 } 537 }
490 538
491 /// track document.register'ed tag names and their declarations 539 /// track document.register'ed tag names and their declarations
492 final Map _declarations = new Map<String, PolymerDeclaration>(); 540 final Map _declarations = new Map<String, PolymerDeclaration>();
493 541
494 bool _isRegistered(String name) => _declarations.containsKey(name); 542 bool _isRegistered(String name) => _declarations.containsKey(name);
495 PolymerDeclaration _getDeclaration(String name) => _declarations[name]; 543 PolymerDeclaration _getDeclaration(String name) => _declarations[name];
496 544
497 final _objectType = reflectClass(Object); 545 final _objectType = reflectClass(Object);
498 546 final _htmlElementType = reflectClass(HtmlElement);
499 547
500 Map _getPublishedProperties(ClassMirror cls, Map props) { 548 Map _getPublishedProperties(ClassMirror cls, Map props) {
501 if (cls == _objectType) return props; 549 if (cls == _htmlElementType) return props;
502 props = _getPublishedProperties(cls.superclass, props); 550 props = _getPublishedProperties(cls.superclass, props);
503 for (var member in cls.declarations.values) { 551 for (var member in cls.declarations.values) {
504 if (member.isStatic || member.isPrivate) continue; 552 if (member.isStatic || member.isPrivate) continue;
505 553
506 if (member is VariableMirror && !member.isFinal 554 if (member is VariableMirror && !member.isFinal
507 || member is MethodMirror && member.isGetter) { 555 || member is MethodMirror && member.isGetter) {
508 556
509 for (var meta in member.metadata) { 557 for (var meta in member.metadata) {
510 if (meta.reflectee is PublishedProperty) { 558 if (meta.reflectee is PublishedProperty) {
511 // Note: we delay the setter check until we find @published because 559 // Note: we delay the setter check until we find @published because
512 // it's a tad expensive. 560 // it's a tad expensive.
513 if (member is! MethodMirror || _hasSetter(cls, member)) { 561 if (member is! MethodMirror || _hasSetter(cls, member)) {
514 if (props == null) props = {}; 562 if (props == null) props = {};
515 props[member.simpleName] = member; 563 props[new PropertyPath([member.simpleName])] = member;
516 } 564 }
517 break; 565 break;
518 } 566 }
519 } 567 }
520 } 568 }
521 } 569 }
522 570
523 return props; 571 return props;
524 } 572 }
525 573
(...skipping 12 matching lines...) Expand all
538 // bug introduced between Chrome 31 and 32. After 32 586 // bug introduced between Chrome 31 and 32. After 32
539 // JsClassMirror.declarations on Object calls 587 // JsClassMirror.declarations on Object calls
540 // JsClassMirror.typeVariables, which tries to get the _jsConstructor's 588 // JsClassMirror.typeVariables, which tries to get the _jsConstructor's
541 // .prototype["<>"]. This ends up getting the "" property instead, maybe 589 // .prototype["<>"]. This ends up getting the "" property instead, maybe
542 // because "<>" doesn't exist, and gets ";" which then blows up because 590 // because "<>" doesn't exist, and gets ";" which then blows up because
543 // the code later on expects a List of ints. 591 // the code later on expects a List of ints.
544 } while (cls != _objectType); 592 } while (cls != _objectType);
545 return null; 593 return null;
546 } 594 }
547 595
596 List _safeGetMetadata(MethodMirror method) {
597 // TODO(jmesserly): dart2js blows up getting metadata from methods in some
598 // cases. Why does this happen? It seems like the culprit might be named
599 // arguments. Unfortunately even calling method.parameters also
600 // triggers the bug in computeFunctionRti. For now we guard against it
601 // with this check.
602 try {
603 return method.metadata;
604 } catch (e) {
605 return [];
606 }
607 }
608
548 bool _hasSetter(ClassMirror cls, MethodMirror getter) { 609 bool _hasSetter(ClassMirror cls, MethodMirror getter) {
549 var setterName = new Symbol('${MirrorSystem.getName(getter.simpleName)}='); 610 var setterName = new Symbol('${MirrorSystem.getName(getter.simpleName)}=');
550 var mirror = cls.declarations[setterName]; 611 var mirror = cls.declarations[setterName];
551 return mirror is MethodMirror && mirror.isSetter; 612 return mirror is MethodMirror && mirror.isSetter;
552 } 613 }
553 614
554 615
555 /** Attribute prefix used for declarative event handlers. */ 616 /** Attribute prefix used for declarative event handlers. */
556 const _EVENT_PREFIX = 'on-'; 617 const _EVENT_PREFIX = 'on-';
557 618
558 /** Whether an attribute declares an event. */ 619 /** Whether an attribute declares an event. */
559 bool _hasEventPrefix(String attr) => attr.startsWith(_EVENT_PREFIX); 620 bool _hasEventPrefix(String attr) => attr.startsWith(_EVENT_PREFIX);
560 621
561 String _removeEventPrefix(String name) => name.substring(_EVENT_PREFIX.length); 622 String _removeEventPrefix(String name) => name.substring(_EVENT_PREFIX.length);
562 623
563 /** 624 /**
564 * Using Polymer's platform/src/ShadowCSS.js passing the style tag's content. 625 * Using Polymer's platform/src/ShadowCSS.js passing the style tag's content.
565 */ 626 */
566 void _shimShadowDomStyling(DocumentFragment template, String name, 627 void _shimShadowDomStyling(DocumentFragment template, String name,
567 String extendee) { 628 String extendee) {
568 if (js.context == null || template == null) return; 629 if (template == null || !_hasShadowDomPolyfill) return;
569 if (!js.context.hasProperty('ShadowDOMPolyfill')) return;
570 630
571 var platform = js.context['Platform']; 631 var platform = js.context['Platform'];
572 if (platform == null) return; 632 if (platform == null) return;
573 var shadowCss = platform['ShadowCSS']; 633 var shadowCss = platform['ShadowCSS'];
574 if (shadowCss == null) return; 634 if (shadowCss == null) return;
575 shadowCss.callMethod('shimStyling', [template, name, extendee]); 635 shadowCss.callMethod('shimStyling', [template, name, extendee]);
576 } 636 }
577 637
638 final bool _hasShadowDomPolyfill = js.context != null &&
639 js.context.hasProperty('ShadowDOMPolyfill');
640
578 const _STYLE_SELECTOR = 'style'; 641 const _STYLE_SELECTOR = 'style';
579 const _SHEET_SELECTOR = '[rel=stylesheet]'; 642 const _SHEET_SELECTOR = '[rel=stylesheet]';
580 const _STYLE_GLOBAL_SCOPE = 'global'; 643 const _STYLE_GLOBAL_SCOPE = 'global';
581 const _SCOPE_ATTR = 'polymer-scope'; 644 const _SCOPE_ATTR = 'polymer-scope';
582 const _STYLE_SCOPE_ATTRIBUTE = 'element'; 645 const _STYLE_SCOPE_ATTRIBUTE = 'element';
583 const _STYLE_CONTROLLER_SCOPE = 'controller'; 646 const _STYLE_CONTROLLER_SCOPE = 'controller';
584 647
585 String _cssTextFromSheet(LinkElement sheet) { 648 String _cssTextFromSheet(LinkElement sheet) {
586 if (sheet == null) return ''; 649 if (sheet == null) return '';
587 650
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
620 // TODO(jmesserly): is this list complete? 683 // TODO(jmesserly): is this list complete?
621 final _eventTranslations = const { 684 final _eventTranslations = const {
622 // TODO(jmesserly): these three Polymer.js translations won't work in Dart, 685 // TODO(jmesserly): these three Polymer.js translations won't work in Dart,
623 // because we strip the webkit prefix (below). Reconcile. 686 // because we strip the webkit prefix (below). Reconcile.
624 'webkitanimationstart': 'webkitAnimationStart', 687 'webkitanimationstart': 'webkitAnimationStart',
625 'webkitanimationend': 'webkitAnimationEnd', 688 'webkitanimationend': 'webkitAnimationEnd',
626 'webkittransitionend': 'webkitTransitionEnd', 689 'webkittransitionend': 'webkitTransitionEnd',
627 690
628 'domfocusout': 'DOMFocusOut', 691 'domfocusout': 'DOMFocusOut',
629 'domfocusin': 'DOMFocusIn', 692 'domfocusin': 'DOMFocusIn',
693 'dommousescroll': 'DOMMouseScroll',
630 694
631 // TODO(jmesserly): Dart specific renames. Reconcile with Polymer.js 695 // TODO(jmesserly): Dart specific renames. Reconcile with Polymer.js
632 'animationend': 'webkitAnimationEnd', 696 'animationend': 'webkitAnimationEnd',
633 'animationiteration': 'webkitAnimationIteration', 697 'animationiteration': 'webkitAnimationIteration',
634 'animationstart': 'webkitAnimationStart', 698 'animationstart': 'webkitAnimationStart',
635 'doubleclick': 'dblclick', 699 'doubleclick': 'dblclick',
636 'fullscreenchange': 'webkitfullscreenchange', 700 'fullscreenchange': 'webkitfullscreenchange',
637 'fullscreenerror': 'webkitfullscreenerror', 701 'fullscreenerror': 'webkitfullscreenerror',
638 'keyadded': 'webkitkeyadded', 702 'keyadded': 'webkitkeyadded',
639 'keyerror': 'webkitkeyerror', 703 'keyerror': 'webkitkeyerror',
(...skipping 10 matching lines...) Expand all
650 return map; 714 return map;
651 }(); 715 }();
652 716
653 // Dart note: we need this function because we have additional renames JS does 717 // Dart note: we need this function because we have additional renames JS does
654 // not have. The JS renames are simply case differences, whereas we have ones 718 // not have. The JS renames are simply case differences, whereas we have ones
655 // like doubleclick -> dblclick and stripping the webkit prefix. 719 // like doubleclick -> dblclick and stripping the webkit prefix.
656 String _eventNameFromType(String eventType) { 720 String _eventNameFromType(String eventType) {
657 final result = _reverseEventTranslations[eventType]; 721 final result = _reverseEventTranslations[eventType];
658 return result != null ? result : eventType; 722 return result != null ? result : eventType;
659 } 723 }
724
725 final _ATTRIBUTES_REGEX = new RegExp(r'\s|,');
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698