Index: pkg/polymer/lib/polymer.dart |
diff --git a/pkg/polymer/lib/polymer.dart b/pkg/polymer/lib/polymer.dart |
new file mode 100644 |
index 0000000000000000000000000000000000000000..b4265bd32581deed2c92bc216240ce490f4f01da |
--- /dev/null |
+++ b/pkg/polymer/lib/polymer.dart |
@@ -0,0 +1,143 @@ |
+// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
+// for details. All rights reserved. Use of this source code is governed by a |
+// BSD-style license that can be found in the LICENSE file. |
+ |
+/** |
+ * This library exports all of the commonly used functions and types for |
+ * building UI's. |
+ * |
+ * See this article for more information: |
+ * <http://www.dartlang.org/articles/dart-web-components/>. |
+ */ |
+library polymer; |
+ |
+import 'dart:async'; |
+import 'dart:mirrors'; |
+ |
+import 'package:mdv/mdv.dart' as mdv; |
+import 'package:observe/src/microtask.dart'; |
+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 'package:observe/src/microtask.dart'; |
+ |
+export 'observe.dart'; |
+export 'observe_html.dart'; |
+export 'polymer_element.dart'; |
+export 'safe_html.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 polymerInitMethod = const _InitPolymerAnnotation(); |
+ |
+/** |
+ * 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 [polymerInitMethod]. |
+ * |
+ * The urls in [elementLibraries] can be absolute or relative to [srcUrl]. |
+ */ |
+void initPolymer(List<String> elementLibraries, void userMain(), [String srcUrl]) { |
+ wrapMicrotask(() { |
+ // DOM events don't yet go through microtasks, so we catch those here. |
+ new Timer.periodic(new Duration(milliseconds: 125), |
+ (_) => performMicrotaskCheckpoint()); |
+ |
+ // 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. */ |
+final _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 |
+ * [polymerInitMethod] 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 @polymerInitMethod |
+ 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 @polymerInitMethod. |
+ // 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, polymerInitMethod)) { |
+ annotationFound = true; |
+ break; |
+ } |
+ } |
+ if (!annotationFound) return; |
+ if (!method.isStatic) { |
+ print("warning: methods marked with @polymerInitMethod should be static," |
+ " ${method.simpleName} is not."); |
+ return; |
+ } |
+ if (!method.parameters.where((p) => !p.isOptional).isEmpty) { |
+ print("warning: methods marked with @polymerInitMethod should take no " |
+ "arguments, ${method.simpleName} expects some."); |
+ return; |
+ } |
+ obj.invoke(method.simpleName, const []); |
+} |
+ |
+class _InitPolymerAnnotation { |
+ const _InitPolymerAnnotation(); |
+} |