Chromium Code Reviews| Index: lib/polymer.dart |
| diff --git a/lib/polymer.dart b/lib/polymer.dart |
| index b81a01d3001886e591acfc09832317ca57c5e804..3118019175cbc8c1e12b7be0b9c5b79d9988e380 100644 |
| --- a/lib/polymer.dart |
| +++ b/lib/polymer.dart |
| @@ -11,10 +11,131 @@ |
| */ |
| library polymer; |
| -export 'custom_element.dart'; |
| +import 'dart:async'; |
| +import 'dart:mirrors'; |
| + |
| +import 'package:mdv/mdv.dart' as mdv; |
| +import 'package:observe/observe.dart' show Observable; |
| +import 'package:path/path.dart' as path; |
| +import 'polymer_element.dart' show registerPolymerElement; |
| + |
| +export 'package:custom_element/custom_element.dart'; |
| +export 'package:observe/observe.dart'; |
| + |
| export 'event.dart'; |
| export 'observe.dart'; |
| export 'observe_html.dart'; |
| export 'polymer_element.dart'; |
| export 'safe_html.dart'; |
| export 'scoped_css.dart'; |
| + |
| + |
| +/** Annotation used to automatically register polymer elements. */ |
| +class CustomTag { |
| + final String tagName; |
| + const CustomTag(this.tagName); |
| +} |
| + |
| +/** |
| + * Metadata used to label static or top-level methods that are called |
| + * automatically when loading the library of a custom element. |
| + */ |
| +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
|
| + |
| +/** |
| + * Initializes a polymer application by: setting up polling for observable |
| + * changes, initializing MDV, registering and initializing custom elements from |
| + * each library in [elementLibraries], and finally invoking [userMain]. |
| + * |
| + * There are two mechanisms by which custom elements can be initialized: |
| + * annotating the class that declares a custom element with [CustomTag] or |
| + * programatically registering the element in a static or top-level function and |
| + * annotating that function with [init_polymer]. |
| + * |
| + * The urls in [elementLibraries] can be absolute or relative to [srcUrl]. |
| + */ |
| +initPolymer(List<String> elementLibraries, void userMain(), [String srcUrl]) { |
| + new Timer.periodic(new Duration(milliseconds: 125), |
| + (_) => Observable.dirtyCheck()); |
| + |
| + // TODO(jmesserly): mdv should use initMdv instead of mdv.initialize. |
| + mdv.initialize(); |
| + for (var lib in elementLibraries) { |
| + _registerPolymerElementsOf(lib, srcUrl); |
| + } |
| + userMain(); |
| +} |
| + |
| +/** All libraries in the current isolate. */ |
| +var _libs = currentMirrorSystem().libraries; |
| + |
| +/** |
| + * Reads the library at [uriString] (which can be an absolute URI or a relative |
| + * URI from [srcUrl]), and: |
| + * |
| + * * Invokes top-level and static functions marked with the [init_polymer] |
| + * annotation. |
| + * |
| + * * Registers any [PolymerElement] that is marked with the [CustomTag] |
| + * annotation. |
| + */ |
| +void _registerPolymerElementsOf(String uriString, [String srcUrl]) { |
| + var uri = Uri.parse(uriString); |
| + if (uri.scheme == '' && srcUrl != null) { |
| + uri = Uri.parse(path.normalize(path.join(path.dirname(srcUrl), uriString))); |
| + } |
| + var lib = _libs[uri]; |
| + if (lib == null) { |
| + print('warning: $uri library not found'); |
| + return; |
| + } |
| + |
| + // Search top-level functions marked with @init_polymer |
| + for (var f in lib.functions.values) { |
| + _maybeInvoke(lib, f); |
| + } |
| + |
| + for (var c in lib.classes.values) { |
| + // Search for @CustomTag on classes |
| + for (var m in c.metadata) { |
| + var meta = m.reflectee; |
| + if (meta is CustomTag) { |
| + registerPolymerElement(meta.tagName, |
| + () => c.newInstance(const Symbol(''), const []).reflectee); |
| + } |
| + } |
| + |
| + // TODO(sigmund): check also static methods marked with @init_polymer. This |
| + // is blocked on two bugs: |
| + // - dartbug.com/12133 (static methods are incorrectly listed as top-level |
| + // in dart2js, so they end up being called twice) |
| + // - dartbug.com/12134 (sometimes "method.metadata" throws an exception, |
| + // we could wrap and hide those exceptions, but it's not ideal). |
| + } |
| +} |
| + |
| +void _maybeInvoke(ObjectMirror obj, MethodMirror method) { |
| + var annotationFound = false; |
| + for (var meta in method.metadata) { |
| + if (identical(meta.reflectee, init_polymer)) { |
| + annotationFound = true; |
| + break; |
| + } |
| + } |
| + if (!annotationFound) return; |
| + if (!method.isStatic) { |
| + print("warning: methods marked with @init_polymer should be static," |
| + " ${method.simpleName} is not."); |
| + return; |
| + } |
| + if (!method.parameters.where((p) => !p.isOptional).isEmpty) { |
| + print("warning: methods marked with @init_polymer should take no arguments," |
| + " ${method.simpleName} expects some."); |
| + return; |
| + } |
| + obj.invoke(method.simpleName, const []); |
| +} |
| + |
| +class _InitPolymerAnnotation { |
| + const _InitPolymerAnnotation(); |
| +} |