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

Side by Side Diff: frog/corejs.dart

Issue 8746005: Fix a bunch of issues with 'hidden' DOM types. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: removed dead code Created 9 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
« no previous file with comments | « no previous file | frog/frogsh » ('j') | frog/lib/corelib.dart » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, 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 * Generates JS helpers for dart:core. This used to be in a file "core.js". 6 * Generates JS helpers for dart:core. This used to be in a file "core.js".
7 * Having them in Dart code means we can easily control which are generated. 7 * Having them in Dart code means we can easily control which are generated.
8 */ 8 */
9 // TODO(jmesserly): one idea to make this cleaner: put these as private "native" 9 // TODO(jmesserly): one idea to make this cleaner: put these as private "native"
10 // methods somewhere in a library that we import. This would be rather elegant 10 // methods somewhere in a library that we import. This would be rather elegant
11 // because they'd get the right name collision behavior, conversions, 11 // because they'd get the right name collision behavior, conversions,
12 // include-if-used, etc for free. Not sure if it's worth doing that. 12 // include-if-used, etc for free. Not sure if it's worth doing that.
13 class CoreJs { 13 class CoreJs {
14 // These values track if the helper is actually used. If it is we generate it. 14 // These values track if the helper is actually used. If it is we generate it.
15 bool useTypeNameOf = false;
16 bool useStackTraceOf = false; 15 bool useStackTraceOf = false;
17 bool useThrow = false; 16 bool useThrow = false;
18 bool useVarMethod = false;
19 bool useGenStub = false; 17 bool useGenStub = false;
20 bool useMap = false; 18 bool useMap = false;
21 bool useAssert = false; 19 bool useAssert = false;
22 bool useNotNullBool = false; 20 bool useNotNullBool = false;
23 bool useIndex = false; 21 bool useIndex = false;
24 bool useSetIndex = false; 22 bool useSetIndex = false;
25 23
26 bool useWrap0 = false; 24 bool useWrap0 = false;
27 bool useWrap1 = false; 25 bool useWrap1 = false;
28 bool useIsolates = false; 26 bool useIsolates = false;
29 27
30 /** An experimental toString implementation. Currently unused. */ 28 /** An experimental toString implementation. Currently unused. */
31 bool useToString = false; 29 bool useToString = false;
32 30
31 // These helpers had to switch to a new pattern, because they can be generated
32 // after everything else.
33 bool _generatedTypeNameOf = false;
34 bool _generatedDynamicProto = false;
35 bool _generatedInherits = false;
36
33 Map<String, String> _usedOperators; 37 Map<String, String> _usedOperators;
34 38
35 CoreJs(): _usedOperators = {}; 39 CodeWriter writer;
40
41 CoreJs(): _usedOperators = {}, writer = new CodeWriter();
36 42
37 /** 43 /**
38 * Generates the special operator method, e.g. $add. 44 * Generates the special operator method, e.g. $add.
39 * We want to do $add(x, y) instead of x.$add(y) so it doesn't box. 45 * We want to do $add(x, y) instead of x.$add(y) so it doesn't box.
40 * Same idea for the other methods. 46 * Same idea for the other methods.
41 */ 47 */
42 void useOperator(String name) { 48 void useOperator(String name) {
43 if (_usedOperators[name] != null) return; 49 if (_usedOperators[name] != null) return;
44 50
45 var code; 51 var code;
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
134 function ${name}(x, y) { 140 function ${name}(x, y) {
135 return (typeof(x) == 'number' && typeof(y) == 'number') 141 return (typeof(x) == 'number' && typeof(y) == 'number')
136 ? x ${op} y : x.${name}(y); 142 ? x ${op} y : x.${name}(y);
137 }"""; 143 }""";
138 break; 144 break;
139 } 145 }
140 146
141 _usedOperators[name] = code; 147 _usedOperators[name] = code;
142 } 148 }
143 149
150 // NOTE: some helpers can't be generated when we generate corelib,
151 // because we don't discover that we need them until later.
152 // Generate on-demand instead
153 void ensureDynamicProto() {
154 if (_generatedDynamicProto) return;
155 _generatedDynamicProto = true;
156
157 ensureTypeNameOf();
158
159 // Usage:
160 // $dynamic(name).SomeTypeName = ... method ...;
161 // $dynamic(name).Object = ... noSuchMethod ...;
162 writer.writeln(@"""
163 function $dynamic(name) {
164 var f = Object.prototype[name];
165 if (f && f.methods) return f.methods;
166
167 var methods = {};
168 if (f) methods.Object = f;
169 function $dynamicBind() {
170 // Find the target method
171 var method;
172 var proto = Object.getPrototypeOf(this);
173 var obj = proto;
174 do {
175 method = methods[obj.$typeNameOf()];
176 if (method) break;
177 obj = Object.getPrototypeOf(obj);
178 } while (obj);
179
180 // Patch the prototype, but don't overwrite an existing stub, like
181 // the one on Object.prototype.
182 if (!proto.hasOwnProperty(name)) proto[name] = method || methods.Object;
183
184 return method.apply(this, Array.prototype.slice.call(arguments));
185 };
186 $dynamicBind.methods = methods;
187 Object.prototype[name] = $dynamicBind;
188 return methods;
189 }""");
190 }
191
192 void ensureTypeNameOf() {
193 if (_generatedTypeNameOf) return;
194 _generatedTypeNameOf = true;
195
196 // TODO(sigmund): find a way to make this work on all browsers, including
197 // checking the typeName on prototype objects (so we can fix dynamic
198 // dispatching on $varMethod).
199 writer.writeln(@"""
200 Object.prototype.$typeNameOf = function() {
201 if ((typeof(window) != 'undefined' && window.constructor.name == 'DOMWindow')
202 || typeof(process) != 'undefined') { // fast-path for Chrome and Node
203 return this.constructor.name;
204 }
205 var str = Object.prototype.toString.call(this);
206 str = str.substring(8, str.length - 1);
207 if (str == 'Window') str = 'DOMWindow';
208 return str;
209 }""");
210 }
211
212
213 /** Generates the $inherits function when it's first used. */
214 ensureInheritsHelper() {
215 if (_generatedInherits) return;
216 _generatedInherits = true;
217
218 writer.writeln(@"""
219 /** Implements extends for Dart classes on JavaScript prototypes. */
220 function $inherits(child, parent) {
221 if (child.prototype.__proto__) {
222 child.prototype.__proto__ = parent.prototype;
223 } else {
224 function tmp() {};
225 tmp.prototype = parent.prototype;
226 child.prototype = new tmp();
227 child.prototype.constructor = child;
228 }
229 }""");
230 }
231
144 void generate(CodeWriter w) { 232 void generate(CodeWriter w) {
145 if (useVarMethod) { 233 // Write any stuff we had queued up, then replace our writer with the one
146 useTypeNameOf = true; 234 // in WorldGenerator so anything we discover that we need later on will be
147 w.writeln(@""" 235 // generated on-demand.
148 function $varMethod(name, methods) { 236 w.write(writer.text);
149 Object.prototype[name] = function() { 237 writer = w;
150 $patchMethod(this, name, methods);
151 return this[name].apply(this, Array.prototype.slice.call(arguments));
152 };
153 }
154 function $patchMethod(obj, name, methods) {
155 // Get the prototype to patch.
156 // Don't overwrite an existing stub, like the one on Object.prototype
157 var proto = Object.getPrototypeOf(obj);
158 if (!proto || proto.hasOwnProperty(name)) proto = obj;
159 var method;
160 while (obj && !(method = methods[obj.$typeNameOf()])) {
161 obj = Object.getPrototypeOf(obj);
162 }
163 obj[name] = method || methods['Object'];
164 }""");
165 }
166 238
167 if (useGenStub) { 239 if (useGenStub) {
168 useThrow = true; 240 useThrow = true;
169 w.writeln(@""" 241 w.writeln(@"""
170 /** 242 /**
171 * Generates a dynamic call stub for a function. 243 * Generates a dynamic call stub for a function.
172 * Our goal is to create a stub method like this on-the-fly: 244 * Our goal is to create a stub method like this on-the-fly:
173 * function($0, $1, capture) { this($0, $1, true, capture); } 245 * function($0, $1, capture) { return this($0, $1, true, capture); }
174 * 246 *
175 * This stub then replaces the dynamic one on Function, with one that is 247 * This stub then replaces the dynamic one on Function, with one that is
176 * specialized for that particular function, taking into account its default 248 * specialized for that particular function, taking into account its default
177 * arguments. 249 * arguments.
178 */ 250 */
179 Function.prototype.$genStub = function(argsLength, names) { 251 Function.prototype.$genStub = function(argsLength, names) {
180 // TODO(jmesserly): only emit $genStub if actually needed
181
182 // Fast path: if no named arguments and arg count matches 252 // Fast path: if no named arguments and arg count matches
183 if (this.length == argsLength && !names) { 253 if (this.length == argsLength && !names) {
184 return this; 254 return this;
185 } 255 }
186 256
187 function $throwArgMismatch() { 257 function $throwArgMismatch() {
188 // TODO(jmesserly): better error message 258 // TODO(jmesserly): better error message
189 $throw(new ClosureArgumentMismatchException()); 259 $throw(new ClosureArgumentMismatchException());
190 } 260 }
191 261
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
246 return (e && e.stack) ? e.stack : null; 316 return (e && e.stack) ? e.stack : null;
247 }"""); 317 }""");
248 } 318 }
249 319
250 if (useNotNullBool) { 320 if (useNotNullBool) {
251 useThrow = true; 321 useThrow = true;
252 // This pattern chosen because IE9 does really badly with typeof, and 322 // This pattern chosen because IE9 does really badly with typeof, and
253 // it's still decent on other browsers. 323 // it's still decent on other browsers.
254 w.writeln(@""" 324 w.writeln(@"""
255 function $notnull_bool(test) { 325 function $notnull_bool(test) {
256 return (test === true || test === false) ? test : test.is$bool(); // TypeError 326 if (test === true || test === false) return test;
327 $throw(new TypeError(test, 'bool'));
257 }"""); 328 }""");
258 } 329 }
259 330
260 if (useAssert) { 331 if (useAssert) {
261 useThrow = true; 332 useThrow = true;
262 w.writeln(@""" 333 w.writeln(@"""
263 function $assert(test, text, url, line, column) { 334 function $assert(test, text, url, line, column) {
264 if (typeof test == 'function') test = test(); 335 if (typeof test == 'function') test = test();
265 if (!test) $throw(new AssertError(text, url, line, column)); 336 if (!test) $throw(new AssertError(text, url, line, column));
266 }"""); 337 }""");
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
298 if (o == null) return 'null'; 369 if (o == null) return 'null';
299 var t = typeof(o); 370 var t = typeof(o);
300 if (t == 'object') { return o.toString(); } 371 if (t == 'object') { return o.toString(); }
301 else if (t == 'string') { return o; } 372 else if (t == 'string') { return o; }
302 else if (t == 'bool') { return ''+o; } 373 else if (t == 'bool') { return ''+o; }
303 else if (t == 'number') { return ''+o; } 374 else if (t == 'number') { return ''+o; }
304 else return o.toString(); 375 else return o.toString();
305 }"""); 376 }""");
306 } 377 }
307 378
308 if (useTypeNameOf) {
309 // TODO(sigmund): find a way to make this work on all browsers, including
310 // checking the typeName on prototype objects (so we can fix dynamic
311 // dispatching on $varMethod).
312 w.writeln(@"""
313 Object.prototype.$typeNameOf = function() {
314 if ((typeof(window) != 'undefined' && window.constructor.name == 'DOMWindow')
315 || typeof(process) != 'undefined') { // fast-path for Chrome and Node
316 return this.constructor.name;
317 }
318 var str = Object.prototype.toString.call(this);
319 str = str.substring(8, str.length - 1);
320 if (str == 'Window')
321 str = 'DOMWindow';
322 return str;
323 }""");
324 }
325
326 if (useIndex) { 379 if (useIndex) {
327 // If not overridden, $index and $setindex fall back to JS [] and []= 380 // If not overridden, $index and $setindex fall back to JS [] and []=
328 // accessors 381 // accessors
329 // TODO(jimhug): This fallback could be very confusing in a few cases - 382 // TODO(jimhug): This fallback could be very confusing in a few cases -
330 // because of the bizare default [] rules in JS. We need to revisit this 383 // because of the bizare default [] rules in JS. We need to revisit this
331 // to get the right errors - at least in checked mode (once we have that). 384 // to get the right errors - at least in checked mode (once we have that).
332 // TODO(jmesserly): do perf analysis, figure out if this is worth it and 385 // TODO(jmesserly): do perf analysis, figure out if this is worth it and
333 // what the cost of $index $setindex is on all browsers 386 // what the cost of $index $setindex is on all browsers
334 w.writeln(@""" 387 w.writeln(@"""
335 Object.prototype.$index = function(i) { return this[i]; } 388 Object.prototype.$index = function(i) { return this[i]; }
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
393 w.writeln(@"function $wrap_call$1(fn) { return fn; }"); 446 w.writeln(@"function $wrap_call$1(fn) { return fn; }");
394 } 447 }
395 } 448 }
396 449
397 // Write operator helpers 450 // Write operator helpers
398 for (var opImpl in orderValuesByKeys(_usedOperators)) { 451 for (var opImpl in orderValuesByKeys(_usedOperators)) {
399 w.writeln(opImpl); 452 w.writeln(opImpl);
400 } 453 }
401 } 454 }
402 } 455 }
OLDNEW
« no previous file with comments | « no previous file | frog/frogsh » ('j') | frog/lib/corelib.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698