OLD | NEW |
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 * Use this annotation to publish a field as an attribute. For example: | 8 * Use this annotation to publish a field as an attribute. For example: |
9 * | 9 * |
10 * class MyPlaybackElement extends PolymerElement { | 10 * class MyPlaybackElement extends PolymerElement { |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
121 * Invoke [callback] in [wait], unless the job is re-registered, | 121 * Invoke [callback] in [wait], unless the job is re-registered, |
122 * which resets the timer. For example: | 122 * which resets the timer. For example: |
123 * | 123 * |
124 * _myJob = job(_myJob, callback, const Duration(milliseconds: 100)); | 124 * _myJob = job(_myJob, callback, const Duration(milliseconds: 100)); |
125 * | 125 * |
126 * Returns a job handle which can be used to re-register a job. | 126 * Returns a job handle which can be used to re-register a job. |
127 */ | 127 */ |
128 Job job(Job job, void callback(), Duration wait) => | 128 Job job(Job job, void callback(), Duration wait) => |
129 runJob(job, callback, wait); | 129 runJob(job, callback, wait); |
130 | 130 |
131 // TODO(jmesserly): I am not sure if we should have the | |
132 // created/createdCallback distinction. See post here: | |
133 // https://groups.google.com/d/msg/polymer-dev/W0ZUpU5caIM/v5itFnvnehEJ | |
134 // Same issue with inserted and removed. | |
135 void polymerCreated() { | 131 void polymerCreated() { |
136 if (this.document.window != null || alwaysPrepare || | 132 if (this.document.window != null || alwaysPrepare || |
137 _preparingElements > 0) { | 133 _preparingElements > 0) { |
138 prepareElement(); | 134 prepareElement(); |
139 } | 135 } |
140 } | 136 } |
141 | 137 |
142 void prepareElement() { | 138 void prepareElement() { |
143 // Dart note: get the _declaration, which also marks _elementPrepared | 139 // Dart note: get the _declaration, which also marks _elementPrepared |
144 _declaration = _getDeclaration(this.runtimeType); | 140 _declaration = _getDeclaration(this.runtimeType); |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
322 | 318 |
323 /** | 319 /** |
324 * Convert representation of [value] based on [type] and [defaultValue]. | 320 * Convert representation of [value] based on [type] and [defaultValue]. |
325 */ | 321 */ |
326 // TODO(jmesserly): this should probably take a ClassMirror instead of | 322 // TODO(jmesserly): this should probably take a ClassMirror instead of |
327 // TypeMirror, but it is currently impossible to get from a TypeMirror to a | 323 // TypeMirror, but it is currently impossible to get from a TypeMirror to a |
328 // ClassMirror. | 324 // ClassMirror. |
329 Object deserializeValue(String value, Object defaultValue, TypeMirror type) => | 325 Object deserializeValue(String value, Object defaultValue, TypeMirror type) => |
330 deserialize.deserializeValue(value, defaultValue, type); | 326 deserialize.deserializeValue(value, defaultValue, type); |
331 | 327 |
332 String serializeValue(Object value, TypeMirror inferredType) { | 328 String serializeValue(Object value) { |
333 if (value == null) return null; | 329 if (value == null) return null; |
334 | 330 |
335 final type = inferredType.qualifiedName; | 331 if (value is bool) { |
336 if (type == #dart.core.bool) { | |
337 return _toBoolean(value) ? '' : null; | 332 return _toBoolean(value) ? '' : null; |
338 } else if (type == #dart.core.String | 333 } else if (value is String || value is int || value is double) { |
339 || type == #dart.core.int | |
340 || type == #dart.core.double) { | |
341 return '$value'; | 334 return '$value'; |
342 } | 335 } |
343 return null; | 336 return null; |
344 } | 337 } |
345 | 338 |
346 void reflectPropertyToAttribute(String name) { | 339 void reflectPropertyToAttribute(String name) { |
347 // TODO(sjmiles): consider memoizing this | 340 // TODO(sjmiles): consider memoizing this |
348 final self = reflect(this); | 341 final self = reflect(this); |
349 // try to intelligently serialize property value | 342 // try to intelligently serialize property value |
350 // TODO(jmesserly): cache symbol? | 343 // TODO(jmesserly): cache symbol? |
351 final propValue = self.getField(new Symbol(name)).reflectee; | 344 final propValue = self.getField(new Symbol(name)).reflectee; |
352 final property = _declaration._publish[name]; | 345 final serializedValue = serializeValue(propValue); |
353 var inferredType = _inferPropertyType(propValue, property); | |
354 final serializedValue = serializeValue(propValue, inferredType); | |
355 // boolean properties must reflect as boolean attributes | 346 // boolean properties must reflect as boolean attributes |
356 if (serializedValue != null) { | 347 if (serializedValue != null) { |
357 attributes[name] = serializedValue; | 348 attributes[name] = serializedValue; |
358 // TODO(sorvell): we should remove attr for all properties | 349 // TODO(sorvell): we should remove attr for all properties |
359 // that have undefined serialization; however, we will need to | 350 // that have undefined serialization; however, we will need to |
360 // refine the attr reflection system to achieve this; pica, for example, | 351 // refine the attr reflection system to achieve this; pica, for example, |
361 // relies on having inferredType object properties not removed as | 352 // relies on having inferredType object properties not removed as |
362 // attrs. | 353 // attrs. |
363 } else if (inferredType.qualifiedName == #dart.core.bool) { | 354 } else if (propValue is bool) { |
364 attributes.remove(name); | 355 attributes.remove(name); |
365 } | 356 } |
366 } | 357 } |
367 | 358 |
368 /** | 359 /** |
369 * Creates the document fragment to use for each instance of the custom | 360 * Creates the document fragment to use for each instance of the custom |
370 * element, given the `<template>` node. By default this is equivalent to: | 361 * element, given the `<template>` node. By default this is equivalent to: |
371 * | 362 * |
372 * template.createInstance(this, polymerSyntax); | 363 * template.createInstance(this, polymerSyntax); |
373 * | 364 * |
(...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
663 if (method != null) { | 654 if (method != null) { |
664 // This will either truncate the argument list or extend it with extra | 655 // This will either truncate the argument list or extend it with extra |
665 // null arguments, so it will match the signature. | 656 // null arguments, so it will match the signature. |
666 // TODO(sigmund): consider accepting optional arguments when we can tell | 657 // TODO(sigmund): consider accepting optional arguments when we can tell |
667 // them appart from named arguments (see http://dartbug.com/11334) | 658 // them appart from named arguments (see http://dartbug.com/11334) |
668 args.length = method.parameters.where((p) => !p.isOptional).length; | 659 args.length = method.parameters.where((p) => !p.isOptional).length; |
669 } | 660 } |
670 self.invoke(methodName, args); | 661 self.invoke(methodName, args); |
671 | 662 |
672 if (log) _eventsLog.fine('<<< [$localName]: dispatch $methodName'); | 663 if (log) _eventsLog.fine('<<< [$localName]: dispatch $methodName'); |
673 | |
674 // TODO(jmesserly): workaround for HTML events not supporting zones. | |
675 performMicrotaskCheckpoint(); | |
676 } | 664 } |
677 | 665 |
678 void instanceEventListener(Event event) { | 666 void instanceEventListener(Event event) { |
679 _listenLocal(this, event); | 667 _listenLocal(this, event); |
680 } | 668 } |
681 | 669 |
682 // TODO(sjmiles): much of the below privatized only because of the vague | 670 // TODO(sjmiles): much of the below privatized only because of the vague |
683 // notion this code is too fiddly and we need to revisit the core feature | 671 // notion this code is too fiddly and we need to revisit the core feature |
684 void _listenLocal(Polymer host, Event event) { | 672 void _listenLocal(Polymer host, Event event) { |
685 // TODO(jmesserly): do we need this check? It was using cancelBubble, see: | 673 // TODO(jmesserly): do we need this check? It was using cancelBubble, see: |
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
915 property is VariableMirror | 903 property is VariableMirror |
916 ? (property as VariableMirror).type | 904 ? (property as VariableMirror).type |
917 : (property as MethodMirror).returnType; | 905 : (property as MethodMirror).returnType; |
918 | 906 |
919 TypeMirror _inferPropertyType(Object value, DeclarationMirror property) { | 907 TypeMirror _inferPropertyType(Object value, DeclarationMirror property) { |
920 var type = _propertyType(property); | 908 var type = _propertyType(property); |
921 if (type.qualifiedName == #dart.core.Object || | 909 if (type.qualifiedName == #dart.core.Object || |
922 type.qualifiedName == #dynamic) { | 910 type.qualifiedName == #dynamic) { |
923 // Attempt to infer field type from the default value. | 911 // Attempt to infer field type from the default value. |
924 if (value != null) { | 912 if (value != null) { |
925 type = reflect(value).type; | 913 Type t = _getCoreType(value); |
| 914 if (t != null) return reflectClass(t); |
| 915 return reflect(value).type; |
926 } | 916 } |
927 } | 917 } |
928 return type; | 918 return type; |
929 } | 919 } |
930 | 920 |
| 921 Type _getCoreType(Object value) { |
| 922 if (value == null) return Null; |
| 923 if (value is int) return int; |
| 924 // Avoid "is double" to prevent warning that it won't work in dart2js. |
| 925 if (value is num) return double; |
| 926 if (value is bool) return bool; |
| 927 if (value is String) return String; |
| 928 if (value is DateTime) return DateTime; |
| 929 return null; |
| 930 } |
| 931 |
931 final Logger _observeLog = new Logger('polymer.observe'); | 932 final Logger _observeLog = new Logger('polymer.observe'); |
932 final Logger _eventsLog = new Logger('polymer.events'); | 933 final Logger _eventsLog = new Logger('polymer.events'); |
933 final Logger _unbindLog = new Logger('polymer.unbind'); | 934 final Logger _unbindLog = new Logger('polymer.unbind'); |
934 final Logger _bindLog = new Logger('polymer.bind'); | 935 final Logger _bindLog = new Logger('polymer.bind'); |
935 | 936 |
936 final Expando _shadowHost = new Expando<Polymer>(); | 937 final Expando _shadowHost = new Expando<Polymer>(); |
937 | 938 |
938 final Expando _eventHandledTable = new Expando<Set<Node>>(); | 939 final Expando _eventHandledTable = new Expando<Set<Node>>(); |
939 | 940 |
940 /** | 941 /** |
941 * Base class for PolymerElements deriving from HtmlElement. | 942 * Base class for PolymerElements deriving from HtmlElement. |
942 * | 943 * |
943 * See [Polymer]. | 944 * See [Polymer]. |
944 */ | 945 */ |
945 class PolymerElement extends HtmlElement with Polymer, Observable { | 946 class PolymerElement extends HtmlElement with Polymer, Observable { |
946 PolymerElement.created() : super.created() { | 947 PolymerElement.created() : super.created() { |
947 polymerCreated(); | 948 polymerCreated(); |
948 } | 949 } |
949 } | 950 } |
OLD | NEW |