Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 var dart, _js_helper, _js_primitives; | 5 var dart, _js_helper, _js_primitives, dartx; |
| 6 (function (dart) { | 6 (function (dart) { |
| 7 'use strict'; | 7 'use strict'; |
| 8 | 8 |
| 9 // TODO(vsm): This is referenced (as init.globalState) from | 9 // TODO(vsm): This is referenced (as init.globalState) from |
| 10 // isolate_helper.dart. Where should it go? | 10 // isolate_helper.dart. Where should it go? |
| 11 // See: https://github.com/dart-lang/dev_compiler/issues/164 | 11 // See: https://github.com/dart-lang/dev_compiler/issues/164 |
| 12 dart.globalState = null; | 12 dart.globalState = null; |
| 13 | 13 |
| 14 let defineProperty = Object.defineProperty; | 14 const defineProperty = Object.defineProperty; |
| 15 let getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; | 15 const getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; |
| 16 let getOwnPropertyNames = Object.getOwnPropertyNames; | 16 const getOwnPropertyNames = Object.getOwnPropertyNames; |
| 17 let getOwnPropertySymbols = Object.getOwnPropertySymbols; | 17 const getOwnPropertySymbols = Object.getOwnPropertySymbols; |
| 18 const hasOwnProperty = Object.prototype.hasOwnProperty; | |
| 19 const slice = [].slice; | |
| 18 | 20 |
| 19 function getOwnNamesAndSymbols(obj) { | 21 function getOwnNamesAndSymbols(obj) { |
| 20 return getOwnPropertyNames(obj).concat(getOwnPropertySymbols(obj)); | 22 return getOwnPropertyNames(obj).concat(getOwnPropertySymbols(obj)); |
| 21 } | 23 } |
| 22 | 24 |
| 23 // Adapted from Angular.js | |
| 24 let FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m; | |
| 25 let FN_ARG_SPLIT = /,/; | |
| 26 let FN_ARG = /^\s*(_?)(\S+?)\1\s*$/; | |
| 27 let STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg; | |
| 28 | |
| 29 function formalParameterList(fn) { | |
| 30 let fnText,argDecl; | |
| 31 let args=[]; | |
| 32 fnText = fn.toString().replace(STRIP_COMMENTS, ''); | |
| 33 argDecl = fnText.match(FN_ARGS); | |
| 34 | |
| 35 let r = argDecl[1].split(FN_ARG_SPLIT); | |
| 36 for (let arg of r) { | |
| 37 arg.replace(FN_ARG, function(all, underscore, name){ | |
| 38 args.push(name); | |
| 39 }); | |
| 40 } | |
| 41 return args; | |
| 42 } | |
| 43 | |
| 44 function dload(obj, field) { | 25 function dload(obj, field) { |
| 45 field = _canonicalFieldName(obj, field); | 26 field = _canonicalFieldName(obj, field, []); |
| 46 if (_getMethodType(obj, field) !== void 0) { | 27 if (_getMethodType(obj, field) !== void 0) { |
| 47 return dart.bind(obj, field); | 28 return dart.bind(obj, field); |
| 48 } | 29 } |
| 49 // TODO(vsm): Implement NSM robustly. An 'in' check breaks on certain | 30 // TODO(vsm): Implement NSM robustly. An 'in' check breaks on certain |
| 50 // types. hasOwnProperty doesn't chase the proto chain. | 31 // types. hasOwnProperty doesn't chase the proto chain. |
| 51 // Also, do we want an NSM on regular JS objects? | 32 // Also, do we want an NSM on regular JS objects? |
| 52 // See: https://github.com/dart-lang/dev_compiler/issues/169 | 33 // See: https://github.com/dart-lang/dev_compiler/issues/169 |
| 53 var result = obj[field]; | 34 var result = obj[field]; |
| 54 | 35 |
| 55 // TODO(leafp): Decide whether to keep this for javascript | 36 // TODO(vsm): Check this more robustly. |
| 56 // objects, or just use the javascript semantics. | 37 if (typeof result == "function" && !hasOwnProperty.call(obj, field)) { |
| 57 if (typeof result == "function" && | |
| 58 !Object.prototype.hasOwnProperty.call(obj, field)) { | |
| 59 // This appears to be a method tearoff. Bind this. | 38 // This appears to be a method tearoff. Bind this. |
| 60 return result.bind(obj); | 39 return result.bind(obj); |
| 61 } | 40 } |
| 62 return result; | 41 return result; |
| 63 } | 42 } |
| 64 dart.dload = dload; | 43 dart.dload = dload; |
| 65 | 44 |
| 66 function dput(obj, field, value) { | 45 function dput(obj, field, value) { |
| 67 field = _canonicalFieldName(obj, field); | 46 field = _canonicalFieldName(obj, field, [value]); |
| 68 // TODO(vsm): Implement NSM and type checks. | 47 // TODO(vsm): Implement NSM and type checks. |
| 69 // See: https://github.com/dart-lang/dev_compiler/issues/170 | 48 // See: https://github.com/dart-lang/dev_compiler/issues/170 |
| 70 obj[field] = value; | 49 obj[field] = value; |
| 71 } | 50 } |
| 72 dart.dput = dput; | 51 dart.dput = dput; |
| 73 | 52 |
| 74 // TODO(jmesserly): this should call noSuchMethod, not throw. | 53 // TODO(jmesserly): this should call noSuchMethod, not throw. |
| 75 function throwNoSuchMethod(obj, name, args, opt_func) { | 54 function throwNoSuchMethod(obj, name, args, opt_func) { |
| 76 if (obj === void 0) obj = opt_func; | 55 if (obj === void 0) obj = opt_func; |
| 77 throw new core.NoSuchMethodError(obj, name, args); | 56 throw new core.NoSuchMethodError(obj, name, args); |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 105 if (ftype.checkApply(args)) { | 84 if (ftype.checkApply(args)) { |
| 106 return f.apply(obj, args); | 85 return f.apply(obj, args); |
| 107 } | 86 } |
| 108 | 87 |
| 109 // TODO(leafp): throw a type error (rather than NSM) | 88 // TODO(leafp): throw a type error (rather than NSM) |
| 110 // if the arity matches but the types are wrong. | 89 // if the arity matches but the types are wrong. |
| 111 throwNoSuchMethod(obj, name, args, f); | 90 throwNoSuchMethod(obj, name, args, f); |
| 112 } | 91 } |
| 113 | 92 |
| 114 function dcall(f/*, ...args*/) { | 93 function dcall(f/*, ...args*/) { |
| 115 let args = Array.prototype.slice.call(arguments, 1); | 94 let args = slice.call(arguments, 1); |
| 116 let ftype = _getFunctionType(f); | 95 let ftype = _getFunctionType(f); |
| 117 return checkAndCall(f, ftype, void 0, args, 'call'); | 96 return checkAndCall(f, ftype, void 0, args, 'call'); |
| 118 } | 97 } |
| 119 dart.dcall = dcall; | 98 dart.dcall = dcall; |
| 120 | 99 |
| 121 // TODO(vsm): Automatically build this. | 100 let _extensionType = Symbol('extensionType'); |
| 122 // All dynamic methods should check for these. | 101 function _canonicalFieldName(obj, name, args, displayName) { |
| 123 // See: https://github.com/dart-lang/dev_compiler/issues/142 | 102 if (obj[_extensionType]) { |
| 124 var _extensionMethods = { | 103 var extension = dartx[name]; |
| 125 // Lazy - as these symbols may not be loaded yet. | 104 if (extension) return extension; |
| 126 // TODO(vsm): This should record / check the receiver type | 105 // TODO(jmesserly): in the future we might have types that "overlay" Dart |
| 127 // as well. E.g., only look for core.$map if the receiver | 106 // methods while also exposing the full native API, e.g. dart:html vs |
| 128 // is an Iterable. | 107 // dart:dom. To support that we'd need to fall back to the normal name |
| 129 'map': () => core.$map, | 108 // if an extension method wasn't found. |
| 130 }; | 109 throwNoSuchMethod(obj, displayName, args); |
|
vsm
2015/06/02 17:59:10
displayName isn't passed in by dload / dput above.
Jennifer Messerly
2015/06/04 21:31:18
Done.
| |
| 131 | 110 } |
| 132 // TODO(leafp): Integrate this with the eventual proper extension | |
| 133 // method system. | |
| 134 function _canonicalFieldName(obj, name) { | |
| 135 if (obj[name] === void 0) return _extensionMethods[name](); | |
| 136 return name; | 111 return name; |
| 137 } | 112 } |
| 138 | 113 |
| 114 /** Shared code for dsend, dindex, and dsetindex. */ | |
| 115 function callMethod(obj, name, displayName, args) { | |
|
Leaf
2015/06/02 21:35:04
Slightly confusing that callMethod and _canonicalF
Jennifer Messerly
2015/06/04 21:31:18
Done.
| |
| 116 let symbol = _canonicalFieldName(obj, name, args, displayName); | |
| 117 let f = obj[symbol]; | |
| 118 let ftype = _getMethodType(obj, name); | |
| 119 return checkAndCall(f, ftype, obj, args, displayName); | |
| 120 } | |
| 121 | |
| 139 function dsend(obj, method/*, ...args*/) { | 122 function dsend(obj, method/*, ...args*/) { |
| 140 let args = Array.prototype.slice.call(arguments, 2); | 123 return callMethod(obj, method, method, slice.call(arguments, 2)); |
| 141 let symbol = _canonicalFieldName(obj, method); | |
| 142 let f = obj[symbol]; | |
| 143 let ftype = _getMethodType(obj, symbol); | |
| 144 return checkAndCall(f, ftype, obj, args, method); | |
| 145 } | 124 } |
| 146 dart.dsend = dsend; | 125 dart.dsend = dsend; |
| 147 | 126 |
| 148 function dindex(obj, index) { | 127 function dindex(obj, index) { |
| 149 // TODO(jmesserly): remove this special case once Array extensions are | 128 return callMethod(obj, 'get', '[]', [index]); |
| 150 // hooked up. | |
| 151 if (obj instanceof Array && realRuntimeType(index) == core.int) { | |
| 152 return obj[index]; | |
| 153 } | |
| 154 return checkAndCall(obj.get, void 0, obj, [index], '[]'); | |
| 155 } | 129 } |
| 156 dart.dindex = dindex; | 130 dart.dindex = dindex; |
| 157 | 131 |
| 158 function dsetindex(obj, index, value) { | 132 function dsetindex(obj, index, value) { |
| 159 return checkAndCall(obj.set, void 0, obj, [index, value], '[]='); | 133 return callMethod(obj, 'set', '[]=', [index, value]); |
| 160 } | 134 } |
| 161 dart.dsetindex = dsetindex; | 135 dart.dsetindex = dsetindex; |
| 162 | 136 |
| 163 function typeToString(type) { | 137 function typeToString(type) { |
| 164 if (typeof(type) == "function") { | 138 if (typeof(type) == "function") { |
| 165 var name = type.name; | 139 var name = type.name; |
| 166 var args = type[dart.typeArguments]; | 140 var args = type[dart.typeArguments]; |
| 167 if (args) { | 141 if (args) { |
| 168 name += '<'; | 142 name += '<'; |
| 169 for (var i = 0; i < args.length; ++i) { | 143 for (var i = 0; i < args.length; ++i) { |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 192 console.log('Warning: ignoring cast fail from ' + typeToString(actual) + ' to ' + typeToString(type)); | 166 console.log('Warning: ignoring cast fail from ' + typeToString(actual) + ' to ' + typeToString(type)); |
| 193 return obj; | 167 return obj; |
| 194 } | 168 } |
| 195 // console.log('Error: cast fail from ' + typeToString(actual) + ' to ' + ty peToString(type)); | 169 // console.log('Error: cast fail from ' + typeToString(actual) + ' to ' + ty peToString(type)); |
| 196 throw new _js_helper.CastErrorImplementation(actual, type); | 170 throw new _js_helper.CastErrorImplementation(actual, type); |
| 197 } | 171 } |
| 198 dart.as = cast; | 172 dart.as = cast; |
| 199 | 173 |
| 200 | 174 |
| 201 // TODO(vsm): How should we encode the runtime type? | 175 // TODO(vsm): How should we encode the runtime type? |
| 202 let _runtimeType = Symbol('_runtimeType'); | 176 const _runtimeType = Symbol('_runtimeType'); |
| 203 | 177 |
| 204 function checkPrimitiveType(obj) { | 178 function checkPrimitiveType(obj) { |
| 205 switch (typeof obj) { | 179 switch (typeof obj) { |
| 206 case "undefined": | 180 case "undefined": |
| 207 return core.Null; | 181 return core.Null; |
| 208 case "number": | 182 case "number": |
| 209 return Math.floor(obj) == obj ? core.int : core.double; | 183 return Math.floor(obj) == obj ? core.int : core.double; |
| 210 case "boolean": | 184 case "boolean": |
| 211 return core.bool; | 185 return core.bool; |
| 212 case "string": | 186 case "string": |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 261 if (t === Array) return core.List; | 235 if (t === Array) return core.List; |
| 262 | 236 |
| 263 // We shouldn't normally get here with these types, unless something strange | 237 // We shouldn't normally get here with these types, unless something strange |
| 264 // happens like subclassing Number in JS and passing it to Dart. | 238 // happens like subclassing Number in JS and passing it to Dart. |
| 265 if (t === String) return core.String; | 239 if (t === String) return core.String; |
| 266 if (t === Number) return core.double; | 240 if (t === Number) return core.double; |
| 267 if (t === Boolean) return core.bool; | 241 if (t === Boolean) return core.bool; |
| 268 return t; | 242 return t; |
| 269 } | 243 } |
| 270 | 244 |
| 271 let subtypeMap = new Map(); | 245 const subtypeMap = new Map(); |
| 272 function isSubtype(t1, t2) { | 246 function isSubtype(t1, t2) { |
| 273 // See if we already know the answer | 247 // See if we already know the answer |
| 274 // TODO(jmesserly): general purpose memoize function? | 248 // TODO(jmesserly): general purpose memoize function? |
| 275 let map = subtypeMap.get(t1); | 249 let map = subtypeMap.get(t1); |
| 276 let result; | 250 let result; |
| 277 if (map) { | 251 if (map) { |
| 278 result = map.get(t2); | 252 result = map.get(t2); |
| 279 if (result !== void 0) return result; | 253 if (result !== void 0) return result; |
| 280 } else { | 254 } else { |
| 281 subtypeMap.set(t1, map = new Map()); | 255 subtypeMap.set(t1, map = new Map()); |
| (...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 565 function fn(closure/* ...args*/) { | 539 function fn(closure/* ...args*/) { |
| 566 // Closure and a lazy type constructor | 540 // Closure and a lazy type constructor |
| 567 if (arguments.length == 2) { | 541 if (arguments.length == 2) { |
| 568 defineLazyProperty(closure, _runtimeType, {get : arguments[1]}); | 542 defineLazyProperty(closure, _runtimeType, {get : arguments[1]}); |
| 569 return closure; | 543 return closure; |
| 570 } | 544 } |
| 571 var t; | 545 var t; |
| 572 if (arguments.length == 1) { | 546 if (arguments.length == 1) { |
| 573 // No type arguments, it's all dynamic | 547 // No type arguments, it's all dynamic |
| 574 let len = closure.length; | 548 let len = closure.length; |
| 575 function build() { | 549 let build = () => { |
| 576 let args = Array.apply(null, new Array(len)).map(() => core.Object); | 550 let args = Array.apply(null, new Array(len)).map(() => core.Object); |
| 577 return functionType(core.Object, args); | 551 return functionType(core.Object, args); |
| 578 } | 552 }; |
| 579 // We could be called before Object is defined. | 553 // We could be called before Object is defined. |
| 580 if (core.Object === void 0) return fn(closure, build); | 554 if (core.Object === void 0) return fn(closure, build); |
| 581 t = build(); | 555 t = build(); |
| 582 } else { | 556 } else { |
| 583 // We're passed the piecewise components of the function type, | 557 // We're passed the piecewise components of the function type, |
| 584 // construct it. | 558 // construct it. |
| 585 let args = Array.prototype.slice.call(arguments, 1); | 559 let args = slice.call(arguments, 1); |
| 586 t = functionType.apply(null, args); | 560 t = functionType.apply(null, args); |
| 587 } | 561 } |
| 588 setRuntimeType(closure, t); | 562 setRuntimeType(closure, t); |
| 589 return closure; | 563 return closure; |
| 590 } | 564 } |
| 591 dart.fn = fn; | 565 dart.fn = fn; |
| 592 | 566 |
| 593 function functionType(returnType, args, extra) { | 567 function functionType(returnType, args, extra) { |
| 594 // TODO(vsm): Cache / memomize? | 568 // TODO(vsm): Cache / memomize? |
| 595 var optionals; | 569 var optionals; |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 792 | 766 |
| 793 /** | 767 /** |
| 794 * Copy properties from source to destination object. | 768 * Copy properties from source to destination object. |
| 795 * This operation is commonly called `mixin` in JS. | 769 * This operation is commonly called `mixin` in JS. |
| 796 */ | 770 */ |
| 797 function copyProperties(to, from) { | 771 function copyProperties(to, from) { |
| 798 return copyPropertiesHelper(to, from, getOwnNamesAndSymbols(from)); | 772 return copyPropertiesHelper(to, from, getOwnNamesAndSymbols(from)); |
| 799 } | 773 } |
| 800 dart.copyProperties = copyProperties; | 774 dart.copyProperties = copyProperties; |
| 801 | 775 |
| 776 function getExtensionSymbol(name) { | |
| 777 let sym = dartx[name]; | |
| 778 if (!sym) dartx[name] = sym = Symbol('dartx.' + name); | |
| 779 return sym; | |
| 780 } | |
| 781 | |
| 802 /** | 782 /** |
| 803 * Copy symbols from the prototype of the source to destination. | 783 * Copy symbols from the prototype of the source to destination. |
| 804 * These are the only properties safe to copy onto an existing public | 784 * These are the only properties safe to copy onto an existing public |
| 805 * JavaScript class. | 785 * JavaScript class. |
| 806 */ | 786 */ |
| 807 function registerExtension(to, from) { | 787 function registerExtension(jsType, dartExtType) { |
| 808 return copyPropertiesHelper(to.prototype, from.prototype, | 788 let extProto = dartExtType.prototype; |
| 809 getOwnPropertySymbols(from.prototype)); | 789 let jsProto = jsType.prototype; |
| 790 | |
| 791 // Mark the JS type's instances so we can easily check for extensions. | |
| 792 jsProto[_extensionType] = extProto; | |
|
vsm
2015/06/02 17:59:10
assert that this isn't already defined?
Jennifer Messerly
2015/06/04 21:31:18
Done.
| |
| 793 for (let name of getOwnPropertyNames(extProto)) { | |
| 794 let symbol = getExtensionSymbol(name); | |
| 795 defineProperty(jsProto, symbol, getOwnPropertyDescriptor(extProto, name)); | |
| 796 } | |
| 810 } | 797 } |
| 811 dart.registerExtension = registerExtension; | 798 dart.registerExtension = registerExtension; |
| 812 | 799 |
| 800 /** | |
| 801 * Mark a concrete type as implementing extension methods. | |
| 802 * For example: `class MyIter implements Iterable`. | |
| 803 * | |
| 804 * Because it's implementing `Iterable` for the first time, it needs to | |
| 805 * define the extension method symbols and have them call the normal Dart | |
| 806 * method with the corresponding name. | |
| 807 * | |
| 808 * Unfortunately we have no way of knowing what interface members are, so | |
| 809 * we just forward everything. These calls are only generated to static types | |
| 810 * like `List list;` so it won't confuse dynamic dispatch. | |
| 811 */ | |
| 812 function implementExtension(type) { | |
|
vsm
2015/06/02 17:59:10
Hmm, you're calling this everywhere with a second
Jennifer Messerly
2015/06/02 18:16:04
Sigh, I wish we could. The doc comment above expla
vsm
2015/06/03 15:48:39
General thoughts:
(1) it's worth declaring the se
Jennifer Messerly
2015/06/04 21:31:18
Update: redesigned this. We now emit extension met
| |
| 813 let proto = type.prototype; | |
| 814 for (let name of getOwnPropertyNames(proto)) { | |
| 815 // TODO(jmesserly): skip named ctors as well | |
| 816 if (name == type.name || name == 'constructor') continue; | |
| 817 let symbol = getExtensionSymbol(name); | |
| 818 defineProperty(proto, symbol, getOwnPropertyDescriptor(proto, name)); | |
|
Jennifer Messerly
2015/06/02 23:43:42
Oops. Just noticed, this needs to generate a stub
vsm
2015/06/03 15:48:40
Good catch. :-)
Jennifer Messerly
2015/06/04 21:31:18
fixed now.
| |
| 819 } | |
| 820 } | |
| 821 dart.implementExtension = implementExtension; | |
| 822 | |
| 813 function setBaseClass(derived, base) { | 823 function setBaseClass(derived, base) { |
| 814 // Link the extension to the type it's extending as a base class. | 824 // Link the extension to the type it's extending as a base class. |
| 815 derived.prototype.__proto__ = base.prototype; | 825 derived.prototype.__proto__ = base.prototype; |
| 816 } | 826 } |
| 817 dart.setBaseClass = setBaseClass; | 827 dart.setBaseClass = setBaseClass; |
| 818 | 828 |
| 819 /** | 829 /** |
| 820 * This is called whenever a derived class needs to introduce a new field, | 830 * This is called whenever a derived class needs to introduce a new field, |
| 821 * shadowing a field or getter/setter pair on its parent. | 831 * shadowing a field or getter/setter pair on its parent. |
| 822 * | 832 * |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 847 * | 857 * |
| 848 * Each mixin applies in sequence, with further to the right ones overriding | 858 * Each mixin applies in sequence, with further to the right ones overriding |
| 849 * previous entries. | 859 * previous entries. |
| 850 * | 860 * |
| 851 * For each mixin, we only take its own properties, not anything from its | 861 * For each mixin, we only take its own properties, not anything from its |
| 852 * superclass (prototype). | 862 * superclass (prototype). |
| 853 */ | 863 */ |
| 854 function mixin(base/*, ...mixins*/) { | 864 function mixin(base/*, ...mixins*/) { |
| 855 // Create an initializer for the mixin, so when derived constructor calls | 865 // Create an initializer for the mixin, so when derived constructor calls |
| 856 // super, we can correctly initialize base and mixins. | 866 // super, we can correctly initialize base and mixins. |
| 857 let mixins = Array.prototype.slice.call(arguments, 1); | 867 let mixins = slice.call(arguments, 1); |
| 858 | 868 |
| 859 // Create a class that will hold all of the mixin methods. | 869 // Create a class that will hold all of the mixin methods. |
| 860 class Mixin extends base { | 870 class Mixin extends base { |
| 861 // Initializer method: run mixin initializers, then the base. | 871 // Initializer method: run mixin initializers, then the base. |
| 862 [base.name](/*...args*/) { | 872 [base.name](/*...args*/) { |
| 863 // Run mixin initializers. They cannot have arguments. | 873 // Run mixin initializers. They cannot have arguments. |
| 864 // Run them backwards so most-derived mixin is initialized first. | 874 // Run them backwards so most-derived mixin is initialized first. |
| 865 for (let i = mixins.length - 1; i >= 0; i--) { | 875 for (let i = mixins.length - 1; i >= 0; i--) { |
| 866 let mixin = mixins[i]; | 876 let mixin = mixins[i]; |
| 867 let init = mixin.prototype[mixin.name]; | 877 let init = mixin.prototype[mixin.name]; |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 935 function throw_(obj) { throw obj; } | 945 function throw_(obj) { throw obj; } |
| 936 dart.throw_ = throw_; | 946 dart.throw_ = throw_; |
| 937 | 947 |
| 938 /** | 948 /** |
| 939 * Given a class and an initializer method name, creates a constructor | 949 * Given a class and an initializer method name, creates a constructor |
| 940 * function with the same name. For example `new SomeClass.name(args)`. | 950 * function with the same name. For example `new SomeClass.name(args)`. |
| 941 */ | 951 */ |
| 942 function defineNamedConstructor(clazz, name) { | 952 function defineNamedConstructor(clazz, name) { |
| 943 let proto = clazz.prototype; | 953 let proto = clazz.prototype; |
| 944 let initMethod = proto[name]; | 954 let initMethod = proto[name]; |
| 945 let ctor = function() { return initMethod.apply(this, arguments); } | 955 let ctor = function() { return initMethod.apply(this, arguments); }; |
| 946 ctor.prototype = proto; | 956 ctor.prototype = proto; |
| 947 // Use defineProperty so we don't hit a property defined on Function, | 957 // Use defineProperty so we don't hit a property defined on Function, |
| 948 // like `caller` and `arguments`. | 958 // like `caller` and `arguments`. |
| 949 defineProperty(clazz, name, { value: ctor, configurable: true }); | 959 defineProperty(clazz, name, { value: ctor, configurable: true }); |
| 950 } | 960 } |
| 951 dart.defineNamedConstructor = defineNamedConstructor; | 961 dart.defineNamedConstructor = defineNamedConstructor; |
| 952 | 962 |
| 953 function stackTrace(exception) { | 963 function stackTrace(exception) { |
| 954 return _js_helper.getTraceFromException(exception); | 964 return _js_helper.getTraceFromException(exception); |
| 955 } | 965 } |
| 956 dart.stackTrace = stackTrace; | 966 dart.stackTrace = stackTrace; |
| 957 | 967 |
| 958 /** The Symbol for storing type arguments on a specialized generic type. */ | 968 /** The Symbol for storing type arguments on a specialized generic type. */ |
| 959 dart.typeArguments = Symbol('typeArguments'); | 969 dart.typeArguments = Symbol('typeArguments'); |
| 960 dart.originalDeclaration = Symbol('originalDeclaration'); | 970 dart.originalDeclaration = Symbol('originalDeclaration'); |
| 961 | 971 |
| 962 /** Memoize a generic type constructor function. */ | 972 /** Memoize a generic type constructor function. */ |
| 963 function generic(typeConstructor) { | 973 function generic(typeConstructor) { |
| 964 let length = typeConstructor.length; | 974 let length = typeConstructor.length; |
| 965 if (length < 1) throw Error('must have at least one generic type argument'); | 975 if (length < 1) throw Error('must have at least one generic type argument'); |
| 966 | 976 |
| 967 let resultMap = new Map(); | 977 let resultMap = new Map(); |
| 968 function makeGenericType(/*...arguments*/) { | 978 function makeGenericType(/*...arguments*/) { |
| 969 if (arguments.length != length && arguments.length != 0) { | 979 if (arguments.length != length && arguments.length != 0) { |
| 970 throw Error('requires ' + length + ' or 0 type arguments'); | 980 throw Error('requires ' + length + ' or 0 type arguments'); |
| 971 } | 981 } |
| 972 let args = Array.prototype.slice.call(arguments); | 982 let args = slice.call(arguments); |
| 973 // TODO(leafp): This should really be core.Object for | 983 // TODO(leafp): This should really be core.Object for |
| 974 // consistency, but Object is not attached to core | 984 // consistency, but Object is not attached to core |
| 975 // until the entire core library has been processed, | 985 // until the entire core library has been processed, |
| 976 // which is too late. | 986 // which is too late. |
| 977 while (args.length < length) args.push(dart.dynamic); | 987 while (args.length < length) args.push(dart.dynamic); |
| 978 | 988 |
| 979 let value = resultMap; | 989 let value = resultMap; |
| 980 for (let i = 0; i < length; i++) { | 990 for (let i = 0; i < length; i++) { |
| 981 let arg = args[i]; | 991 let arg = args[i]; |
| 982 if (arg == null) { | 992 if (arg == null) { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1014 } | 1024 } |
| 1015 | 1025 |
| 1016 /// Get the type of a method using the stored signature | 1026 /// Get the type of a method using the stored signature |
| 1017 function _getMethodType(obj, name) { | 1027 function _getMethodType(obj, name) { |
| 1018 if (obj === void 0) return void 0; | 1028 if (obj === void 0) return void 0; |
| 1019 if (obj == null) return void 0; | 1029 if (obj == null) return void 0; |
| 1020 let sigObj = obj.__proto__.constructor[_methodSig]; | 1030 let sigObj = obj.__proto__.constructor[_methodSig]; |
| 1021 if (sigObj === void 0) return void 0; | 1031 if (sigObj === void 0) return void 0; |
| 1022 let parts = sigObj[name]; | 1032 let parts = sigObj[name]; |
| 1023 if (parts === void 0) return void 0; | 1033 if (parts === void 0) return void 0; |
| 1024 let sig = functionType.apply(null, parts); | 1034 return functionType.apply(null, parts); |
| 1025 return sig; | |
| 1026 } | 1035 } |
| 1027 | 1036 |
| 1028 /// Get the type of a constructor from a class using the stored signature | 1037 /// Get the type of a constructor from a class using the stored signature |
| 1029 /// If name is undefined, returns the type of the default constructor | 1038 /// If name is undefined, returns the type of the default constructor |
| 1030 /// Returns undefined if the constructor is not found. | 1039 /// Returns undefined if the constructor is not found. |
| 1031 function _getConstructorType(cls, name) { | 1040 function _getConstructorType(cls, name) { |
| 1032 if(!name) name = cls.name; | 1041 if(!name) name = cls.name; |
| 1033 if (cls === void 0) return void 0; | 1042 if (cls === void 0) return void 0; |
| 1034 if (cls == null) return void 0; | 1043 if (cls == null) return void 0; |
| 1035 let sigCtor = cls[_constructorSig]; | 1044 let sigCtor = cls[_constructorSig]; |
| 1036 if (sigCtor === void 0) return void 0; | 1045 if (sigCtor === void 0) return void 0; |
| 1037 let parts = sigCtor[name]; | 1046 let parts = sigCtor[name]; |
| 1038 if (parts === void 0) return void 0; | 1047 if (parts === void 0) return void 0; |
| 1039 let sig = functionType.apply(null, parts); | 1048 return functionType.apply(null, parts); |
| 1040 return sig; | |
| 1041 } | 1049 } |
| 1042 dart.classGetConstructorType = _getConstructorType; | 1050 dart.classGetConstructorType = _getConstructorType; |
| 1043 | 1051 |
| 1044 /// Given an object and a method name, tear off the method. | 1052 /// Given an object and a method name, tear off the method. |
| 1045 /// Sets the runtime type of the torn off method appropriately, | 1053 /// Sets the runtime type of the torn off method appropriately, |
| 1046 /// and also binds the object. | 1054 /// and also binds the object. |
| 1047 /// TODO(leafp): Consider caching the tearoff on the object? | 1055 /// TODO(leafp): Consider caching the tearoff on the object? |
| 1048 function bind(obj, name) { | 1056 function bind(obj, name) { |
| 1049 let f = obj[name].bind(obj); | 1057 let f = obj[name].bind(obj); |
| 1050 let sig = _getMethodType(obj, name) | 1058 let sig = _getMethodType(obj, name); |
| 1051 assert(sig); | 1059 assert(sig); |
| 1052 setRuntimeType(f, sig); | 1060 setRuntimeType(f, sig); |
| 1053 return f; | 1061 return f; |
| 1054 } | 1062 } |
| 1055 dart.bind = bind; | 1063 dart.bind = bind; |
| 1056 | 1064 |
| 1057 // Set up the method signature field on the constructor | 1065 // Set up the method signature field on the constructor |
| 1058 function _setMethodSignature(f, sigF) { | 1066 function _setMethodSignature(f, sigF) { |
| 1059 defineMemoizedGetter(f, _methodSig, () => { | 1067 defineMemoizedGetter(f, _methodSig, () => { |
| 1060 let sigObj = sigF(); | 1068 let sigObj = sigF(); |
| 1061 sigObj.__proto__ = f.__proto__[_methodSig]; | 1069 sigObj.__proto__ = f.__proto__[_methodSig]; |
| 1062 return sigObj; | 1070 return sigObj; |
| 1063 }); | 1071 }); |
| 1064 } | 1072 } |
| 1065 | 1073 |
| 1066 // Set up the constructor signature field on the constructor | 1074 // Set up the constructor signature field on the constructor |
| 1067 function _setConstructorSignature(f, sigF) { | 1075 function _setConstructorSignature(f, sigF) { |
| 1068 defineMemoizedGetter(f, _constructorSig, sigF); | 1076 defineMemoizedGetter(f, _constructorSig, sigF); |
| 1069 } | 1077 } |
| 1070 | 1078 |
| 1071 // Set up the static signature field on the constructor | 1079 // Set up the static signature field on the constructor |
| 1072 function _setStaticSignature(f, sigF) { | 1080 function _setStaticSignature(f, sigF) { |
| 1073 defineMemoizedGetter(f, _staticSig, sigF); | 1081 defineMemoizedGetter(f, _staticSig, sigF); |
| 1074 } | 1082 } |
| 1075 | 1083 |
| 1076 // Set the lazily computed runtime type field on static methods | 1084 // Set the lazily computed runtime type field on static methods |
| 1077 function _setStaticTypes(f, names) { | 1085 function _setStaticTypes(f, names) { |
| 1078 for (let name of names) { | 1086 for (let name of names) { |
| 1079 function getT() { | 1087 defineProperty(f[name], _runtimeType, { get: function() { |
| 1080 let parts = f[_staticSig][name]; | 1088 let parts = f[_staticSig][name]; |
| 1081 return functionType.apply(null, parts); | 1089 return functionType.apply(null, parts); |
| 1082 }; | 1090 }}); |
| 1083 defineProperty(f[name], _runtimeType, {get : getT}); | |
| 1084 } | 1091 } |
| 1085 } | 1092 } |
| 1086 | 1093 |
| 1087 /// Set up the type signature of a class (constructor object) | 1094 /// Set up the type signature of a class (constructor object) |
| 1088 /// f is a constructor object | 1095 /// f is a constructor object |
| 1089 /// signature is an object containing optional properties as follows: | 1096 /// signature is an object containing optional properties as follows: |
| 1090 /// methods: A function returning an object mapping method names | 1097 /// methods: A function returning an object mapping method names |
| 1091 /// to method types. The function is evaluated lazily and cached. | 1098 /// to method types. The function is evaluated lazily and cached. |
| 1092 /// statics: A function returning an object mapping static method | 1099 /// statics: A function returning an object mapping static method |
| 1093 /// names to types. The function is evalutated lazily and cached. | 1100 /// names to types. The function is evalutated lazily and cached. |
| 1094 /// names: An array of the names of the static methods. Used to | 1101 /// names: An array of the names of the static methods. Used to |
| 1095 /// permit eagerly setting the runtimeType field on the methods | 1102 /// permit eagerly setting the runtimeType field on the methods |
| 1096 /// while still lazily computing the type descriptor object. | 1103 /// while still lazily computing the type descriptor object. |
| 1097 function setSignature(f, signature) { | 1104 function setSignature(f, signature) { |
| 1098 let constructors = | 1105 let constructors = |
| 1099 ('constructors' in signature) ? signature.constructors : () => ({}); | 1106 ('constructors' in signature) ? signature.constructors : () => ({}); |
| 1100 let methods = | 1107 let methods = |
| 1101 ('methods' in signature) ? signature.methods : () => ({}); | 1108 ('methods' in signature) ? signature.methods : () => ({}); |
| 1102 let statics = | 1109 let statics = |
| 1103 ('statics' in signature) ? signature.statics : () => ({}); | 1110 ('statics' in signature) ? signature.statics : () => ({}); |
| 1104 let names = | 1111 let names = |
| 1105 ('names' in signature) ? signature.names : []; | 1112 ('names' in signature) ? signature.names : []; |
| 1106 _setConstructorSignature(f, constructors); | 1113 _setConstructorSignature(f, constructors); |
| 1107 _setMethodSignature(f, methods); | 1114 _setMethodSignature(f, methods); |
| 1108 _setStaticSignature(f, statics); | 1115 _setStaticSignature(f, statics); |
| 1109 _setStaticTypes(f, names); | 1116 _setStaticTypes(f, names); |
| 1110 }; | 1117 } |
| 1111 dart.setSignature = setSignature; | 1118 dart.setSignature = setSignature; |
| 1112 | 1119 |
| 1113 let _value = Symbol('_value'); | 1120 let _value = Symbol('_value'); |
| 1114 /** | 1121 /** |
| 1115 * Looks up a sequence of [keys] in [map], recursively, and | 1122 * Looks up a sequence of [keys] in [map], recursively, and |
| 1116 * returns the result. If the value is not found, [valueFn] will be called to | 1123 * returns the result. If the value is not found, [valueFn] will be called to |
| 1117 * add it. For example: | 1124 * add it. For example: |
| 1118 * | 1125 * |
| 1119 * var map = new Map(); | 1126 * var map = new Map(); |
| 1120 * putIfAbsent(map, [1, 2, 'hi ', 'there '], () => 'world'); | 1127 * putIfAbsent(map, [1, 2, 'hi ', 'there '], () => 'world'); |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 1133 } | 1140 } |
| 1134 map = value; | 1141 map = value; |
| 1135 } | 1142 } |
| 1136 if (map.has(_value)) return map.get(_value); | 1143 if (map.has(_value)) return map.get(_value); |
| 1137 let value = valueFn(); | 1144 let value = valueFn(); |
| 1138 map.set(_value, value); | 1145 map.set(_value, value); |
| 1139 return value; | 1146 return value; |
| 1140 } | 1147 } |
| 1141 | 1148 |
| 1142 /** The global constant table. */ | 1149 /** The global constant table. */ |
| 1143 let constants = new Map(); | 1150 const constants = new Map(); |
| 1144 | 1151 |
| 1145 /** | 1152 /** |
| 1146 * Canonicalize a constant object. | 1153 * Canonicalize a constant object. |
| 1147 * | 1154 * |
| 1148 * Preconditions: | 1155 * Preconditions: |
| 1149 * - `obj` is an objects or array, not a primitive. | 1156 * - `obj` is an objects or array, not a primitive. |
| 1150 * - nested values of the object are themselves already canonicalized. | 1157 * - nested values of the object are themselves already canonicalized. |
| 1151 */ | 1158 */ |
| 1152 function constant(obj) { | 1159 function constant(obj) { |
| 1153 let objectKey = [realRuntimeType(obj)]; | 1160 let objectKey = [realRuntimeType(obj)]; |
| 1154 // There's no guarantee in JS that names/symbols are returned in the same | 1161 // TODO(jmesserly): there's no guarantee in JS that names/symbols are |
| 1155 // order. We could probably get the same order if we're judicious about | 1162 // returned in the same order. |
| 1156 // initializing them, but easier to not depend on that. | 1163 // |
| 1164 // We could probably get the same order if we're judicious about | |
| 1165 // initializing fields in a consistent order across all const constructors. | |
| 1166 // Alternatively we need a way to sort them to make consistent. | |
| 1167 // | |
| 1168 // Right now we use the (name,value) pairs in sequence, which prevents | |
| 1169 // an object with incorrect field values being returned, but won't | |
| 1170 // canonicalize correctly if key order is different. | |
| 1157 for (let name of getOwnNamesAndSymbols(obj)) { | 1171 for (let name of getOwnNamesAndSymbols(obj)) { |
| 1158 // TODO(jmesserly): we can make this faster if needed. | |
| 1159 objectKey.push(name); | 1172 objectKey.push(name); |
| 1160 objectKey.push(obj[name]); | 1173 objectKey.push(obj[name]); |
| 1161 } | 1174 } |
| 1162 return multiKeyPutIfAbsent(constants, objectKey, () => obj); | 1175 return multiKeyPutIfAbsent(constants, objectKey, () => obj); |
| 1163 } | 1176 } |
| 1164 dart.const = constant; | 1177 dart.const = constant; |
| 1165 | 1178 |
| 1166 // TODO(vsm): Rationalize these type methods. We're currently using the | 1179 // TODO(vsm): Rationalize these type methods. We're currently using the |
| 1167 // setType / proto scheme for nominal types (e.g., classes) and the | 1180 // setType / proto scheme for nominal types (e.g., classes) and the |
| 1168 // setRuntimeType / field scheme for structural types (e.g., functions | 1181 // setRuntimeType / field scheme for structural types (e.g., functions |
| 1169 // - and only in tests for now). | 1182 // - and only in tests for now). |
| 1170 // See: https://github.com/dart-lang/dev_compiler/issues/172 | 1183 // See: https://github.com/dart-lang/dev_compiler/issues/172 |
| 1171 | 1184 |
| 1172 /** Sets the type of `obj` to be `type` */ | 1185 /** Sets the type of `obj` to be `type` */ |
| 1173 function setType(obj, type) { | 1186 function setType(obj, type) { |
| 1174 obj.__proto__ = type.prototype; | 1187 obj.__proto__ = type.prototype; |
| 1175 return obj; | 1188 return obj; |
| 1176 } | 1189 } |
| 1177 dart.setType = setType; | 1190 dart.setType = setType; |
| 1178 | 1191 |
| 1192 /** Sets the element type of a list literal. */ | |
| 1193 function list(obj, elementType) { | |
| 1194 return setType(obj, _interceptors.JSArray$(elementType)); | |
| 1195 } | |
| 1196 dart.list = list; | |
| 1197 | |
| 1179 /** Sets the internal runtime type of `obj` to be `type` */ | 1198 /** Sets the internal runtime type of `obj` to be `type` */ |
| 1180 function setRuntimeType(obj, type) { | 1199 function setRuntimeType(obj, type) { |
| 1181 obj[_runtimeType] = type; | 1200 obj[_runtimeType] = type; |
| 1182 } | 1201 } |
| 1183 dart.setRuntimeType = setRuntimeType; | 1202 dart.setRuntimeType = setRuntimeType; |
| 1184 | 1203 |
| 1185 // The following are helpers for Object methods when the receiver | 1204 // The following are helpers for Object methods when the receiver |
| 1186 // may be null or primitive. These should only be generated by | 1205 // may be null or primitive. These should only be generated by |
| 1187 // the compiler. | 1206 // the compiler. |
| 1188 function hashCode(obj) { | 1207 function hashCode(obj) { |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1275 } | 1294 } |
| 1276 dart.defineLibrary = defineLibrary; | 1295 dart.defineLibrary = defineLibrary; |
| 1277 | 1296 |
| 1278 // TODO(jmesserly): hack to bootstrap the SDK | 1297 // TODO(jmesserly): hack to bootstrap the SDK |
| 1279 _js_helper = _js_helper || {}; | 1298 _js_helper = _js_helper || {}; |
| 1280 _js_helper.checkNum = notNull; | 1299 _js_helper.checkNum = notNull; |
| 1281 | 1300 |
| 1282 _js_primitives = _js_primitives || {}; | 1301 _js_primitives = _js_primitives || {}; |
| 1283 _js_primitives.printString = (s) => console.log(s); | 1302 _js_primitives.printString = (s) => console.log(s); |
| 1284 | 1303 |
| 1285 // TODO(vsm): Plumb this correctly. | |
| 1286 // See: https://github.com/dart-lang/dev_compiler/issues/40 | |
| 1287 String.prototype.contains = function(sub) { return this.indexOf(sub) >= 0; } | |
| 1288 let _split = String.prototype.split; | |
| 1289 String.prototype.split = function() { | |
| 1290 let result = _split.apply(this, arguments); | |
| 1291 dart.setType(result, core.List$(core.String)); | |
| 1292 return result; | |
| 1293 } | |
| 1294 String.prototype.get = function(i) { | |
| 1295 return this[i]; | |
| 1296 } | |
| 1297 String.prototype.codeUnitAt = function(i) { | |
| 1298 return this.charCodeAt(i); | |
| 1299 } | |
| 1300 String.prototype.replaceAllMapped = function(from, cb) { | |
| 1301 return this.replace(from.multiple, function() { | |
| 1302 // Remove offset & string from the result array | |
| 1303 var matches = arguments; | |
| 1304 matches.splice(-2, 2); | |
| 1305 // The callback receives match, p1, ..., pn | |
| 1306 return cb(matches); | |
| 1307 }); | |
| 1308 } | |
| 1309 String.prototype['+'] = function(arg) { return this.valueOf() + arg; }; | |
| 1310 | |
| 1311 Boolean.prototype['!'] = function() { return !this.valueOf(); }; | |
| 1312 Boolean.prototype['&&'] = function(arg) { return this.valueOf() && arg; }; | |
| 1313 Boolean.prototype['||'] = function(arg) { return this.valueOf() || arg; }; | |
| 1314 Number.prototype['<'] = function(arg) { return this.valueOf() < arg; }; | |
| 1315 Number.prototype['<='] = function(arg) { return this.valueOf() <= arg; }; | |
| 1316 Number.prototype['>'] = function(arg) { return this.valueOf() > arg; }; | |
| 1317 Number.prototype['+'] = function(arg) { return this.valueOf() + arg; }; | |
| 1318 | |
| 1319 // TODO(vsm): DOM facades? | 1304 // TODO(vsm): DOM facades? |
| 1320 // See: https://github.com/dart-lang/dev_compiler/issues/173 | 1305 // See: https://github.com/dart-lang/dev_compiler/issues/173 |
| 1321 NodeList.prototype.get = function(i) { return this[i]; }; | 1306 NodeList.prototype.get = function(i) { return this[i]; }; |
| 1322 NamedNodeMap.prototype.get = function(i) { return this[i]; }; | 1307 NamedNodeMap.prototype.get = function(i) { return this[i]; }; |
| 1323 DOMTokenList.prototype.get = function(i) { return this[i]; }; | 1308 DOMTokenList.prototype.get = function(i) { return this[i]; }; |
| 1324 | 1309 |
| 1310 /** Dart extension members. */ | |
| 1311 dartx = dartx || {}; | |
| 1312 | |
| 1325 })(dart || (dart = {})); | 1313 })(dart || (dart = {})); |
| OLD | NEW |