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 |