Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 /** | 5 /** |
| 6 * This library exports all of the commonly used functions and types for | 6 * This library exports all of the commonly used functions and types for |
| 7 * building UI's. | 7 * building UI's. |
| 8 * | 8 * |
| 9 * See this article for more information: | 9 * See this article for more information: |
| 10 * <http://www.dartlang.org/articles/dart-web-components/>. | 10 * <http://www.dartlang.org/articles/dart-web-components/>. |
| 11 */ | 11 */ |
| 12 library polymer; | 12 library polymer; |
| 13 | 13 |
| 14 export 'custom_element.dart'; | 14 import 'dart:async'; |
| 15 import 'dart:mirrors'; | |
| 16 | |
| 17 import 'package:mdv/mdv.dart' as mdv; | |
| 18 import 'package:observe/observe.dart' show Observable; | |
| 19 import 'package:path/path.dart' as path; | |
| 20 import 'polymer_element.dart' show registerPolymerElement; | |
| 21 | |
| 22 export 'package:custom_element/custom_element.dart'; | |
| 23 export 'package:observe/observe.dart'; | |
| 24 | |
| 15 export 'event.dart'; | 25 export 'event.dart'; |
| 16 export 'observe.dart'; | 26 export 'observe.dart'; |
| 17 export 'observe_html.dart'; | 27 export 'observe_html.dart'; |
| 18 export 'polymer_element.dart'; | 28 export 'polymer_element.dart'; |
| 19 export 'safe_html.dart'; | 29 export 'safe_html.dart'; |
| 20 export 'scoped_css.dart'; | 30 export 'scoped_css.dart'; |
| 31 | |
| 32 | |
| 33 /** Annotation used to automatically register polymer elements. */ | |
| 34 class CustomTag { | |
| 35 final String tagName; | |
| 36 const CustomTag(this.tagName); | |
| 37 } | |
| 38 | |
| 39 /** | |
| 40 * Metadata used to label static or top-level methods that are called | |
| 41 * automatically when loading the library of a custom element. | |
| 42 */ | |
| 43 const init_polymer = const _InitPolymerAnnotation(); | |
|
Jennifer Messerly
2013/07/31 01:51:33
this should be camelCase right, per naming guideli
Siggi Cherem (dart-lang)
2013/07/31 02:17:29
Done, renamed to initPolymerMethod.
BTW, your sug
Jennifer Messerly
2013/07/31 02:18:49
yeah, definitely worth discussing
| |
| 44 | |
| 45 /** | |
| 46 * Initializes a polymer application by: setting up polling for observable | |
| 47 * changes, initializing MDV, registering and initializing custom elements from | |
| 48 * each library in [elementLibraries], and finally invoking [userMain]. | |
| 49 * | |
| 50 * There are two mechanisms by which custom elements can be initialized: | |
| 51 * annotating the class that declares a custom element with [CustomTag] or | |
| 52 * programatically registering the element in a static or top-level function and | |
| 53 * annotating that function with [init_polymer]. | |
| 54 * | |
| 55 * The urls in [elementLibraries] can be absolute or relative to [srcUrl]. | |
| 56 */ | |
| 57 initPolymer(List<String> elementLibraries, void userMain(), [String srcUrl]) { | |
| 58 new Timer.periodic(new Duration(milliseconds: 125), | |
| 59 (_) => Observable.dirtyCheck()); | |
| 60 | |
| 61 // TODO(jmesserly): mdv should use initMdv instead of mdv.initialize. | |
| 62 mdv.initialize(); | |
| 63 for (var lib in elementLibraries) { | |
| 64 _registerPolymerElementsOf(lib, srcUrl); | |
| 65 } | |
| 66 userMain(); | |
| 67 } | |
| 68 | |
| 69 /** All libraries in the current isolate. */ | |
| 70 var _libs = currentMirrorSystem().libraries; | |
| 71 | |
| 72 /** | |
| 73 * Reads the library at [uriString] (which can be an absolute URI or a relative | |
| 74 * URI from [srcUrl]), and: | |
| 75 * | |
| 76 * * Invokes top-level and static functions marked with the [init_polymer] | |
| 77 * annotation. | |
| 78 * | |
| 79 * * Registers any [PolymerElement] that is marked with the [CustomTag] | |
| 80 * annotation. | |
| 81 */ | |
| 82 void _registerPolymerElementsOf(String uriString, [String srcUrl]) { | |
| 83 var uri = Uri.parse(uriString); | |
| 84 if (uri.scheme == '' && srcUrl != null) { | |
| 85 uri = Uri.parse(path.normalize(path.join(path.dirname(srcUrl), uriString))); | |
| 86 } | |
| 87 var lib = _libs[uri]; | |
| 88 if (lib == null) { | |
| 89 print('warning: $uri library not found'); | |
| 90 return; | |
| 91 } | |
| 92 | |
| 93 // Search top-level functions marked with @init_polymer | |
| 94 for (var f in lib.functions.values) { | |
| 95 _maybeInvoke(lib, f); | |
| 96 } | |
| 97 | |
| 98 for (var c in lib.classes.values) { | |
| 99 // Search for @CustomTag on classes | |
| 100 for (var m in c.metadata) { | |
| 101 var meta = m.reflectee; | |
| 102 if (meta is CustomTag) { | |
| 103 registerPolymerElement(meta.tagName, | |
| 104 () => c.newInstance(const Symbol(''), const []).reflectee); | |
| 105 } | |
| 106 } | |
| 107 | |
| 108 // TODO(sigmund): check also static methods marked with @init_polymer. This | |
| 109 // is blocked on two bugs: | |
| 110 // - dartbug.com/12133 (static methods are incorrectly listed as top-level | |
| 111 // in dart2js, so they end up being called twice) | |
| 112 // - dartbug.com/12134 (sometimes "method.metadata" throws an exception, | |
| 113 // we could wrap and hide those exceptions, but it's not ideal). | |
| 114 } | |
| 115 } | |
| 116 | |
| 117 void _maybeInvoke(ObjectMirror obj, MethodMirror method) { | |
| 118 var annotationFound = false; | |
| 119 for (var meta in method.metadata) { | |
| 120 if (identical(meta.reflectee, init_polymer)) { | |
| 121 annotationFound = true; | |
| 122 break; | |
| 123 } | |
| 124 } | |
| 125 if (!annotationFound) return; | |
| 126 if (!method.isStatic) { | |
| 127 print("warning: methods marked with @init_polymer should be static," | |
| 128 " ${method.simpleName} is not."); | |
| 129 return; | |
| 130 } | |
| 131 if (!method.parameters.where((p) => !p.isOptional).isEmpty) { | |
| 132 print("warning: methods marked with @init_polymer should take no arguments," | |
| 133 " ${method.simpleName} expects some."); | |
| 134 return; | |
| 135 } | |
| 136 obj.invoke(method.simpleName, const []); | |
| 137 } | |
| 138 | |
| 139 class _InitPolymerAnnotation { | |
| 140 const _InitPolymerAnnotation(); | |
| 141 } | |
| OLD | NEW |