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

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

Issue 26051002: Updating Polymer to derive from custom elements. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 2 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
« no previous file with comments | « pkg/polymer/lib/src/build/polyfill_injector.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 * **Deprecated**: use [Polymer.register] instead.
9 *
10 * Registers a [PolymerElement]. This is similar to [registerCustomElement]
11 * but it is designed to work with the `<element>` element and adds additional
12 * features.
13 */
14 @deprecated
15 void registerPolymerElement(String localName, PolymerElement create()) {
16 Polymer._registerClassMirror(localName, reflect(create()).type);
17 }
18
19 /**
20 * **Warning**: this class is experiental and subject to change. 8 * **Warning**: this class is experiental and subject to change.
21 * 9 *
22 * The implementation for the `polymer-element` element. 10 * The implementation for the `polymer-element` element.
23 * 11 *
24 * 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].
25 */ 13 */
26 class PolymerDeclaration extends CustomElement { 14 class PolymerDeclaration extends HtmlElement {
15 static const _TAG = 'polymer-element';
16
17 factory PolymerDeclaration() => new Element.tag(_TAG);
27 // Fully ported from revision: 18 // Fully ported from revision:
28 // https://github.com/Polymer/polymer/blob/4dc481c11505991a7c43228d3797d28f212 67779 19 // https://github.com/Polymer/polymer/blob/4dc481c11505991a7c43228d3797d28f212 67779
29 // 20 //
30 // src/declaration/attributes.js 21 // src/declaration/attributes.js
31 // src/declaration/events.js 22 // src/declaration/events.js
32 // src/declaration/polymer-element.js 23 // src/declaration/polymer-element.js
33 // src/declaration/properties.js 24 // src/declaration/properties.js
34 // src/declaration/prototype.js (note: most code not needed in Dart) 25 // src/declaration/prototype.js (note: most code not needed in Dart)
35 // src/declaration/styles.js 26 // src/declaration/styles.js
36 // 27 //
37 // Not yet ported: 28 // Not yet ported:
38 // src/declaration/path.js - blocked on HTMLImports.getDocumentUrl 29 // src/declaration/path.js - blocked on HTMLImports.getDocumentUrl
39 30
40 // TODO(jmesserly): these should be Type not ClassMirror. But we can't get 31 Type _type;
41 // from ClassMirror to Type yet in dart2js, so we use ClassMirror for now. 32 Type get type => _type;
42 // See https://code.google.com/p/dart/issues/detail?id=12607
43 ClassMirror _type;
44 ClassMirror get type => _type;
45 33
46 // 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
47 // ClassMirror -> Supertype. 35 // Type -> Supertype.
48 ClassMirror _supertype; 36 Type _supertype;
49 ClassMirror get supertype => _supertype; 37 Type get supertype => _supertype;
50 38
51 // 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
52 // each level of the __proto__ like JS does. 40 // each level of the __proto__ like JS does.
53 PolymerDeclaration _super; 41 PolymerDeclaration _super;
54 PolymerDeclaration get superDeclaration => _super; 42 PolymerDeclaration get superDeclaration => _super;
55 43
56 String _name; 44 String _name;
57 String get name => _name; 45 String get name => _name;
58 46
59 /** 47 /**
(...skipping 13 matching lines...) Expand all
73 61
74 Map<String, Object> _instanceAttributes; 62 Map<String, Object> _instanceAttributes;
75 63
76 List<Element> _sheets; 64 List<Element> _sheets;
77 List<Element> get sheets => _sheets; 65 List<Element> get sheets => _sheets;
78 66
79 List<Element> _styles; 67 List<Element> _styles;
80 List<Element> get styles => _styles; 68 List<Element> get styles => _styles;
81 69
82 DocumentFragment get templateContent { 70 DocumentFragment get templateContent {
83 final template = query('template'); 71 final template = this.query('template');
84 return template != null ? template.content : null; 72 return template != null ? template.content : null;
85 } 73 }
86 74
87 /** Maps event names and their associated method in the element class. */ 75 /** Maps event names and their associated method in the element class. */
88 final Map<String, String> _eventDelegates = {}; 76 final Map<String, String> _eventDelegates = {};
89 77
90 /** Expected events per element node. */ 78 /** Expected events per element node. */
91 // TODO(sigmund): investigate whether we need more than 1 set of local events 79 // TODO(sigmund): investigate whether we need more than 1 set of local events
92 // per element (why does the js implementation stores 1 per template node?) 80 // per element (why does the js implementation stores 1 per template node?)
93 Expando<Set<String>> _templateDelegates; 81 Expando<Set<String>> _templateDelegates;
94 82
95 void created() { 83 PolymerDeclaration.created() : super.created() {
96 super.created();
97
98 // fetch the element name 84 // fetch the element name
99 _name = attributes['name']; 85 _name = attributes['name'];
100 // install element definition, if ready 86 // install element definition, if ready
101 registerWhenReady(); 87 registerWhenReady();
102 } 88 }
103 89
104 void registerWhenReady() { 90 void registerWhenReady() {
105 // if we have no prototype, wait 91 // if we have no prototype, wait
106 if (waitingForType(name)) { 92 if (waitingForType(name)) {
107 return; 93 return;
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
179 // setting resource paths. e.g. 165 // setting resource paths. e.g.
180 // this.$.image.src = this.resolvePath('images/foo.png') 166 // this.$.image.src = this.resolvePath('images/foo.png')
181 // Potentially remove when spec bug is addressed. 167 // Potentially remove when spec bug is addressed.
182 // https://www.w3.org/Bugs/Public/show_bug.cgi?id=21407 168 // https://www.w3.org/Bugs/Public/show_bug.cgi?id=21407
183 // TODO(jmesserly): resolvePath not ported, see first comment in this class. 169 // TODO(jmesserly): resolvePath not ported, see first comment in this class.
184 170
185 // under ShadowDOMPolyfill, transforms to approximate missing CSS features 171 // under ShadowDOMPolyfill, transforms to approximate missing CSS features
186 _shimShadowDomStyling(templateContent, name); 172 _shimShadowDomStyling(templateContent, name);
187 173
188 // register our custom element 174 // register our custom element
189 registerType(name); 175 registerType(name, extendsTag: extendee);
190 176
191 // NOTE: skip in Dart because we don't have mutable global scope. 177 // NOTE: skip in Dart because we don't have mutable global scope.
192 // reference constructor in a global named by 'constructor' attribute 178 // reference constructor in a global named by 'constructor' attribute
193 // publishConstructor(); 179 // publishConstructor();
194 } 180 }
195 181
196 /** 182 /**
197 * Gets the Dart type registered for this name, and sets up declarative 183 * Gets the Dart type registered for this name, and sets up declarative
198 * features. Fills in the [type] and [supertype] fields. 184 * features. Fills in the [type] and [supertype] fields.
199 * 185 *
200 * *Note*: unlike the JavaScript version, we do not have to metaprogram the 186 * *Note*: unlike the JavaScript version, we do not have to metaprogram the
201 * prototype, which simplifies this method. 187 * prototype, which simplifies this method.
202 */ 188 */
203 void buildType(String name, String extendee) { 189 void buildType(String name, String extendee) {
204 // get our custom type 190 // get our custom type
205 _type = _getRegisteredType(name); 191 _type = _getRegisteredType(name);
206 192
207 // get basal prototype 193 // get basal prototype
208 _supertype = _getRegisteredType(extendee); 194 _supertype = _getRegisteredType(extendee);
209 if (supertype != null) _super = _getDeclaration(supertype); 195 if (supertype != null) _super = _getDeclaration(supertype);
210 196
197 var cls = reflectClass(_type);
198
211 // transcribe `attributes` declarations onto own prototype's `publish` 199 // transcribe `attributes` declarations onto own prototype's `publish`
212 publishAttributes(type, _super); 200 publishAttributes(cls, _super);
213 201
214 publishProperties(type); 202 publishProperties(type);
215 203
216 inferObservers(type); 204 inferObservers(cls);
217 205
218 // Skip the rest in Dart: 206 // Skip the rest in Dart:
219 // chain various meta-data objects to inherited versions 207 // chain various meta-data objects to inherited versions
220 // chain custom api to inherited 208 // chain custom api to inherited
221 // build side-chained lists to optimize iterations 209 // build side-chained lists to optimize iterations
222 // inherit publishing meta-data 210 // inherit publishing meta-data
223 //this.inheritAttributesObjects(prototype); 211 //this.inheritAttributesObjects(prototype);
224 //this.inheritDelegates(prototype); 212 //this.inheritDelegates(prototype);
225 // x-platform fixups 213 // x-platform fixups
226 } 214 }
227 215
228 /** Implement various declarative features. */ 216 /** Implement various declarative features. */
229 void desugar() { 217 void desugar() {
230 // compile list of attributes to copy to instances 218 // compile list of attributes to copy to instances
231 accumulateInstanceAttributes(); 219 accumulateInstanceAttributes();
232 // parse on-* delegates declared on `this` element 220 // parse on-* delegates declared on `this` element
233 parseHostEvents(); 221 parseHostEvents();
234 // parse on-* delegates declared in templates 222 // parse on-* delegates declared in templates
235 parseLocalEvents(); 223 parseLocalEvents();
236 // install external stylesheets as if they are inline 224 // install external stylesheets as if they are inline
237 installSheets(); 225 installSheets();
226 var cls = reflectClass(type);
238 // TODO(jmesserly): this feels unnatrual in Dart. Since we have convenient 227 // TODO(jmesserly): this feels unnatrual in Dart. Since we have convenient
239 // lazy static initialization, can we get by without it? 228 // lazy static initialization, can we get by without it?
240 var registered = type.methods[#registerCallback]; 229 var registered = cls.methods[#registerCallback];
241 if (registered != null && registered.isStatic && 230 if (registered != null && registered.isStatic &&
242 registered.isRegularMethod) { 231 registered.isRegularMethod) {
243 type.invoke(#registerCallback, [this]); 232 cls.invoke(#registerCallback, [this]);
244 } 233 }
245 234
246 } 235 }
247 236
248 void registerType(String name) { 237 void registerType(String name, {String extendsTag}) {
249 // TODO(jmesserly): document.register 238 // native element must be specified in extends
250 registerCustomElement(name, () => 239 var nativeExtends = (extendsTag != null && !extendsTag.contains('-')) ?
251 type.newInstance(const Symbol(''), const []).reflectee); 240 extendsTag : null;
241 document.register(name, type, extendsTag: nativeExtends);
252 } 242 }
253 243
254 void publishAttributes(ClassMirror type, PolymerDeclaration superDecl) { 244 void publishAttributes(ClassMirror cls, PolymerDeclaration superDecl) {
255 // get properties to publish 245 // get properties to publish
256 if (superDecl != null && superDecl._publish != null) { 246 if (superDecl != null && superDecl._publish != null) {
257 _publish = new Map.from(superDecl._publish); 247 _publish = new Map.from(superDecl._publish);
258 } 248 }
259 _publish = _getProperties(type, _publish, (x) => x is PublishedProperty); 249 _publish = _getProperties(cls, _publish, (x) => x is PublishedProperty);
260 250
261 // merge names from 'attributes' attribute 251 // merge names from 'attributes' attribute
262 var attrs = attributes['attributes']; 252 var attrs = attributes['attributes'];
263 if (attrs != null) { 253 if (attrs != null) {
264 // names='a b c' or names='a,b,c' 254 // names='a b c' or names='a,b,c'
265 // record each name for publishing 255 // record each name for publishing
266 for (var attr in attrs.split(attrs.contains(',') ? ',' : ' ')) { 256 for (var attr in attrs.split(attrs.contains(',') ? ',' : ' ')) {
267 // remove excess ws 257 // remove excess ws
268 attr = attr.trim(); 258 attr = attr.trim();
269 259
270 // do not override explicit entries 260 // do not override explicit entries
271 if (_publish != null && _publish.containsKey(attr)) continue; 261 if (_publish != null && _publish.containsKey(attr)) continue;
272 262
273 var property = new Symbol(attr); 263 var property = new Symbol(attr);
274 var mirror = type.variables[property]; 264 var mirror = cls.variables[property];
275 if (mirror == null) { 265 if (mirror == null) {
276 mirror = type.getters[property]; 266 mirror = cls.getters[property];
277 if (mirror != null && !_hasSetter(type, mirror)) mirror = null; 267 if (mirror != null && !_hasSetter(cls, mirror)) mirror = null;
278 } 268 }
279 if (mirror == null) { 269 if (mirror == null) {
280 window.console.warn('property for attribute $attr of polymer-element ' 270 window.console.warn('property for attribute $attr of polymer-element '
281 'name=$name not found.'); 271 'name=$name not found.');
282 continue; 272 continue;
283 } 273 }
284 if (_publish == null) _publish = {}; 274 if (_publish == null) _publish = {};
285 _publish[attr] = mirror; 275 _publish[attr] = mirror;
286 } 276 }
287 } 277 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 void addAttributeDelegates(Map<String, String> delegates) { 311 void addAttributeDelegates(Map<String, String> delegates) {
322 attributes.forEach((name, value) { 312 attributes.forEach((name, value) {
323 if (_hasEventPrefix(name)) { 313 if (_hasEventPrefix(name)) {
324 delegates[_removeEventPrefix(name)] = value; 314 delegates[_removeEventPrefix(name)] = value;
325 } 315 }
326 }); 316 });
327 } 317 }
328 318
329 /** Extracts events under the element's <template>. */ 319 /** Extracts events under the element's <template>. */
330 void parseLocalEvents() { 320 void parseLocalEvents() {
331 for (var t in queryAll('template')) { 321 for (var t in this.queryAll('template')) {
332 final events = new Set<String>(); 322 final events = new Set<String>();
333 // acquire delegates from entire subtree at t 323 // acquire delegates from entire subtree at t
334 accumulateTemplatedEvents(t, events); 324 accumulateTemplatedEvents(t, events);
335 if (events.isNotEmpty) { 325 if (events.isNotEmpty) {
336 // store delegate information directly on template 326 // store delegate information directly on template
337 if (_templateDelegates == null) { 327 if (_templateDelegates == null) {
338 _templateDelegates = new Expando<Set<String>>(); 328 _templateDelegates = new Expando<Set<String>>();
339 } 329 }
340 _templateDelegates[t] = events; 330 _templateDelegates[t] = events;
341 } 331 }
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
477 ..attributes[_STYLE_SCOPE_ATTRIBUTE] = '$name-$scopeDescriptor'; 467 ..attributes[_STYLE_SCOPE_ATTRIBUTE] = '$name-$scopeDescriptor';
478 } 468 }
479 469
480 /** 470 /**
481 * fetch a list of all observable properties names in our inheritance chain 471 * fetch a list of all observable properties names in our inheritance chain
482 * above Polymer. 472 * above Polymer.
483 */ 473 */
484 // TODO(sjmiles): perf: reflection is slow, relatively speaking 474 // TODO(sjmiles): perf: reflection is slow, relatively speaking
485 // If an element may take 6us to create, getCustomPropertyNames might 475 // If an element may take 6us to create, getCustomPropertyNames might
486 // cost 1.6us more. 476 // cost 1.6us more.
487 void inferObservers(ClassMirror type) { 477 void inferObservers(ClassMirror cls) {
488 for (var method in type.methods.values) { 478 for (var method in cls.methods.values) {
489 if (method.isStatic || !method.isRegularMethod) continue; 479 if (method.isStatic || !method.isRegularMethod) continue;
490 480
491 String name = MirrorSystem.getName(method.simpleName); 481 String name = MirrorSystem.getName(method.simpleName);
492 if (name.endsWith('Changed')) { 482 if (name.endsWith('Changed')) {
493 if (_observe == null) _observe = {}; 483 if (_observe == null) _observe = {};
494 name = name.substring(0, name.length - 7); 484 name = name.substring(0, name.length - 7);
495 _observe[name] = method.simpleName; 485 _observe[name] = method.simpleName;
496 } 486 }
497 } 487 }
498 } 488 }
499 489
500 void publishProperties(ClassMirror type) { 490 void publishProperties(Type type) {
501 // Dart note: _publish was already populated by publishAttributes 491 // Dart note: _publish was already populated by publishAttributes
502 if (_publish != null) _publishLC = _lowerCaseMap(_publish); 492 if (_publish != null) _publishLC = _lowerCaseMap(_publish);
503 } 493 }
504 494
505 Map<String, dynamic> _lowerCaseMap(Map<String, dynamic> properties) { 495 Map<String, dynamic> _lowerCaseMap(Map<String, dynamic> properties) {
506 final map = new Map<String, dynamic>(); 496 final map = new Map<String, dynamic>();
507 properties.forEach((name, value) { 497 properties.forEach((name, value) {
508 map[name.toLowerCase()] = value; 498 map[name.toLowerCase()] = value;
509 }); 499 });
510 return map; 500 return map;
511 } 501 }
512 } 502 }
513 503
514 /// maps tag names to prototypes 504 /// maps tag names to prototypes
515 final Map _typesByName = new Map<String, ClassMirror>(); 505 final Map _typesByName = new Map<String, Type>();
516 506
517 ClassMirror _getRegisteredType(String name) => _typesByName[name]; 507 Type _getRegisteredType(String name) => _typesByName[name];
518 508
519 /// elements waiting for prototype, by name 509 /// elements waiting for prototype, by name
520 final Map _waitType = new Map<String, PolymerDeclaration>(); 510 final Map _waitType = new Map<String, PolymerDeclaration>();
521 511
522 void _notifyType(String name) { 512 void _notifyType(String name) {
523 var waiting = _waitType.remove(name); 513 var waiting = _waitType.remove(name);
524 if (waiting != null) waiting.registerWhenReady(); 514 if (waiting != null) waiting.registerWhenReady();
525 } 515 }
526 516
527 /// elements waiting for super, by name 517 /// elements waiting for super, by name
528 final Map _waitSuper = new Map<String, List<PolymerDeclaration>>(); 518 final Map _waitSuper = new Map<String, List<PolymerDeclaration>>();
529 519
530 void _notifySuper(String name) { 520 void _notifySuper(String name) {
531 _registered.add(name); 521 _registered.add(name);
532 var waiting = _waitSuper.remove(name); 522 var waiting = _waitSuper.remove(name);
533 if (waiting != null) { 523 if (waiting != null) {
534 for (var w in waiting) { 524 for (var w in waiting) {
535 w.registerWhenReady(); 525 w.registerWhenReady();
536 } 526 }
537 } 527 }
538 } 528 }
539 529
540 /// track document.register'ed tag names 530 /// track document.register'ed tag names
541 final Set _registered = new Set<String>(); 531 final Set _registered = new Set<String>();
542 532
543 bool _isRegistered(name) => _registered.contains(name); 533 bool _isRegistered(name) => _registered.contains(name);
544 534
545 final Map _declarations = new Map<ClassMirror, PolymerDeclaration>(); 535 final Map _declarations = new Map<Type, PolymerDeclaration>();
546 536
547 PolymerDeclaration _getDeclaration(ClassMirror type) => _declarations[type]; 537 PolymerDeclaration _getDeclaration(Type type) => _declarations[type];
548 538
549 final _objectType = reflectClass(Object); 539 final _objectType = reflectClass(Object);
550 540
551 Map _getProperties(ClassMirror type, Map props, bool matches(metadata)) { 541 Map _getProperties(ClassMirror cls, Map props, bool matches(metadata)) {
552 for (var field in type.variables.values) { 542 for (var field in cls.variables.values) {
553 if (field.isFinal || field.isStatic || field.isPrivate) continue; 543 if (field.isFinal || field.isStatic || field.isPrivate) continue;
554 544
555 for (var meta in field.metadata) { 545 for (var meta in field.metadata) {
556 if (matches(meta.reflectee)) { 546 if (matches(meta.reflectee)) {
557 if (props == null) props = {}; 547 if (props == null) props = {};
558 props[MirrorSystem.getName(field.simpleName)] = field; 548 props[MirrorSystem.getName(field.simpleName)] = field;
559 break; 549 break;
560 } 550 }
561 } 551 }
562 } 552 }
563 553
564 for (var getter in type.getters.values) { 554 for (var getter in cls.getters.values) {
565 if (getter.isStatic || getter.isPrivate) continue; 555 if (getter.isStatic || getter.isPrivate) continue;
566 556
567 for (var meta in getter.metadata) { 557 for (var meta in getter.metadata) {
568 if (matches(meta.reflectee)) { 558 if (matches(meta.reflectee)) {
569 if (_hasSetter(type, getter)) { 559 if (_hasSetter(cls, getter)) {
570 if (props == null) props = {}; 560 if (props == null) props = {};
571 props[MirrorSystem.getName(getter.simpleName)] = getter; 561 props[MirrorSystem.getName(getter.simpleName)] = getter;
572 } 562 }
573 break; 563 break;
574 } 564 }
575 } 565 }
576 } 566 }
577 567
578 return props; 568 return props;
579 } 569 }
580 570
581 bool _hasSetter(ClassMirror type, MethodMirror getter) { 571 bool _hasSetter(ClassMirror cls, MethodMirror getter) {
582 var setterName = new Symbol('${MirrorSystem.getName(getter.simpleName)}='); 572 var setterName = new Symbol('${MirrorSystem.getName(getter.simpleName)}=');
583 return type.setters.containsKey(setterName); 573 return cls.setters.containsKey(setterName);
584 } 574 }
585 575
586 bool _inDartHtml(ClassMirror type) => type.owner.simpleName == #dart.dom.html;
587
588 576
589 /** Attribute prefix used for declarative event handlers. */ 577 /** Attribute prefix used for declarative event handlers. */
590 const _EVENT_PREFIX = 'on-'; 578 const _EVENT_PREFIX = 'on-';
591 579
592 /** Whether an attribute declares an event. */ 580 /** Whether an attribute declares an event. */
593 bool _hasEventPrefix(String attr) => attr.startsWith(_EVENT_PREFIX); 581 bool _hasEventPrefix(String attr) => attr.startsWith(_EVENT_PREFIX);
594 582
595 String _removeEventPrefix(String name) => name.substring(_EVENT_PREFIX.length); 583 String _removeEventPrefix(String name) => name.substring(_EVENT_PREFIX.length);
596 584
597 /** 585 /**
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
703 return map; 691 return map;
704 }(); 692 }();
705 693
706 // Dart note: we need this function because we have additional renames JS does 694 // Dart note: we need this function because we have additional renames JS does
707 // not have. The JS renames are simply case differences, whereas we have ones 695 // not have. The JS renames are simply case differences, whereas we have ones
708 // like doubleclick -> dblclick and stripping the webkit prefix. 696 // like doubleclick -> dblclick and stripping the webkit prefix.
709 String _eventNameFromType(String eventType) { 697 String _eventNameFromType(String eventType) {
710 final result = _reverseEventTranslations[eventType]; 698 final result = _reverseEventTranslations[eventType];
711 return result != null ? result : eventType; 699 return result != null ? result : eventType;
712 } 700 }
OLDNEW
« no previous file with comments | « pkg/polymer/lib/src/build/polyfill_injector.dart ('k') | pkg/polymer/lib/src/instance.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698