OLD | NEW |
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 |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
153 w.writeln(opImpl); | 153 w.writeln(opImpl); |
154 } | 154 } |
155 | 155 |
156 if (world.dom != null) { | 156 if (world.dom != null) { |
157 ensureTypeNameOf(); | 157 ensureTypeNameOf(); |
158 // TODO(jmesserly): we need to find a way to avoid conflicts with other | 158 // TODO(jmesserly): we need to find a way to avoid conflicts with other |
159 // generated "typeName" fields. Ideally we wouldn't be patching 'Object' | 159 // generated "typeName" fields. Ideally we wouldn't be patching 'Object' |
160 // here. | 160 // here. |
161 w.writeln('Object.defineProperty(Object.prototype, "get\$typeName", ' + | 161 w.writeln('Object.defineProperty(Object.prototype, "get\$typeName", ' + |
162 '{ value: Object.prototype.\$typeNameOf, enumerable: false, ' + | 162 '{ value: Object.prototype.\$typeNameOf, enumerable: false, ' + |
163 'configurable: true});'); | 163 'writable: true, configurable: true});'); |
164 } | 164 } |
165 } | 165 } |
166 } | 166 } |
167 | 167 |
168 | 168 |
169 /** Snippet for `$ne`. */ | 169 /** Snippet for `$ne`. */ |
170 final String _NE_FUNCTION = @""" | 170 final String _NE_FUNCTION = @""" |
171 function $ne(x, y) { | 171 function $ne(x, y) { |
172 if (x == null) return y != null; | 172 if (x == null) return y != null; |
173 return (typeof(x) == 'number' && typeof(y) == 'number') || | 173 return (typeof(x) == 'number' && typeof(y) == 'number') || |
174 (typeof(x) == 'boolean' && typeof(y) == 'boolean') || | 174 (typeof(x) == 'boolean' && typeof(y) == 'boolean') || |
175 (typeof(x) == 'string' && typeof(y) == 'string') | 175 (typeof(x) == 'string' && typeof(y) == 'string') |
176 ? x != y : !x.$eq(y); | 176 ? x != y : !x.$eq(y); |
177 }"""; | 177 }"""; |
178 | 178 |
179 /** Snippet for `$eq`. */ | 179 /** Snippet for `$eq`. */ |
180 final String _EQ_FUNCTION = @""" | 180 final String _EQ_FUNCTION = @""" |
181 function $eq(x, y) { | 181 function $eq(x, y) { |
182 if (x == null) return y == null; | 182 if (x == null) return y == null; |
183 return (typeof(x) == 'number' && typeof(y) == 'number') || | 183 return (typeof(x) == 'number' && typeof(y) == 'number') || |
184 (typeof(x) == 'boolean' && typeof(y) == 'boolean') || | 184 (typeof(x) == 'boolean' && typeof(y) == 'boolean') || |
185 (typeof(x) == 'string' && typeof(y) == 'string') | 185 (typeof(x) == 'string' && typeof(y) == 'string') |
186 ? x == y : x.$eq(y); | 186 ? x == y : x.$eq(y); |
187 } | 187 } |
188 // TODO(jimhug): Should this or should it not match equals? | 188 // TODO(jimhug): Should this or should it not match equals? |
189 Object.defineProperty(Object.prototype, '$eq', { value: function(other) { | 189 Object.defineProperty(Object.prototype, '$eq', { value: function(other) { |
190 return this === other; | 190 return this === other; |
191 }, enumerable: false, configurable: true });"""; | 191 }, enumerable: false, writable: true, configurable: true });"""; |
192 | 192 |
193 /** Snippet for `$bit_not`. */ | 193 /** Snippet for `$bit_not`. */ |
194 final String _BIT_NOT_FUNCTION = @""" | 194 final String _BIT_NOT_FUNCTION = @""" |
195 function $bit_not(x) { | 195 function $bit_not(x) { |
196 return (typeof(x) == 'number') ? ~x : x.$bit_not(); | 196 return (typeof(x) == 'number') ? ~x : x.$bit_not(); |
197 }"""; | 197 }"""; |
198 | 198 |
199 /** Snippet for `$negate`. */ | 199 /** Snippet for `$negate`. */ |
200 final String _NEGATE_FUNCTION = @""" | 200 final String _NEGATE_FUNCTION = @""" |
201 function $negate(x) { | 201 function $negate(x) { |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
272 var table = $dynamicMetadata; | 272 var table = $dynamicMetadata; |
273 for (var i = 0; i < table.length; i++) { | 273 for (var i = 0; i < table.length; i++) { |
274 var entry = table[i]; | 274 var entry = table[i]; |
275 if (entry.map.hasOwnProperty(tag)) { | 275 if (entry.map.hasOwnProperty(tag)) { |
276 method = methods[entry.tag]; | 276 method = methods[entry.tag]; |
277 if (method) break; | 277 if (method) break; |
278 } | 278 } |
279 } | 279 } |
280 } | 280 } |
281 method = method || methods.Object; | 281 method = method || methods.Object; |
282 // Patch the prototype, but don't overwrite an existing stub, like | |
283 // the one on Object.prototype. | |
284 var proto = Object.getPrototypeOf(obj); | 282 var proto = Object.getPrototypeOf(obj); |
285 if (!proto.hasOwnProperty(name)) { | 283 if (!proto.hasOwnProperty(name)) { |
286 Object.defineProperty(proto, name, | 284 Object.defineProperty(proto, name, |
287 { value: method, enumerable: false, configurable: true }); | 285 { value: method, enumerable: false, writable: true, |
| 286 configurable: true }); |
288 } | 287 } |
289 | 288 |
290 return method.apply(this, Array.prototype.slice.call(arguments)); | 289 return method.apply(this, Array.prototype.slice.call(arguments)); |
291 }; | 290 }; |
292 $dynamicBind.methods = methods; | 291 $dynamicBind.methods = methods; |
293 Object.defineProperty(Object.prototype, name, { value: $dynamicBind, | 292 Object.defineProperty(Object.prototype, name, { value: $dynamicBind, |
294 enumerable: false, configurable: true}); | 293 enumerable: false, writable: true, configurable: true}); |
295 return methods; | 294 return methods; |
296 } | 295 } |
297 if (typeof $dynamicMetadata == 'undefined') $dynamicMetadata = []; | 296 if (typeof $dynamicMetadata == 'undefined') $dynamicMetadata = []; |
298 | 297 |
299 function $dynamicSetMetadata(inputTable) { | 298 function $dynamicSetMetadata(inputTable) { |
300 // TODO: Deal with light isolates. | 299 // TODO: Deal with light isolates. |
301 var table = []; | 300 var table = []; |
302 for (var i = 0; i < inputTable.length; i++) { | 301 for (var i = 0; i < inputTable.length; i++) { |
303 var tag = inputTable[i][0]; | 302 var tag = inputTable[i][0]; |
304 var tags = inputTable[i][1]; | 303 var tags = inputTable[i][1]; |
(...skipping 16 matching lines...) Expand all Loading... |
321 return this.constructor.name; | 320 return this.constructor.name; |
322 } | 321 } |
323 var str = Object.prototype.toString.call(this); | 322 var str = Object.prototype.toString.call(this); |
324 str = str.substring(8, str.length - 1); | 323 str = str.substring(8, str.length - 1); |
325 if (str == 'Window') { | 324 if (str == 'Window') { |
326 str = 'DOMWindow'; | 325 str = 'DOMWindow'; |
327 } else if (str == 'Document') { | 326 } else if (str == 'Document') { |
328 str = 'HTMLDocument'; | 327 str = 'HTMLDocument'; |
329 } | 328 } |
330 return str; | 329 return str; |
331 }, enumerable: false, configurable: true});"""; | 330 }, enumerable: false, writable: true, configurable: true});"""; |
332 | 331 |
333 /** Snippet for `$inherits`. */ | 332 /** Snippet for `$inherits`. */ |
334 final String _INHERITS_FUNCTION = @""" | 333 final String _INHERITS_FUNCTION = @""" |
335 /** Implements extends for Dart classes on JavaScript prototypes. */ | 334 /** Implements extends for Dart classes on JavaScript prototypes. */ |
336 function $inherits(child, parent) { | 335 function $inherits(child, parent) { |
337 if (child.prototype.__proto__) { | 336 if (child.prototype.__proto__) { |
338 child.prototype.__proto__ = parent.prototype; | 337 child.prototype.__proto__ = parent.prototype; |
339 } else { | 338 } else { |
340 function tmp() {}; | 339 function tmp() {}; |
341 tmp.prototype = parent.prototype; | 340 tmp.prototype = parent.prototype; |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
388 // so many of them. Instead, first time we hit it, put it on the derived | 387 // so many of them. Instead, first time we hit it, put it on the derived |
389 // prototype. TODO(jmesserly): make this go away by handling index more | 388 // prototype. TODO(jmesserly): make this go away by handling index more |
390 // like a normal method. | 389 // like a normal method. |
391 final String _INDEX_OPERATORS = @""" | 390 final String _INDEX_OPERATORS = @""" |
392 Object.defineProperty(Object.prototype, '$index', { value: function(i) { | 391 Object.defineProperty(Object.prototype, '$index', { value: function(i) { |
393 var proto = Object.getPrototypeOf(this); | 392 var proto = Object.getPrototypeOf(this); |
394 if (proto !== Object) { | 393 if (proto !== Object) { |
395 proto.$index = function(i) { return this[i]; } | 394 proto.$index = function(i) { return this[i]; } |
396 } | 395 } |
397 return this[i]; | 396 return this[i]; |
398 }, enumerable: false, configurable: true}); | 397 }, enumerable: false, writable: true, configurable: true}); |
399 Object.defineProperty(Array.prototype, '$index', { value: function(i) { | 398 Object.defineProperty(Array.prototype, '$index', { value: function(i) { |
400 return this[i]; | 399 return this[i]; |
401 }, enumerable: false, configurable: true}); | 400 }, enumerable: false, writable: true, configurable: true}); |
402 Object.defineProperty(String.prototype, '$index', { value: function(i) { | 401 Object.defineProperty(String.prototype, '$index', { value: function(i) { |
403 return this[i]; | 402 return this[i]; |
404 }, enumerable: false, configurable: true});"""; | 403 }, enumerable: false, writable: true, configurable: true});"""; |
405 | 404 |
406 /** Snippet for `$setindex` in Object, Array, and String. */ | 405 /** Snippet for `$setindex` in Object, Array, and String. */ |
407 // TODO(jimhug): Add array bounds checking in checked mode | 406 // TODO(jimhug): Add array bounds checking in checked mode |
408 /* | 407 /* |
409 function $inlineArrayIndexCheck(array, index) { | 408 function $inlineArrayIndexCheck(array, index) { |
410 if (index >= 0 && index < array.length) { | 409 if (index >= 0 && index < array.length) { |
411 return index; | 410 return index; |
412 } | 411 } |
413 native__ArrayJsUtil__throwIndexOutOfRangeException(index); | 412 native__ArrayJsUtil__throwIndexOutOfRangeException(index); |
414 }*/ | 413 }*/ |
415 final String _SETINDEX_OPERATORS = @""" | 414 final String _SETINDEX_OPERATORS = @""" |
416 Object.defineProperty(Object.prototype, '$setindex', { value: function(i, value)
{ | 415 Object.defineProperty(Object.prototype, '$setindex', { value: function(i, value)
{ |
417 var proto = Object.getPrototypeOf(this); | 416 var proto = Object.getPrototypeOf(this); |
418 if (proto !== Object) { | 417 if (proto !== Object) { |
419 proto.$setindex = function(i, value) { return this[i] = value; } | 418 proto.$setindex = function(i, value) { return this[i] = value; } |
420 } | 419 } |
421 return this[i] = value; | 420 return this[i] = value; |
422 }, enumerable: false, configurable: true}); | 421 }, enumerable: false, writable: true, configurable: true}); |
423 Object.defineProperty(Array.prototype, '$setindex', { value: function(i, value)
{ | 422 Object.defineProperty(Array.prototype, '$setindex', { value: function(i, value)
{ |
424 return this[i] = value; }, enumerable: false, configurable: true});"""; | 423 return this[i] = value; }, enumerable: false, writable: true, |
| 424 configurable: true});"""; |
425 | 425 |
426 /** Snippet for `$wrap_call$0`. */ | 426 /** Snippet for `$wrap_call$0`. */ |
427 final String _WRAP_CALL0_FUNCTION = @""" | 427 final String _WRAP_CALL0_FUNCTION = @""" |
428 // Wrap a 0-arg dom-callback to bind it with the current isolate: | 428 // Wrap a 0-arg dom-callback to bind it with the current isolate: |
429 function $wrap_call$0(fn) { return fn && fn.wrap$call$0(); } | 429 function $wrap_call$0(fn) { return fn && fn.wrap$call$0(); } |
430 Function.prototype.wrap$call$0 = function() { | 430 Function.prototype.wrap$call$0 = function() { |
431 var isolateContext = $globalState.currentContext; | 431 var isolateContext = $globalState.currentContext; |
432 var self = this; | 432 var self = this; |
433 this.wrap$0 = function() { | 433 this.wrap$0 = function() { |
434 isolateContext.eval(self); | 434 isolateContext.eval(self); |
(...skipping 24 matching lines...) Expand all Loading... |
459 | 459 |
460 /** Snippet for `$wrap_call$1`, in case it was not necessary. */ | 460 /** Snippet for `$wrap_call$1`, in case it was not necessary. */ |
461 final String _EMPTY_WRAP_CALL1_FUNCTION = | 461 final String _EMPTY_WRAP_CALL1_FUNCTION = |
462 @"function $wrap_call$1(fn) { return fn; }"; | 462 @"function $wrap_call$1(fn) { return fn; }"; |
463 | 463 |
464 /** Snippet that initializes the isolates state. */ | 464 /** Snippet that initializes the isolates state. */ |
465 final String _ISOLATE_INIT_CODE = @""" | 465 final String _ISOLATE_INIT_CODE = @""" |
466 var $globalThis = this; | 466 var $globalThis = this; |
467 var $globals = null; | 467 var $globals = null; |
468 var $globalState = null;"""; | 468 var $globalState = null;"""; |
OLD | NEW |