| 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 |