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

Side by Side Diff: observatory_pub_packages/polymer/src/loader.dart

Issue 816693004: Add observatory_pub_packages snapshot to third_party (Closed) Base URL: http://dart.googlecode.com/svn/third_party/
Patch Set: Created 6 years 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
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 part of polymer;
6
7 /// Annotation used to automatically register polymer elements.
8 class CustomTag {
9 final String tagName;
10 const CustomTag(this.tagName);
11 }
12
13 /// Metadata used to label static or top-level methods that are called
14 /// automatically when loading the library of a custom element.
15 const initMethod = const InitMethodAnnotation();
16
17 /// Implementation behind [initMethod]. Only exposed for internal implementation
18 /// details
19 class InitMethodAnnotation {
20 const InitMethodAnnotation();
21 }
22
23 /// Initializes a polymer application as follows:
24 /// * if running in development mode, set up a dirty-checking zone that polls
25 /// for observable changes
26 /// * initialize template binding and polymer-element
27 /// * for each library included transitively from HTML and HTML imports,
28 /// register custom elements declared there (labeled with [CustomTag]) and
29 /// invoke the initialization method on it (top-level functions annotated with
30 /// [initMethod]).
31 Zone initPolymer() {
32 _initializeLogging();
33 if (loader.deployMode) {
34 startPolymer(loader.initializers, loader.deployMode);
35 return Zone.current;
36 }
37 return dirtyCheckZone()..run(
38 () => startPolymer(loader.initializers, loader.deployMode));
39 }
40
41 /// True if we're in deployment mode.
42 bool _deployMode = false;
43
44 bool _startPolymerCalled = false;
45
46 /// Starts polymer by running all [initializers] and hooking the polymer.js
47 /// code. **Note**: this function is not meant to be invoked directly by
48 /// application developers. It is invoked either by [initPolymer] or, if you are
49 /// using the experimental bootstrap API, this would be invoked by an entry
50 /// point that is automatically generated somehow. In particular, during
51 /// development, the entry point would be generated dynamically in `boot.js`.
52 /// Similarly, pub-build would generate the entry point for deployment.
53 void startPolymer(List<Function> initializers, [bool deployMode = true]) {
54 if (_startPolymerCalled) throw 'Initialization was already done.';
55 _startPolymerCalled = true;
56 _hookJsPolymer();
57 _deployMode = deployMode;
58
59 if (initializers == null) {
60 throw 'Missing initialization of polymer elements. '
61 'Please check that the list of entry points in your pubspec.yaml '
62 'is correct. If you are using pub-serve, you may need to restart it.';
63 }
64
65 Polymer.registerSync('auto-binding-dart', AutoBindingElement,
66 extendsTag: 'template');
67
68 for (var initializer in initializers) {
69 initializer();
70 }
71
72 _watchWaitingFor();
73 }
74
75 /// Configures [initPolymer] making it optimized for deployment to the internet.
76 /// With this setup the initializer list is supplied instead of searched for
77 /// at runtime. Additionally, after this method is called [initPolymer] omits
78 /// the [Zone] that automatically invokes [Observable.dirtyCheck].
79 void configureForDeployment(List<Function> initializers) {
80 loader.initializers = initializers;
81 loader.deployMode = true;
82 }
83
84 /// To ensure Dart can interoperate with polymer-element registered by
85 /// polymer.js, we need to be able to execute Dart code if we are registering
86 /// a Dart class for that element. We trigger Dart logic by patching
87 /// polymer-element's register function and:
88 ///
89 /// * if it has a Dart class, run PolymerDeclaration's register.
90 /// * otherwise it is a JS prototype, run polymer-element's normal register.
91 void _hookJsPolymer() {
92 var polymerJs = js.context['Polymer'];
93 if (polymerJs == null) {
94 throw new StateError('polymer.js must be loaded before polymer.dart, please'
95 ' add <link rel="import" href="packages/polymer/polymer.html"> to your'
96 ' <head> before any Dart scripts. Alternatively you can get a different'
97 ' version of polymer.js by following the instructions at'
98 ' http://www.polymer-project.org.');
99 }
100
101 // TODO(jmesserly): dart:js appears to not callback in the correct zone:
102 // https://code.google.com/p/dart/issues/detail?id=17301
103 var zone = Zone.current;
104
105 polymerJs.callMethod('whenPolymerReady',
106 [zone.bindCallback(() => Polymer._onReady.complete())]);
107
108 JsFunction originalRegister = _polymerElementProto['register'];
109 if (originalRegister == null) {
110 throw new StateError('polymer.js must expose "register" function on '
111 'polymer-element to enable polymer.dart to interoperate.');
112 }
113
114 registerDart(jsElem, String name, String extendee) {
115 // By the time we get here, we'll know for sure if it is a Dart object
116 // or not, because polymer-element will wait for us to notify that
117 // the @CustomTag was found.
118 final type = _getRegisteredType(name);
119 if (type != null) {
120 final extendsDecl = _getDeclaration(extendee);
121 return zone.run(() =>
122 new PolymerDeclaration(jsElem, name, type, extendsDecl).register());
123 }
124 // It's a JavaScript polymer element, fall back to the original register.
125 return originalRegister.apply([name, extendee], thisArg: jsElem);
126 }
127
128 _polymerElementProto['register'] = new JsFunction.withThis(registerDart);
129 }
130
131 // Note: we cache this so we can use it later to look up 'init'.
132 // See registerSync.
133 JsObject _polymerElementProto = () {
134 var polyElem = document.createElement('polymer-element');
135 var proto = new JsObject.fromBrowserObject(polyElem)['__proto__'];
136 if (proto is Node) proto = new JsObject.fromBrowserObject(proto);
137 return proto;
138 }();
139
140 // Add support for the polymer js style of enabling logging. The global logging
141 // level is respected for specified loggers (see http://goo.gl/btfDe1). All
142 // other loggers will be set to [Level.OFF]. Logs will also be printed to the
143 // console automatically if any are supplied.
144 void _initializeLogging() {
145 hierarchicalLoggingEnabled = true;
146 var webComponents = js.context['WebComponents'];
147 var logFlags = (webComponents == null || webComponents['flags'] == null) ? {}
148 : webComponents['flags']['log'];
149 if (logFlags == null) logFlags = {};
150 var loggers =
151 [_observeLog, _eventsLog, _unbindLog, _bindLog, _watchLog, _readyLog];
152 var polymerLogger = new Logger('polymer');
153
154 // If no loggers specified then disable globally and return.
155 if (!loggers.any((logger) => logFlags[logger.name] == true)) {
156 polymerLogger.level = Level.OFF;
157 return;
158 }
159
160 // Disable the loggers that were not specified.
161 loggers.where((logger) => logFlags[logger.name] != true)
162 .forEach((logger) {logger.level = Level.OFF;});
163
164 // Listen to the polymer logs and print them to the console.
165 polymerLogger.onRecord.listen((rec) {print(rec);});
166 }
167
168 /// Watches the waitingFor queue and if it fails to make progress then prints
169 /// a message to the console.
170 void _watchWaitingFor() {
171 int lastWaiting = Polymer.waitingFor.length;
172 int lastAlert;
173 new Timer.periodic(new Duration(seconds: 1), (Timer timer) {
174 var waiting = Polymer.waitingFor;
175 // Done, cancel timer.
176 if (waiting.isEmpty) {
177 timer.cancel();
178 return;
179 }
180 // Made progress, don't alert.
181 if (waiting.length != lastWaiting) {
182 lastWaiting = waiting.length;
183 return;
184 }
185 // Only alert once per waiting state.
186 if (lastAlert == lastWaiting) return;
187 lastAlert = lastWaiting;
188
189 print('No elements registered in a while, but still waiting on '
190 '${waiting.length} elements to be registered. Check that you have a '
191 'class with an @CustomTag annotation for each of the following tags: '
192 '${waiting.map((e) => "'${e.attributes['name']}'").join(', ')}');
193 });
194 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698