| 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 |