| 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 * Custom HTML tags, data binding, and templates for building | 6 * Custom HTML tags, data binding, and templates for building |
| 7 * structured, encapsulated, client-side web apps. | 7 * structured, encapsulated, client-side web apps. |
| 8 * | 8 * |
| 9 * Polymer.dart, the next evolution of Web UI, | 9 * Polymer.dart, the next evolution of Web UI, |
| 10 * is an in-progress Dart port of the | 10 * is an in-progress Dart port of the |
| (...skipping 22 matching lines...) Expand all Loading... |
| 33 * | 33 * |
| 34 * * [polymer.dart package](http://pub.dartlang.org/packages/polymer): | 34 * * [polymer.dart package](http://pub.dartlang.org/packages/polymer): |
| 35 * More details, such as the current major release number. | 35 * More details, such as the current major release number. |
| 36 * | 36 * |
| 37 * * [Upgrading to Polymer.dart](http://www.dartlang.org/polymer-dart/upgrading-
to-polymer-from-web-ui.html): | 37 * * [Upgrading to Polymer.dart](http://www.dartlang.org/polymer-dart/upgrading-
to-polymer-from-web-ui.html): |
| 38 * Tips for converting your apps from Web UI to Polymer.dart. | 38 * Tips for converting your apps from Web UI to Polymer.dart. |
| 39 */ | 39 */ |
| 40 library polymer; | 40 library polymer; |
| 41 | 41 |
| 42 import 'dart:async'; | 42 import 'dart:async'; |
| 43 import 'dart:collection' show HashMap; |
| 44 import 'dart:html'; |
| 45 import 'dart:js' as js; |
| 43 import 'dart:mirrors'; | 46 import 'dart:mirrors'; |
| 44 | 47 |
| 48 import 'package:custom_element/custom_element.dart'; |
| 49 import 'package:logging/logging.dart' show Logger, Level; |
| 45 import 'package:mdv/mdv.dart' as mdv; | 50 import 'package:mdv/mdv.dart' as mdv; |
| 51 import 'package:mdv/mdv.dart' show NodeBinding; |
| 52 import 'package:meta/meta.dart' show deprecated; |
| 53 import 'package:observe/observe.dart'; |
| 46 import 'package:observe/src/microtask.dart'; | 54 import 'package:observe/src/microtask.dart'; |
| 47 import 'package:path/path.dart' as path; | 55 import 'package:path/path.dart' as path; |
| 48 import 'polymer_element.dart' show registerPolymerElement; | 56 import 'package:polymer_expressions/polymer_expressions.dart' |
| 57 show PolymerExpressions; |
| 58 |
| 59 import 'deserialize.dart' as deserialize; |
| 60 import 'job.dart'; |
| 61 import 'platform.dart' as platform; |
| 49 | 62 |
| 50 export 'package:custom_element/custom_element.dart'; | 63 export 'package:custom_element/custom_element.dart'; |
| 51 export 'package:observe/observe.dart'; | 64 export 'package:observe/observe.dart'; |
| 52 export 'package:observe/html.dart'; | 65 export 'package:observe/html.dart'; |
| 53 export 'package:observe/src/microtask.dart'; | 66 export 'package:observe/src/microtask.dart'; |
| 54 | 67 |
| 55 export 'polymer_element.dart'; | 68 part 'src/declaration.dart'; |
| 56 | 69 part 'src/instance.dart'; |
| 57 | 70 part 'src/loader.dart'; |
| 58 /** Annotation used to automatically register polymer elements. */ | |
| 59 class CustomTag { | |
| 60 final String tagName; | |
| 61 const CustomTag(this.tagName); | |
| 62 } | |
| 63 | |
| 64 /** | |
| 65 * Metadata used to label static or top-level methods that are called | |
| 66 * automatically when loading the library of a custom element. | |
| 67 */ | |
| 68 const initMethod = const _InitMethodAnnotation(); | |
| 69 | |
| 70 /** | |
| 71 * Initializes a polymer application as follows: | |
| 72 * * set up up polling for observable changes | |
| 73 * * initialize MDV | |
| 74 * * for each library in [libraries], register custom elements labeled with | |
| 75 * [CustomTag] and invoke the initialization method on it. | |
| 76 * | |
| 77 * The initialization on each library is either a method named `main` or | |
| 78 * a top-level function and annotated with [initMethod]. | |
| 79 * | |
| 80 * The urls in [libraries] can be absolute or relative to [srcUrl]. | |
| 81 */ | |
| 82 void initPolymer(List<String> libraries, [String srcUrl]) { | |
| 83 wrapMicrotask(() { | |
| 84 // DOM events don't yet go through microtasks, so we catch those here. | |
| 85 new Timer.periodic(new Duration(milliseconds: 125), | |
| 86 (_) => performMicrotaskCheckpoint()); | |
| 87 | |
| 88 // TODO(jmesserly): mdv should use initMdv instead of mdv.initialize. | |
| 89 mdv.initialize(); | |
| 90 for (var lib in libraries) { | |
| 91 _loadLibrary(lib, srcUrl); | |
| 92 } | |
| 93 })(); | |
| 94 } | |
| 95 | |
| 96 /** All libraries in the current isolate. */ | |
| 97 final _libs = currentMirrorSystem().libraries; | |
| 98 | |
| 99 /** | |
| 100 * Reads the library at [uriString] (which can be an absolute URI or a relative | |
| 101 * URI from [srcUrl]), and: | |
| 102 * | |
| 103 * * If present, invokes `main`. | |
| 104 * | |
| 105 * * If present, invokes any top-level and static functions marked | |
| 106 * with the [initMethod] annotation (in the order they appear). | |
| 107 * | |
| 108 * * Registers any [PolymerElement] that is marked with the [CustomTag] | |
| 109 * annotation. | |
| 110 */ | |
| 111 void _loadLibrary(String uriString, [String srcUrl]) { | |
| 112 var uri = Uri.parse(uriString); | |
| 113 if (uri.scheme == '' && srcUrl != null) { | |
| 114 uri = Uri.parse(path.normalize(path.join(path.dirname(srcUrl), uriString))); | |
| 115 } | |
| 116 var lib = _libs[uri]; | |
| 117 if (lib == null) { | |
| 118 print('warning: $uri library not found'); | |
| 119 return; | |
| 120 } | |
| 121 | |
| 122 // Invoke `main`, if present. | |
| 123 if (lib.functions[const Symbol('main')] != null) { | |
| 124 lib.invoke(const Symbol('main'), const []); | |
| 125 } | |
| 126 | |
| 127 // Search top-level functions marked with @initMethod | |
| 128 for (var f in lib.functions.values) { | |
| 129 _maybeInvoke(lib, f); | |
| 130 } | |
| 131 | |
| 132 for (var c in lib.classes.values) { | |
| 133 // Search for @CustomTag on classes | |
| 134 for (var m in c.metadata) { | |
| 135 var meta = m.reflectee; | |
| 136 if (meta is CustomTag) { | |
| 137 registerPolymerElement(meta.tagName, | |
| 138 () => c.newInstance(const Symbol(''), const []).reflectee); | |
| 139 } | |
| 140 } | |
| 141 | |
| 142 // TODO(sigmund): check also static methods marked with @initMethod. | |
| 143 // This is blocked on two bugs: | |
| 144 // - dartbug.com/12133 (static methods are incorrectly listed as top-level | |
| 145 // in dart2js, so they end up being called twice) | |
| 146 // - dartbug.com/12134 (sometimes "method.metadata" throws an exception, | |
| 147 // we could wrap and hide those exceptions, but it's not ideal). | |
| 148 } | |
| 149 } | |
| 150 | |
| 151 void _maybeInvoke(ObjectMirror obj, MethodMirror method) { | |
| 152 var annotationFound = false; | |
| 153 for (var meta in method.metadata) { | |
| 154 if (identical(meta.reflectee, initMethod)) { | |
| 155 annotationFound = true; | |
| 156 break; | |
| 157 } | |
| 158 } | |
| 159 if (!annotationFound) return; | |
| 160 if (!method.isStatic) { | |
| 161 print("warning: methods marked with @initMethod should be static," | |
| 162 " ${method.simpleName} is not."); | |
| 163 return; | |
| 164 } | |
| 165 if (!method.parameters.where((p) => !p.isOptional).isEmpty) { | |
| 166 print("warning: methods marked with @initMethod should take no " | |
| 167 "arguments, ${method.simpleName} expects some."); | |
| 168 return; | |
| 169 } | |
| 170 obj.invoke(method.simpleName, const []); | |
| 171 } | |
| 172 | |
| 173 class _InitMethodAnnotation { | |
| 174 const _InitMethodAnnotation(); | |
| 175 } | |
| OLD | NEW |