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

Side by Side Diff: lib/runtime/dart_runtime.js

Issue 1153003003: fixes #40, extension methods for primitive types (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
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
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
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 = {}));
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698