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

Side by Side Diff: pkg/polymer/lib/src/declaration.dart

Issue 30183005: port polymer - 00e2982c78fcd396adaebff3118e94029a2b9fb0 (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 1 month 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
« no previous file with comments | « pkg/polymer/lib/src/boot.dart ('k') | pkg/polymer/lib/src/instance.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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.
11 * 11 *
12 * Normally you do not need to use this class directly, see [PolymerElement]. 12 * Normally you do not need to use this class directly, see [PolymerElement].
13 */ 13 */
14 class PolymerDeclaration extends HtmlElement { 14 class PolymerDeclaration extends HtmlElement {
15 static const _TAG = 'polymer-element'; 15 static const _TAG = 'polymer-element';
16 16
17 factory PolymerDeclaration() => new Element.tag(_TAG); 17 factory PolymerDeclaration() => new Element.tag(_TAG);
18 // Fully ported from revision: 18 // Fully ported from revision:
19 // https://github.com/Polymer/polymer/blob/4dc481c11505991a7c43228d3797d28f212 67779 19 // https://github.com/Polymer/polymer/blob/00e2982c78fcd396adaebff3118e94029a2 b9fb0
20 // 20 //
21 // src/declaration/attributes.js 21 // src/declaration/attributes.js
22 // src/declaration/events.js 22 // src/declaration/events.js
23 // src/declaration/polymer-element.js 23 // src/declaration/polymer-element.js
24 // src/declaration/properties.js 24 // src/declaration/properties.js
25 // src/declaration/prototype.js (note: most code not needed in Dart) 25 // src/declaration/prototype.js (note: most code not needed in Dart)
26 // src/declaration/styles.js 26 // src/declaration/styles.js
27 // 27 //
28 // Not yet ported: 28 // Not yet ported:
29 // src/declaration/path.js - blocked on HTMLImports.getDocumentUrl 29 // src/declaration/path.js - blocked on HTMLImports.getDocumentUrl
(...skipping 11 matching lines...) Expand all
41 PolymerDeclaration _super; 41 PolymerDeclaration _super;
42 PolymerDeclaration get superDeclaration => _super; 42 PolymerDeclaration get superDeclaration => _super;
43 43
44 String _name; 44 String _name;
45 String get name => _name; 45 String get name => _name;
46 46
47 /** 47 /**
48 * Map of publish properties. Can be a [VariableMirror] or a [MethodMirror] 48 * 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. 49 * representing a getter. If it is a getter, there will also be a setter.
50 */ 50 */
51 Map<String, DeclarationMirror> _publish; 51 Map<Symbol, DeclarationMirror> _publish;
52 52
53 /** The names of published properties for this polymer-element. */ 53 /** The names of published properties for this polymer-element. */
54 Iterable<String> get publishedProperties => 54 Iterable<Symbol> get publishedProperties =>
55 _publish != null ? _publish.keys : const []; 55 _publish != null ? _publish.keys : const [];
56 56
57 /** Same as [_publish] but with lower case names. */ 57 /** Same as [_publish] but with lower case names. */
58 Map<String, DeclarationMirror> _publishLC; 58 Map<String, DeclarationMirror> _publishLC;
59 59
60 Map<String, Symbol> _observe; 60 Map<Symbol, Symbol> _observe;
61 61
62 Map<String, Object> _instanceAttributes; 62 Map<String, Object> _instanceAttributes;
63 63
64 List<Element> _sheets; 64 List<Element> _sheets;
65 List<Element> get sheets => _sheets; 65 List<Element> get sheets => _sheets;
66 66
67 List<Element> _styles; 67 List<Element> _styles;
68 List<Element> get styles => _styles; 68 List<Element> get styles => _styles;
69 69
70 DocumentFragment get templateContent { 70 DocumentFragment get templateContent {
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
150 return false; 150 return false;
151 } 151 }
152 152
153 void register(String name, String extendee) { 153 void register(String name, String extendee) {
154 // build prototype combining extendee, Polymer base, and named api 154 // build prototype combining extendee, Polymer base, and named api
155 buildType(name, extendee); 155 buildType(name, extendee);
156 156
157 // back reference declaration element 157 // back reference declaration element
158 // TODO(sjmiles): replace `element` with `elementElement` or `declaration` 158 // TODO(sjmiles): replace `element` with `elementElement` or `declaration`
159 _declarations[_type] = this; 159 _declarations[_type] = this;
160
161 // more declarative features 160 // more declarative features
162 desugar(); 161 desugar(name, extendee);
163
164 // TODO(sorvell): install a helper method this.resolvePath to aid in
165 // setting resource paths. e.g.
166 // this.$.image.src = this.resolvePath('images/foo.png')
167 // Potentially remove when spec bug is addressed.
168 // https://www.w3.org/Bugs/Public/show_bug.cgi?id=21407
169 // TODO(jmesserly): resolvePath not ported, see first comment in this class.
170
171 // under ShadowDOMPolyfill, transforms to approximate missing CSS features
172 _shimShadowDomStyling(templateContent, name, extendee);
173
174 // register our custom element 162 // register our custom element
175 registerType(name); 163 registerType(name);
176 164
177 // NOTE: skip in Dart because we don't have mutable global scope. 165 // NOTE: skip in Dart because we don't have mutable global scope.
178 // reference constructor in a global named by 'constructor' attribute 166 // reference constructor in a global named by 'constructor' attribute
179 // publishConstructor(); 167 // publishConstructor();
180 } 168 }
181 169
182 /** 170 /**
183 * Gets the Dart type registered for this name, and sets up declarative 171 * Gets the Dart type registered for this name, and sets up declarative
(...skipping 17 matching lines...) Expand all
201 189
202 publishProperties(type); 190 publishProperties(type);
203 191
204 inferObservers(cls); 192 inferObservers(cls);
205 193
206 // Skip the rest in Dart: 194 // Skip the rest in Dart:
207 // chain various meta-data objects to inherited versions 195 // chain various meta-data objects to inherited versions
208 // chain custom api to inherited 196 // chain custom api to inherited
209 // build side-chained lists to optimize iterations 197 // build side-chained lists to optimize iterations
210 // inherit publishing meta-data 198 // inherit publishing meta-data
211 //this.inheritAttributesObjects(prototype); 199 // x-platform fixup
212 //this.inheritDelegates(prototype);
213 // x-platform fixups
214 } 200 }
215 201
216 /** Implement various declarative features. */ 202 /** Implement various declarative features. */
217 void desugar() { 203 void desugar(name, extendee) {
218 // compile list of attributes to copy to instances 204 // compile list of attributes to copy to instances
219 accumulateInstanceAttributes(); 205 accumulateInstanceAttributes();
220 // parse on-* delegates declared on `this` element 206 // parse on-* delegates declared on `this` element
221 parseHostEvents(); 207 parseHostEvents();
222 // parse on-* delegates declared in templates 208 // parse on-* delegates declared in templates
223 parseLocalEvents(); 209 parseLocalEvents();
224 // install external stylesheets as if they are inline 210 // install external stylesheets as if they are inline
225 installSheets(); 211 installSheets();
212
213 // TODO(sorvell): install a helper method this.resolvePath to aid in
214 // setting resource paths. e.g.
215 // this.$.image.src = this.resolvePath('images/foo.png')
216 // Potentially remove when spec bug is addressed.
217 // https://www.w3.org/Bugs/Public/show_bug.cgi?id=21407
218 // TODO(jmesserly): resolvePath not ported, see first comment in this class.
219
220 // under ShadowDOMPolyfill, transforms to approximate missing CSS features
221 _shimShadowDomStyling(templateContent, name, extendee);
222
226 var cls = reflectClass(type); 223 var cls = reflectClass(type);
227 // TODO(jmesserly): this feels unnatrual in Dart. Since we have convenient 224 // TODO(jmesserly): this feels unnatrual in Dart. Since we have convenient
228 // lazy static initialization, can we get by without it? 225 // lazy static initialization, can we get by without it?
229 var registered = cls.methods[#registerCallback]; 226 var registered = cls.methods[#registerCallback];
230 if (registered != null && registered.isStatic && 227 if (registered != null && registered.isStatic &&
231 registered.isRegularMethod) { 228 registered.isRegularMethod) {
232 cls.invoke(#registerCallback, [this]); 229 cls.invoke(#registerCallback, [this]);
233 } 230 }
234
235 } 231 }
236 232
237 void registerType(String name) { 233 void registerType(String name) {
238 var baseTag; 234 var baseTag;
239 var decl = this; 235 var decl = this;
240 while (decl != null) { 236 while (decl != null) {
241 baseTag = decl.attributes['extends']; 237 baseTag = decl.attributes['extends'];
242 decl = decl.superDeclaration; 238 decl = decl.superDeclaration;
243 } 239 }
244 document.register(name, type, extendsTag: baseTag); 240 document.register(name, type, extendsTag: baseTag);
245 } 241 }
246 242
247 void publishAttributes(ClassMirror cls, PolymerDeclaration superDecl) { 243 void publishAttributes(ClassMirror cls, PolymerDeclaration superDecl) {
248 // get properties to publish 244 // get properties to publish
249 if (superDecl != null && superDecl._publish != null) { 245 if (superDecl != null && superDecl._publish != null) {
250 _publish = new Map.from(superDecl._publish); 246 _publish = new Map.from(superDecl._publish);
251 } 247 }
252 _publish = _getProperties(cls, _publish, (x) => x is PublishedProperty); 248 _publish = _getProperties(cls, _publish, (x) => x is PublishedProperty);
253 249
254 // merge names from 'attributes' attribute 250 // merge names from 'attributes' attribute
255 var attrs = attributes['attributes']; 251 var attrs = attributes['attributes'];
256 if (attrs != null) { 252 if (attrs != null) {
257 // names='a b c' or names='a,b,c' 253 // names='a b c' or names='a,b,c'
258 // record each name for publishing 254 // record each name for publishing
259 for (var attr in attrs.split(attrs.contains(',') ? ',' : ' ')) { 255 for (var attr in attrs.split(attrs.contains(',') ? ',' : ' ')) {
260 // remove excess ws 256 // remove excess ws
261 attr = attr.trim(); 257 attr = attr.trim();
262 258
263 // do not override explicit entries 259 // do not override explicit entries
264 if (_publish != null && _publish.containsKey(attr)) continue; 260 if (attr != '' && _publish != null && _publish.containsKey(attr)) {
261 continue;
262 }
265 263
266 var property = new Symbol(attr); 264 var property = new Symbol(attr);
267 var mirror = cls.variables[property]; 265 var mirror = cls.variables[property];
268 if (mirror == null) { 266 if (mirror == null) {
269 mirror = cls.getters[property]; 267 mirror = cls.getters[property];
270 if (mirror != null && !_hasSetter(cls, mirror)) mirror = null; 268 if (mirror != null && !_hasSetter(cls, mirror)) mirror = null;
271 } 269 }
272 if (mirror == null) { 270 if (mirror == null) {
273 window.console.warn('property for attribute $attr of polymer-element ' 271 window.console.warn('property for attribute $attr of polymer-element '
274 'name=$name not found.'); 272 'name=$name not found.');
275 continue; 273 continue;
276 } 274 }
277 if (_publish == null) _publish = {}; 275 if (_publish == null) _publish = {};
278 _publish[attr] = mirror; 276 _publish[property] = mirror;
279 } 277 }
280 } 278 }
281 279
282 // NOTE: the following is not possible in Dart; fields must be declared. 280 // NOTE: the following is not possible in Dart; fields must be declared.
283 // install 'attributes' as properties on the prototype, 281 // install 'attributes' as properties on the prototype,
284 // but don't override 282 // but don't override
285 } 283 }
286 284
287 void accumulateInstanceAttributes() { 285 void accumulateInstanceAttributes() {
288 // inherit instance attributes 286 // inherit instance attributes
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
431 /** 429 /**
432 * Promotes external stylesheets and style elements with the attribute 430 * Promotes external stylesheets and style elements with the attribute
433 * polymer-scope='global' into global scope. 431 * polymer-scope='global' into global scope.
434 * This is particularly useful for defining @keyframe rules which 432 * This is particularly useful for defining @keyframe rules which
435 * currently do not function in scoped or shadow style elements. 433 * currently do not function in scoped or shadow style elements.
436 * (See wkb.ug/72462) 434 * (See wkb.ug/72462)
437 */ 435 */
438 // TODO(sorvell): remove when wkb.ug/72462 is addressed. 436 // TODO(sorvell): remove when wkb.ug/72462 is addressed.
439 void installGlobalStyles() { 437 void installGlobalStyles() {
440 var style = styleForScope(_STYLE_GLOBAL_SCOPE); 438 var style = styleForScope(_STYLE_GLOBAL_SCOPE);
441 _applyStyleToScope(style, document.head); 439 Polymer.applyStyleToScope(style, document.head);
442 } 440 }
443 441
444 String cssTextForScope(String scopeDescriptor) { 442 String cssTextForScope(String scopeDescriptor) {
445 var cssText = new StringBuffer(); 443 var cssText = new StringBuffer();
446 // handle stylesheets 444 // handle stylesheets
447 var selector = '[$_SCOPE_ATTR=$scopeDescriptor]'; 445 var selector = '[$_SCOPE_ATTR=$scopeDescriptor]';
448 matcher(s) => s.matches(selector); 446 matcher(s) => s.matches(selector);
449 447
450 for (var sheet in sheets.where(matcher)) { 448 for (var sheet in sheets.where(matcher)) {
451 cssText..write(_cssTextFromSheet(sheet))..write('\n\n'); 449 cssText..write(_cssTextFromSheet(sheet))..write('\n\n');
(...skipping 24 matching lines...) Expand all
476 */ 474 */
477 // TODO(sjmiles): perf: reflection is slow, relatively speaking 475 // TODO(sjmiles): perf: reflection is slow, relatively speaking
478 // If an element may take 6us to create, getCustomPropertyNames might 476 // If an element may take 6us to create, getCustomPropertyNames might
479 // cost 1.6us more. 477 // cost 1.6us more.
480 void inferObservers(ClassMirror cls) { 478 void inferObservers(ClassMirror cls) {
481 for (var method in cls.methods.values) { 479 for (var method in cls.methods.values) {
482 if (method.isStatic || !method.isRegularMethod) continue; 480 if (method.isStatic || !method.isRegularMethod) continue;
483 481
484 String name = MirrorSystem.getName(method.simpleName); 482 String name = MirrorSystem.getName(method.simpleName);
485 if (name.endsWith(_OBSERVE_SUFFIX) && name != 'attributeChanged') { 483 if (name.endsWith(_OBSERVE_SUFFIX) && name != 'attributeChanged') {
486 if (_observe == null) _observe = {}; 484 if (_observe == null) _observe = new Map();
487 name = name.substring(0, name.length - 7); 485 name = name.substring(0, name.length - 7);
488 _observe[name] = method.simpleName; 486 _observe[new Symbol(name)] = method.simpleName;
489 } 487 }
490 } 488 }
491 } 489 }
492 490
493 void publishProperties(Type type) { 491 void publishProperties(Type type) {
494 // Dart note: _publish was already populated by publishAttributes 492 // Dart note: _publish was already populated by publishAttributes
495 if (_publish != null) _publishLC = _lowerCaseMap(_publish); 493 if (_publish != null) _publishLC = _lowerCaseMap(_publish);
496 } 494 }
497 495
498 Map<String, dynamic> _lowerCaseMap(Map<String, dynamic> properties) { 496 Map<String, dynamic> _lowerCaseMap(Map<Symbol, dynamic> properties) {
499 final map = new Map<String, dynamic>(); 497 final map = new Map<String, dynamic>();
500 properties.forEach((name, value) { 498 properties.forEach((name, value) {
501 map[name.toLowerCase()] = value; 499 map[MirrorSystem.getName(name).toLowerCase()] = value;
502 }); 500 });
503 return map; 501 return map;
504 } 502 }
505 } 503 }
506 504
507 /// maps tag names to prototypes 505 /// maps tag names to prototypes
508 final Map _typesByName = new Map<String, Type>(); 506 final Map _typesByName = new Map<String, Type>();
509 507
510 Type _getRegisteredType(String name) => _typesByName[name]; 508 Type _getRegisteredType(String name) => _typesByName[name];
511 509
(...skipping 29 matching lines...) Expand all
541 539
542 final _objectType = reflectClass(Object); 540 final _objectType = reflectClass(Object);
543 541
544 Map _getProperties(ClassMirror cls, Map props, bool matches(metadata)) { 542 Map _getProperties(ClassMirror cls, Map props, bool matches(metadata)) {
545 for (var field in cls.variables.values) { 543 for (var field in cls.variables.values) {
546 if (field.isFinal || field.isStatic || field.isPrivate) continue; 544 if (field.isFinal || field.isStatic || field.isPrivate) continue;
547 545
548 for (var meta in field.metadata) { 546 for (var meta in field.metadata) {
549 if (matches(meta.reflectee)) { 547 if (matches(meta.reflectee)) {
550 if (props == null) props = {}; 548 if (props == null) props = {};
551 props[MirrorSystem.getName(field.simpleName)] = field; 549 props[field.simpleName] = field;
552 break; 550 break;
553 } 551 }
554 } 552 }
555 } 553 }
556 554
557 for (var getter in cls.getters.values) { 555 for (var getter in cls.getters.values) {
558 if (getter.isStatic || getter.isPrivate) continue; 556 if (getter.isStatic || getter.isPrivate) continue;
559 557
560 for (var meta in getter.metadata) { 558 for (var meta in getter.metadata) {
561 if (matches(meta.reflectee)) { 559 if (matches(meta.reflectee)) {
562 if (_hasSetter(cls, getter)) { 560 if (_hasSetter(cls, getter)) {
563 if (props == null) props = {}; 561 if (props == null) props = {};
564 props[MirrorSystem.getName(getter.simpleName)] = getter; 562 props[getter.simpleName] = getter;
565 } 563 }
566 break; 564 break;
567 } 565 }
568 } 566 }
569 } 567 }
570 568
571 return props; 569 return props;
572 } 570 }
573 571
574 bool _hasSetter(ClassMirror cls, MethodMirror getter) { 572 bool _hasSetter(ClassMirror cls, MethodMirror getter) {
(...skipping 23 matching lines...) Expand all
598 var shadowCss = platform['ShadowCSS']; 596 var shadowCss = platform['ShadowCSS'];
599 if (shadowCss == null) return; 597 if (shadowCss == null) return;
600 shadowCss.callMethod('shimStyling', [template, name, extendee]); 598 shadowCss.callMethod('shimStyling', [template, name, extendee]);
601 } 599 }
602 600
603 const _STYLE_SELECTOR = 'style'; 601 const _STYLE_SELECTOR = 'style';
604 const _SHEET_SELECTOR = '[rel=stylesheet]'; 602 const _SHEET_SELECTOR = '[rel=stylesheet]';
605 const _STYLE_GLOBAL_SCOPE = 'global'; 603 const _STYLE_GLOBAL_SCOPE = 'global';
606 const _SCOPE_ATTR = 'polymer-scope'; 604 const _SCOPE_ATTR = 'polymer-scope';
607 const _STYLE_SCOPE_ATTRIBUTE = 'element'; 605 const _STYLE_SCOPE_ATTRIBUTE = 'element';
608 606 const _STYLE_CONTROLLER_SCOPE = 'controller';
609 void _applyStyleToScope(StyleElement style, Node scope) {
610 if (style == null) return;
611
612 // TODO(sorvell): necessary for IE
613 // see https://connect.microsoft.com/IE/feedback/details/790212/
614 // cloning-a-style-element-and-adding-to-document-produces
615 // -unexpected-result#details
616 // var clone = style.cloneNode(true);
617 var clone = new StyleElement()..text = style.text;
618
619 var attr = style.attributes[_STYLE_SCOPE_ATTRIBUTE];
620 if (attr != null) {
621 clone.attributes[_STYLE_SCOPE_ATTRIBUTE] = attr;
622 }
623
624 scope.append(clone);
625 }
626 607
627 String _cssTextFromSheet(Element sheet) { 608 String _cssTextFromSheet(Element sheet) {
628 if (sheet == null || js.context == null) return ''; 609 if (sheet == null || js.context == null) return '';
629 var resource = new js.JsObject.fromBrowserObject(sheet)['__resource']; 610 var resource = new js.JsObject.fromBrowserObject(sheet)['__resource'];
630 return resource != null ? resource : ''; 611 return resource != null ? resource : '';
631 } 612 }
632 613
633 const _OBSERVE_SUFFIX = 'Changed'; 614 const _OBSERVE_SUFFIX = 'Changed';
634 615
635 // TODO(jmesserly): is this list complete? 616 // TODO(jmesserly): is this list complete?
(...skipping 29 matching lines...) Expand all
665 return map; 646 return map;
666 }(); 647 }();
667 648
668 // Dart note: we need this function because we have additional renames JS does 649 // Dart note: we need this function because we have additional renames JS does
669 // not have. The JS renames are simply case differences, whereas we have ones 650 // not have. The JS renames are simply case differences, whereas we have ones
670 // like doubleclick -> dblclick and stripping the webkit prefix. 651 // like doubleclick -> dblclick and stripping the webkit prefix.
671 String _eventNameFromType(String eventType) { 652 String _eventNameFromType(String eventType) {
672 final result = _reverseEventTranslations[eventType]; 653 final result = _reverseEventTranslations[eventType];
673 return result != null ? result : eventType; 654 return result != null ? result : eventType;
674 } 655 }
OLDNEW
« no previous file with comments | « pkg/polymer/lib/src/boot.dart ('k') | pkg/polymer/lib/src/instance.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698