Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(27)

Side by Side Diff: pkg/polymer/lib/src/loader.dart

Issue 182193002: [polymer] interop with polymer-element and polymer.js (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « pkg/polymer/lib/src/js/use_native_dartium_shadowdom.js ('k') | pkg/polymer/pubspec.yaml » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 /// Annotation used to automatically register polymer elements. 7 /// Annotation used to automatically register polymer elements.
8 class CustomTag { 8 class CustomTag {
9 final String tagName; 9 final String tagName;
10 const CustomTag(this.tagName); 10 const CustomTag(this.tagName);
(...skipping 28 matching lines...) Expand all
39 } 39 }
40 40
41 /// Same as [initPolymer], but runs the version that is optimized for deployment 41 /// Same as [initPolymer], but runs the version that is optimized for deployment
42 /// to the internet. The biggest difference is it omits the [Zone] that 42 /// to the internet. The biggest difference is it omits the [Zone] that
43 /// automatically invokes [Observable.dirtyCheck], and the list of initializers 43 /// automatically invokes [Observable.dirtyCheck], and the list of initializers
44 /// must be supplied instead of being dynamically searched for at runtime using 44 /// must be supplied instead of being dynamically searched for at runtime using
45 /// mirrors. 45 /// mirrors.
46 Zone initPolymerOptimized() { 46 Zone initPolymerOptimized() {
47 // TODO(sigmund): refactor this so we can replace it by codegen. 47 // TODO(sigmund): refactor this so we can replace it by codegen.
48 smoke.useMirrors(); 48 smoke.useMirrors();
49 // TODO(jmesserly): there is some code in src/declaration/polymer-element.js, 49 _hookJsPolymer();
50 // git version 37eea00e13b9f86ab21c85a955585e8e4237e3d2, right before
51 // it registers polymer-element, which uses Platform.deliverDeclarations to
52 // coordinate with HTML Imports. I don't think we need it so skipping.
53 document.register(PolymerDeclaration._TAG, PolymerDeclaration);
54 50
55 for (var initializer in _initializers) { 51 for (var initializer in _initializers) {
56 initializer(); 52 initializer();
57 } 53 }
58 54
59 // Run this after user code so they can add to Polymer.veiledElements
60 _preventFlashOfUnstyledContent();
61
62 customElementsReady.then((_) => Polymer._ready.complete());
63 return Zone.current; 55 return Zone.current;
64 } 56 }
65 57
66 /// Configures [initPolymer] making it optimized for deployment to the internet. 58 /// Configures [initPolymer] making it optimized for deployment to the internet.
67 /// With this setup the initializer list is supplied instead of searched for 59 /// With this setup the initializer list is supplied instead of searched for
68 /// at runtime. Additionally, after this method is called [initPolymer] omits 60 /// at runtime. Additionally, after this method is called [initPolymer] omits
69 /// the [Zone] that automatically invokes [Observable.dirtyCheck]. 61 /// the [Zone] that automatically invokes [Observable.dirtyCheck].
70 void configureForDeployment(List<Function> initializers) { 62 void configureForDeployment(List<Function> initializers) {
71 _initializers = initializers; 63 _initializers = initializers;
72 _deployMode = true; 64 _deployMode = true;
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 if (lib == null) { 173 if (lib == null) {
182 _loaderLog.info('$uri library not found'); 174 _loaderLog.info('$uri library not found');
183 return; 175 return;
184 } 176 }
185 177
186 // Search top-level functions marked with @initMethod 178 // Search top-level functions marked with @initMethod
187 for (var f in lib.declarations.values.where((d) => d is MethodMirror)) { 179 for (var f in lib.declarations.values.where((d) => d is MethodMirror)) {
188 _addInitMethod(lib, f, initializers); 180 _addInitMethod(lib, f, initializers);
189 } 181 }
190 182
183
184 // Dart note: we don't get back @CustomTags in a reliable order from mirrors,
185 // at least on Dart VM. So we need to sort them so base classes are registered
186 // first, which ensures that document.register will work correctly for a
187 // set of types within in the same library.
188 var customTags = new LinkedHashMap<Type, Function>();
191 for (var c in lib.declarations.values.where((d) => d is ClassMirror)) { 189 for (var c in lib.declarations.values.where((d) => d is ClassMirror)) {
192 // Search for @CustomTag on classes 190 _loadCustomTags(lib, c, customTags);
193 for (var m in c.metadata) {
194 var meta = m.reflectee;
195 if (meta is CustomTag) {
196 initializers.add(() => Polymer.register(meta.tagName, c.reflectedType));
197 }
198 }
199
200 // TODO(sigmund): check also static methods marked with @initMethod. 191 // TODO(sigmund): check also static methods marked with @initMethod.
201 // This is blocked on two bugs: 192 // This is blocked on two bugs:
202 // - dartbug.com/12133 (static methods are incorrectly listed as top-level 193 // - dartbug.com/12133 (static methods are incorrectly listed as top-level
203 // in dart2js, so they end up being called twice) 194 // in dart2js, so they end up being called twice)
204 // - dartbug.com/12134 (sometimes "method.metadata" throws an exception, 195 // - dartbug.com/12134 (sometimes "method.metadata" throws an exception,
205 // we could wrap and hide those exceptions, but it's not ideal). 196 // we could wrap and hide those exceptions, but it's not ideal).
206 } 197 }
198
199 initializers.addAll(customTags.values);
200 }
201
202 void _loadCustomTags(LibraryMirror lib, ClassMirror cls,
203 LinkedHashMap registerFns) {
204 if (cls == null || cls.reflectedType == HtmlElement) return;
205
206 // Register superclass first.
207 _loadCustomTags(lib, cls.superclass, registerFns);
208
209 if (cls.owner != lib) {
210 // Don't register classes from different libraries.
211 // TODO(jmesserly): @CustomTag does not currently respect re-export, because
212 // LibraryMirror.declarations doesn't include these.
213 return;
214 }
215
216 var meta = _getCustomTagMetadata(cls);
217 if (meta == null) return;
218
219 registerFns.putIfAbsent(cls.reflectedType, () =>
220 () => Polymer.register(meta.tagName, cls.reflectedType));
221 }
222
223 /// Search for @CustomTag on a classemirror
224 CustomTag _getCustomTagMetadata(ClassMirror c) {
225 for (var m in c.metadata) {
226 var meta = m.reflectee;
227 if (meta is CustomTag) return meta;
228 }
229 return null;
207 } 230 }
208 231
209 void _addInitMethod(ObjectMirror obj, MethodMirror method, 232 void _addInitMethod(ObjectMirror obj, MethodMirror method,
210 List<Function> initializers) { 233 List<Function> initializers) {
211 var annotationFound = false; 234 var annotationFound = false;
212 for (var meta in method.metadata) { 235 for (var meta in method.metadata) {
213 if (identical(meta.reflectee, initMethod)) { 236 if (identical(meta.reflectee, initMethod)) {
214 annotationFound = true; 237 annotationFound = true;
215 break; 238 break;
216 } 239 }
217 } 240 }
218 if (!annotationFound) return; 241 if (!annotationFound) return;
219 if (!method.isStatic) { 242 if (!method.isStatic) {
220 print("warning: methods marked with @initMethod should be static," 243 print("warning: methods marked with @initMethod should be static,"
221 " ${method.simpleName} is not."); 244 " ${method.simpleName} is not.");
222 return; 245 return;
223 } 246 }
224 if (!method.parameters.where((p) => !p.isOptional).isEmpty) { 247 if (!method.parameters.where((p) => !p.isOptional).isEmpty) {
225 print("warning: methods marked with @initMethod should take no " 248 print("warning: methods marked with @initMethod should take no "
226 "arguments, ${method.simpleName} expects some."); 249 "arguments, ${method.simpleName} expects some.");
227 return; 250 return;
228 } 251 }
229 initializers.add(() => obj.invoke(method.simpleName, const [])); 252 initializers.add(() => obj.invoke(method.simpleName, const []));
230 } 253 }
231 254
232 class _InitMethodAnnotation { 255 class _InitMethodAnnotation {
233 const _InitMethodAnnotation(); 256 const _InitMethodAnnotation();
234 } 257 }
258
259 /// To ensure Dart can interoperate with polymer-element registered by
260 /// polymer.js, we need to be able to execute Dart code if we are registering
261 /// a Dart class for that element. We trigger Dart logic by patching
262 /// polymer-element's register function and:
263 ///
264 /// * if it has a Dart class, run PolymerDeclaration's register.
265 /// * otherwise it is a JS prototype, run polymer-element's normal register.
266 void _hookJsPolymer() {
267 var polymerJs = js.context['Polymer'];
268 if (polymerJs == null) {
269 throw new StateError('polymer.js must be loaded before polymer.dart, please'
270 ' add <link rel="import" href="packages/polymer/polymer.html"> to your'
271 ' <head> before any Dart scripts. Alternatively you can get a different'
272 ' version of polymer.js by following the instructions at'
273 ' http://www.polymer-project.org; if you do that be sure to include'
274 ' the platform polyfills.');
275 }
276
277 // TODO(jmesserly): dart:js appears to not callback in the correct zone:
278 // https://code.google.com/p/dart/issues/detail?id=17301
279 var zone = Zone.current;
280
281 polymerJs.callMethod('whenPolymerReady',
282 [zone.bindCallback(() => Polymer._ready.complete())]);
283
284 var jsPolymer = new JsObject.fromBrowserObject(
285 document.createElement('polymer-element'));
286
287 var proto = js.context['Object'].callMethod('getPrototypeOf', [jsPolymer]);
288 if (proto is Node) {
289 proto = new JsObject.fromBrowserObject(proto);
290 }
291
292 JsFunction originalRegister = proto['register'];
293 if (originalRegister == null) {
294 throw new StateError('polymer.js must expose "register" function on '
295 'polymer-element to enable polymer.dart to interoperate.');
296 }
297
298 registerDart(jsElem, String name, String extendee) {
299 // By the time we get here, we'll know for sure if it is a Dart object
300 // or not, because polymer-element will wait for us to notify that
301 // the @CustomTag was found.
302 final type = _getRegisteredType(name);
303 if (type != null) {
304 final extendsDecl = _getDeclaration(extendee);
305 return zone.run(() =>
306 new PolymerDeclaration(jsElem, name, type, extendsDecl).register());
307 }
308 // It's a JavaScript polymer element, fall back to the original register.
309 return originalRegister.apply([name, extendee], thisArg: jsElem);
310 }
311
312 proto['register'] = new JsFunction.withThis(registerDart);
313 }
OLDNEW
« no previous file with comments | « pkg/polymer/lib/src/js/use_native_dartium_shadowdom.js ('k') | pkg/polymer/pubspec.yaml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698