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

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
« no previous file with comments | « lib/runtime/dart/typed_data.js ('k') | lib/src/checker/resolver.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 function dload(obj, field) { 25 function dload(obj, field) {
24 field = _canonicalFieldName(obj, field); 26 field = _canonicalFieldName(obj, field, [], field);
25 if (_getMethodType(obj, field) !== void 0) { 27 if (_getMethodType(obj, field) !== void 0) {
26 return dart.bind(obj, field); 28 return dart.bind(obj, field);
27 } 29 }
28 // TODO(vsm): Implement NSM robustly. An 'in' check breaks on certain 30 // TODO(vsm): Implement NSM robustly. An 'in' check breaks on certain
29 // types. hasOwnProperty doesn't chase the proto chain. 31 // types. hasOwnProperty doesn't chase the proto chain.
30 // Also, do we want an NSM on regular JS objects? 32 // Also, do we want an NSM on regular JS objects?
31 // See: https://github.com/dart-lang/dev_compiler/issues/169 33 // See: https://github.com/dart-lang/dev_compiler/issues/169
32 var result = obj[field]; 34 var result = obj[field];
33 35
34 // TODO(leafp): Decide whether to keep this for javascript 36 // TODO(vsm): Check this more robustly.
35 // objects, or just use the javascript semantics. 37 if (typeof result == "function" && !hasOwnProperty.call(obj, field)) {
36 if (typeof result == "function" &&
37 !Object.prototype.hasOwnProperty.call(obj, field)) {
38 // This appears to be a method tearoff. Bind this. 38 // This appears to be a method tearoff. Bind this.
39 return result.bind(obj); 39 return result.bind(obj);
40 } 40 }
41 return result; 41 return result;
42 } 42 }
43 dart.dload = dload; 43 dart.dload = dload;
44 44
45 function dput(obj, field, value) { 45 function dput(obj, field, value) {
46 field = _canonicalFieldName(obj, field); 46 field = _canonicalFieldName(obj, field, [value], field);
47 // TODO(vsm): Implement NSM and type checks. 47 // TODO(vsm): Implement NSM and type checks.
48 // See: https://github.com/dart-lang/dev_compiler/issues/170 48 // See: https://github.com/dart-lang/dev_compiler/issues/170
49 obj[field] = value; 49 obj[field] = value;
50 } 50 }
51 dart.dput = dput; 51 dart.dput = dput;
52 52
53 // TODO(jmesserly): this should call noSuchMethod, not throw. 53 // TODO(jmesserly): this should call noSuchMethod, not throw.
54 function throwNoSuchMethod(obj, name, args, opt_func) { 54 function throwNoSuchMethod(obj, name, args, opt_func) {
55 if (obj === void 0) obj = opt_func; 55 if (obj === void 0) obj = opt_func;
56 throw new core.NoSuchMethodError(obj, name, args); 56 throw new core.NoSuchMethodError(obj, name, args);
(...skipping 27 matching lines...) Expand all
84 if (ftype.checkApply(args)) { 84 if (ftype.checkApply(args)) {
85 return f.apply(obj, args); 85 return f.apply(obj, args);
86 } 86 }
87 87
88 // TODO(leafp): throw a type error (rather than NSM) 88 // TODO(leafp): throw a type error (rather than NSM)
89 // if the arity matches but the types are wrong. 89 // if the arity matches but the types are wrong.
90 throwNoSuchMethod(obj, name, args, f); 90 throwNoSuchMethod(obj, name, args, f);
91 } 91 }
92 92
93 function dcall(f/*, ...args*/) { 93 function dcall(f/*, ...args*/) {
94 let args = Array.prototype.slice.call(arguments, 1); 94 let args = slice.call(arguments, 1);
95 let ftype = _getFunctionType(f); 95 let ftype = _getFunctionType(f);
96 return checkAndCall(f, ftype, void 0, args, 'call'); 96 return checkAndCall(f, ftype, void 0, args, 'call');
97 } 97 }
98 dart.dcall = dcall; 98 dart.dcall = dcall;
99 99
100 // TODO(vsm): Automatically build this. 100 let _extensionType = Symbol('extensionType');
101 // All dynamic methods should check for these. 101 function _canonicalFieldName(obj, name, args, displayName) {
102 // See: https://github.com/dart-lang/dev_compiler/issues/142 102 if (obj[_extensionType]) {
103 var _extensionMethods = { 103 var extension = dartx[name];
104 // Lazy - as these symbols may not be loaded yet. 104 if (extension) return extension;
105 // TODO(vsm): This should record / check the receiver type 105 // TODO(jmesserly): in the future we might have types that "overlay" Dart
106 // 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
107 // is an Iterable. 107 // dart:dom. To support that we'd need to fall back to the normal name
108 'map': () => core.$map 108 // if an extension method wasn't found.
109 }; 109 throwNoSuchMethod(obj, displayName, args);
110 110 }
111 // TODO(leafp): Integrate this with the eventual proper extension
112 // method system.
113 function _canonicalFieldName(obj, name) {
114 if (obj[name] === void 0) return _extensionMethods[name]();
115 return name; 111 return name;
116 } 112 }
117 113
114 /** Shared code for dsend, dindex, and dsetindex. */
115 function callMethod(obj, name, args, displayName) {
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
118 function dsend(obj, method/*, ...args*/) { 122 function dsend(obj, method/*, ...args*/) {
119 let args = Array.prototype.slice.call(arguments, 2); 123 return callMethod(obj, method, slice.call(arguments, 2));
120 let symbol = _canonicalFieldName(obj, method);
121 let f = obj[symbol];
122 let ftype = _getMethodType(obj, symbol);
123 return checkAndCall(f, ftype, obj, args, method);
124 } 124 }
125 dart.dsend = dsend; 125 dart.dsend = dsend;
126 126
127 function dindex(obj, index) { 127 function dindex(obj, index) {
128 // TODO(jmesserly): remove this special case once Array extensions are 128 return callMethod(obj, 'get', [index], '[]');
129 // hooked up.
130 if (obj instanceof Array && realRuntimeType(index) == core.int) {
131 return obj[index];
132 }
133 return checkAndCall(obj.get, void 0, obj, [index], '[]');
134 } 129 }
135 dart.dindex = dindex; 130 dart.dindex = dindex;
136 131
137 function dsetindex(obj, index, value) { 132 function dsetindex(obj, index, value) {
138 return checkAndCall(obj.set, void 0, obj, [index, value], '[]='); 133 return callMethod(obj, 'set', [index, value], '[]=');
139 } 134 }
140 dart.dsetindex = dsetindex; 135 dart.dsetindex = dsetindex;
141 136
142 function typeToString(type) { 137 function typeToString(type) {
143 if (typeof(type) == "function") { 138 if (typeof(type) == "function") {
144 var name = type.name; 139 var name = type.name;
145 var args = type[dart.typeArguments]; 140 var args = type[dart.typeArguments];
146 if (args) { 141 if (args) {
147 name += '<'; 142 name += '<';
148 for (var i = 0; i < args.length; ++i) { 143 for (var i = 0; i < args.length; ++i) {
(...skipping 22 matching lines...) Expand all
171 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));
172 return obj; 167 return obj;
173 } 168 }
174 // 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));
175 throw new _js_helper.CastErrorImplementation(actual, type); 170 throw new _js_helper.CastErrorImplementation(actual, type);
176 } 171 }
177 dart.as = cast; 172 dart.as = cast;
178 173
179 174
180 // TODO(vsm): How should we encode the runtime type? 175 // TODO(vsm): How should we encode the runtime type?
181 let _runtimeType = Symbol('_runtimeType'); 176 const _runtimeType = Symbol('_runtimeType');
182 177
183 function checkPrimitiveType(obj) { 178 function checkPrimitiveType(obj) {
184 switch (typeof obj) { 179 switch (typeof obj) {
185 case "undefined": 180 case "undefined":
186 return core.Null; 181 return core.Null;
187 case "number": 182 case "number":
188 return Math.floor(obj) == obj ? core.int : core.double; 183 return Math.floor(obj) == obj ? core.int : core.double;
189 case "boolean": 184 case "boolean":
190 return core.bool; 185 return core.bool;
191 case "string": 186 case "string":
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
240 if (t === Array) return core.List; 235 if (t === Array) return core.List;
241 236
242 // 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
243 // happens like subclassing Number in JS and passing it to Dart. 238 // happens like subclassing Number in JS and passing it to Dart.
244 if (t === String) return core.String; 239 if (t === String) return core.String;
245 if (t === Number) return core.double; 240 if (t === Number) return core.double;
246 if (t === Boolean) return core.bool; 241 if (t === Boolean) return core.bool;
247 return t; 242 return t;
248 } 243 }
249 244
250 let subtypeMap = new Map(); 245 const subtypeMap = new Map();
251 function isSubtype(t1, t2) { 246 function isSubtype(t1, t2) {
252 // See if we already know the answer 247 // See if we already know the answer
253 // TODO(jmesserly): general purpose memoize function? 248 // TODO(jmesserly): general purpose memoize function?
254 let map = subtypeMap.get(t1); 249 let map = subtypeMap.get(t1);
255 let result; 250 let result;
256 if (map) { 251 if (map) {
257 result = map.get(t2); 252 result = map.get(t2);
258 if (result !== void 0) return result; 253 if (result !== void 0) return result;
259 } else { 254 } else {
260 subtypeMap.set(t1, map = new Map()); 255 subtypeMap.set(t1, map = new Map());
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after
554 let build = () => { 549 let build = () => {
555 let args = Array.apply(null, new Array(len)).map(() => core.Object); 550 let args = Array.apply(null, new Array(len)).map(() => core.Object);
556 return functionType(core.Object, args); 551 return functionType(core.Object, args);
557 }; 552 };
558 // We could be called before Object is defined. 553 // We could be called before Object is defined.
559 if (core.Object === void 0) return fn(closure, build); 554 if (core.Object === void 0) return fn(closure, build);
560 t = build(); 555 t = build();
561 } else { 556 } else {
562 // We're passed the piecewise components of the function type, 557 // We're passed the piecewise components of the function type,
563 // construct it. 558 // construct it.
564 let args = Array.prototype.slice.call(arguments, 1); 559 let args = slice.call(arguments, 1);
565 t = functionType.apply(null, args); 560 t = functionType.apply(null, args);
566 } 561 }
567 setRuntimeType(closure, t); 562 setRuntimeType(closure, t);
568 return closure; 563 return closure;
569 } 564 }
570 dart.fn = fn; 565 dart.fn = fn;
571 566
572 function functionType(returnType, args, extra) { 567 function functionType(returnType, args, extra) {
573 // TODO(vsm): Cache / memomize? 568 // TODO(vsm): Cache / memomize?
574 var optionals; 569 var optionals;
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
771 766
772 /** 767 /**
773 * Copy properties from source to destination object. 768 * Copy properties from source to destination object.
774 * This operation is commonly called `mixin` in JS. 769 * This operation is commonly called `mixin` in JS.
775 */ 770 */
776 function copyProperties(to, from) { 771 function copyProperties(to, from) {
777 return copyPropertiesHelper(to, from, getOwnNamesAndSymbols(from)); 772 return copyPropertiesHelper(to, from, getOwnNamesAndSymbols(from));
778 } 773 }
779 dart.copyProperties = copyProperties; 774 dart.copyProperties = copyProperties;
780 775
776 function getExtensionSymbol(name) {
777 let sym = dartx[name];
778 if (!sym) dartx[name] = sym = Symbol('dartx.' + name);
779 return sym;
780 }
781
781 /** 782 /**
782 * Copy symbols from the prototype of the source to destination. 783 * Copy symbols from the prototype of the source to destination.
783 * 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
784 * JavaScript class. 785 * JavaScript class.
785 */ 786 */
786 function registerExtension(to, from) { 787 function registerExtension(jsType, dartExtType) {
787 return copyPropertiesHelper(to.prototype, from.prototype, 788 let extProto = dartExtType.prototype;
788 getOwnPropertySymbols(from.prototype)); 789 let jsProto = jsType.prototype;
790
791 // Mark the JS type's instances so we can easily check for extensions.
792 assert(jsProto[_extensionType] === void 0);
793 jsProto[_extensionType] = extProto;
794 for (let name of getOwnPropertyNames(extProto)) {
795 let symbol = getExtensionSymbol(name);
796 defineProperty(jsProto, symbol, getOwnPropertyDescriptor(extProto, name));
797 }
789 } 798 }
790 dart.registerExtension = registerExtension; 799 dart.registerExtension = registerExtension;
791 800
801 /**
802 * Mark a concrete type as implementing extension methods.
803 * For example: `class MyIter implements Iterable`.
804 *
805 * This takes a list of names, which are the extension methods implemented.
806 * It will add a forwarder, so the extension method name redirects to the
807 * normal Dart method name. For example:
808 *
809 * defineExtensionMembers(MyType, ['add', 'remove']);
810 *
811 * Results in:
812 *
813 * MyType.prototype[dartx.add] = MyType.prototype.add;
814 * MyType.prototype[dartx.remove] = MyType.prototype.remove;
815 */
816 // TODO(jmesserly): essentially this gives two names to the same method.
817 // This benefit is roughly equivalent call performance either way, but the
818 // cost is we need to call implementExtension any time a subclass overrides
819 // one of these methods.
vsm 2015/06/04 21:50:02 I see. So, the virtual dispatch is happening on f
Jennifer Messerly 2015/06/04 21:57:46 exactly. If we wanted to do it the other way, we'd
820 function defineExtensionMembers(type, methodNames) {
821 let proto = type.prototype;
822 for (let name of methodNames) {
823 let method = getOwnPropertyDescriptor(proto, name);
824 defineProperty(proto, getExtensionSymbol(name), method);
825 }
826 }
827 dart.defineExtensionMembers = defineExtensionMembers;
828
792 function setBaseClass(derived, base) { 829 function setBaseClass(derived, base) {
793 // Link the extension to the type it's extending as a base class. 830 // Link the extension to the type it's extending as a base class.
794 derived.prototype.__proto__ = base.prototype; 831 derived.prototype.__proto__ = base.prototype;
795 } 832 }
796 dart.setBaseClass = setBaseClass; 833 dart.setBaseClass = setBaseClass;
797 834
798 /** 835 /**
799 * This is called whenever a derived class needs to introduce a new field, 836 * This is called whenever a derived class needs to introduce a new field,
800 * shadowing a field or getter/setter pair on its parent. 837 * shadowing a field or getter/setter pair on its parent.
801 * 838 *
(...skipping 24 matching lines...) Expand all
826 * 863 *
827 * Each mixin applies in sequence, with further to the right ones overriding 864 * Each mixin applies in sequence, with further to the right ones overriding
828 * previous entries. 865 * previous entries.
829 * 866 *
830 * For each mixin, we only take its own properties, not anything from its 867 * For each mixin, we only take its own properties, not anything from its
831 * superclass (prototype). 868 * superclass (prototype).
832 */ 869 */
833 function mixin(base/*, ...mixins*/) { 870 function mixin(base/*, ...mixins*/) {
834 // Create an initializer for the mixin, so when derived constructor calls 871 // Create an initializer for the mixin, so when derived constructor calls
835 // super, we can correctly initialize base and mixins. 872 // super, we can correctly initialize base and mixins.
836 let mixins = Array.prototype.slice.call(arguments, 1); 873 let mixins = slice.call(arguments, 1);
837 874
838 // Create a class that will hold all of the mixin methods. 875 // Create a class that will hold all of the mixin methods.
839 class Mixin extends base { 876 class Mixin extends base {
840 // Initializer method: run mixin initializers, then the base. 877 // Initializer method: run mixin initializers, then the base.
841 [base.name](/*...args*/) { 878 [base.name](/*...args*/) {
842 // Run mixin initializers. They cannot have arguments. 879 // Run mixin initializers. They cannot have arguments.
843 // Run them backwards so most-derived mixin is initialized first. 880 // Run them backwards so most-derived mixin is initialized first.
844 for (let i = mixins.length - 1; i >= 0; i--) { 881 for (let i = mixins.length - 1; i >= 0; i--) {
845 let mixin = mixins[i]; 882 let mixin = mixins[i];
846 let init = mixin.prototype[mixin.name]; 883 let init = mixin.prototype[mixin.name];
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
914 function throw_(obj) { throw obj; } 951 function throw_(obj) { throw obj; }
915 dart.throw_ = throw_; 952 dart.throw_ = throw_;
916 953
917 /** 954 /**
918 * Given a class and an initializer method name, creates a constructor 955 * Given a class and an initializer method name, creates a constructor
919 * function with the same name. For example `new SomeClass.name(args)`. 956 * function with the same name. For example `new SomeClass.name(args)`.
920 */ 957 */
921 function defineNamedConstructor(clazz, name) { 958 function defineNamedConstructor(clazz, name) {
922 let proto = clazz.prototype; 959 let proto = clazz.prototype;
923 let initMethod = proto[name]; 960 let initMethod = proto[name];
924 let ctor = function() { return initMethod.apply(this, arguments); } 961 let ctor = function() { return initMethod.apply(this, arguments); };
925 ctor.prototype = proto; 962 ctor.prototype = proto;
926 // Use defineProperty so we don't hit a property defined on Function, 963 // Use defineProperty so we don't hit a property defined on Function,
927 // like `caller` and `arguments`. 964 // like `caller` and `arguments`.
928 defineProperty(clazz, name, { value: ctor, configurable: true }); 965 defineProperty(clazz, name, { value: ctor, configurable: true });
929 } 966 }
930 dart.defineNamedConstructor = defineNamedConstructor; 967 dart.defineNamedConstructor = defineNamedConstructor;
931 968
932 function stackTrace(exception) { 969 function stackTrace(exception) {
933 return _js_helper.getTraceFromException(exception); 970 return _js_helper.getTraceFromException(exception);
934 } 971 }
935 dart.stackTrace = stackTrace; 972 dart.stackTrace = stackTrace;
936 973
937 /** The Symbol for storing type arguments on a specialized generic type. */ 974 /** The Symbol for storing type arguments on a specialized generic type. */
938 dart.typeArguments = Symbol('typeArguments'); 975 dart.typeArguments = Symbol('typeArguments');
939 dart.originalDeclaration = Symbol('originalDeclaration'); 976 dart.originalDeclaration = Symbol('originalDeclaration');
940 977
941 /** Memoize a generic type constructor function. */ 978 /** Memoize a generic type constructor function. */
942 function generic(typeConstructor) { 979 function generic(typeConstructor) {
943 let length = typeConstructor.length; 980 let length = typeConstructor.length;
944 if (length < 1) throw Error('must have at least one generic type argument'); 981 if (length < 1) throw Error('must have at least one generic type argument');
945 982
946 let resultMap = new Map(); 983 let resultMap = new Map();
947 function makeGenericType(/*...arguments*/) { 984 function makeGenericType(/*...arguments*/) {
948 if (arguments.length != length && arguments.length != 0) { 985 if (arguments.length != length && arguments.length != 0) {
949 throw Error('requires ' + length + ' or 0 type arguments'); 986 throw Error('requires ' + length + ' or 0 type arguments');
950 } 987 }
951 let args = Array.prototype.slice.call(arguments); 988 let args = slice.call(arguments);
952 // TODO(leafp): This should really be core.Object for 989 // TODO(leafp): This should really be core.Object for
953 // consistency, but Object is not attached to core 990 // consistency, but Object is not attached to core
954 // until the entire core library has been processed, 991 // until the entire core library has been processed,
955 // which is too late. 992 // which is too late.
956 while (args.length < length) args.push(dart.dynamic); 993 while (args.length < length) args.push(dart.dynamic);
957 994
958 let value = resultMap; 995 let value = resultMap;
959 for (let i = 0; i < length; i++) { 996 for (let i = 0; i < length; i++) {
960 let arg = args[i]; 997 let arg = args[i];
961 if (arg == null) { 998 if (arg == null) {
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
1109 } 1146 }
1110 map = value; 1147 map = value;
1111 } 1148 }
1112 if (map.has(_value)) return map.get(_value); 1149 if (map.has(_value)) return map.get(_value);
1113 let value = valueFn(); 1150 let value = valueFn();
1114 map.set(_value, value); 1151 map.set(_value, value);
1115 return value; 1152 return value;
1116 } 1153 }
1117 1154
1118 /** The global constant table. */ 1155 /** The global constant table. */
1119 let constants = new Map(); 1156 const constants = new Map();
1120 1157
1121 /** 1158 /**
1122 * Canonicalize a constant object. 1159 * Canonicalize a constant object.
1123 * 1160 *
1124 * Preconditions: 1161 * Preconditions:
1125 * - `obj` is an objects or array, not a primitive. 1162 * - `obj` is an objects or array, not a primitive.
1126 * - nested values of the object are themselves already canonicalized. 1163 * - nested values of the object are themselves already canonicalized.
1127 */ 1164 */
1128 function constant(obj) { 1165 function constant(obj) {
1129 let objectKey = [realRuntimeType(obj)]; 1166 let objectKey = [realRuntimeType(obj)];
1130 // There's no guarantee in JS that names/symbols are returned in the same 1167 // TODO(jmesserly): there's no guarantee in JS that names/symbols are
1131 // order. We could probably get the same order if we're judicious about 1168 // returned in the same order.
1132 // initializing them, but easier to not depend on that. 1169 //
1170 // We could probably get the same order if we're judicious about
1171 // initializing fields in a consistent order across all const constructors.
1172 // Alternatively we need a way to sort them to make consistent.
1173 //
1174 // Right now we use the (name,value) pairs in sequence, which prevents
1175 // an object with incorrect field values being returned, but won't
1176 // canonicalize correctly if key order is different.
1133 for (let name of getOwnNamesAndSymbols(obj)) { 1177 for (let name of getOwnNamesAndSymbols(obj)) {
1134 // TODO(jmesserly): we can make this faster if needed.
1135 objectKey.push(name); 1178 objectKey.push(name);
1136 objectKey.push(obj[name]); 1179 objectKey.push(obj[name]);
1137 } 1180 }
1138 return multiKeyPutIfAbsent(constants, objectKey, () => obj); 1181 return multiKeyPutIfAbsent(constants, objectKey, () => obj);
1139 } 1182 }
1140 dart.const = constant; 1183 dart.const = constant;
1141 1184
1142 // TODO(vsm): Rationalize these type methods. We're currently using the 1185 // TODO(vsm): Rationalize these type methods. We're currently using the
1143 // setType / proto scheme for nominal types (e.g., classes) and the 1186 // setType / proto scheme for nominal types (e.g., classes) and the
1144 // setRuntimeType / field scheme for structural types (e.g., functions 1187 // setRuntimeType / field scheme for structural types (e.g., functions
1145 // - and only in tests for now). 1188 // - and only in tests for now).
1146 // See: https://github.com/dart-lang/dev_compiler/issues/172 1189 // See: https://github.com/dart-lang/dev_compiler/issues/172
1147 1190
1148 /** Sets the type of `obj` to be `type` */ 1191 /** Sets the type of `obj` to be `type` */
1149 function setType(obj, type) { 1192 function setType(obj, type) {
1150 obj.__proto__ = type.prototype; 1193 obj.__proto__ = type.prototype;
1151 return obj; 1194 return obj;
1152 } 1195 }
1153 dart.setType = setType; 1196 dart.setType = setType;
1154 1197
1198 /** Sets the element type of a list literal. */
1199 function list(obj, elementType) {
1200 return setType(obj, _interceptors.JSArray$(elementType));
1201 }
1202 dart.list = list;
1203
1155 /** Sets the internal runtime type of `obj` to be `type` */ 1204 /** Sets the internal runtime type of `obj` to be `type` */
1156 function setRuntimeType(obj, type) { 1205 function setRuntimeType(obj, type) {
1157 obj[_runtimeType] = type; 1206 obj[_runtimeType] = type;
1158 } 1207 }
1159 dart.setRuntimeType = setRuntimeType; 1208 dart.setRuntimeType = setRuntimeType;
1160 1209
1161 // The following are helpers for Object methods when the receiver 1210 // The following are helpers for Object methods when the receiver
1162 // may be null or primitive. These should only be generated by 1211 // may be null or primitive. These should only be generated by
1163 // the compiler. 1212 // the compiler.
1164 function hashCode(obj) { 1213 function hashCode(obj) {
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
1251 } 1300 }
1252 dart.defineLibrary = defineLibrary; 1301 dart.defineLibrary = defineLibrary;
1253 1302
1254 // TODO(jmesserly): hack to bootstrap the SDK 1303 // TODO(jmesserly): hack to bootstrap the SDK
1255 _js_helper = _js_helper || {}; 1304 _js_helper = _js_helper || {};
1256 _js_helper.checkNum = notNull; 1305 _js_helper.checkNum = notNull;
1257 1306
1258 _js_primitives = _js_primitives || {}; 1307 _js_primitives = _js_primitives || {};
1259 _js_primitives.printString = (s) => console.log(s); 1308 _js_primitives.printString = (s) => console.log(s);
1260 1309
1261 // TODO(vsm): Plumb this correctly.
1262 // See: https://github.com/dart-lang/dev_compiler/issues/40
1263 String.prototype.contains = function(sub) { return this.indexOf(sub) >= 0; }
1264 let _split = String.prototype.split;
1265 String.prototype.split = function() {
1266 let result = _split.apply(this, arguments);
1267 dart.setType(result, core.List$(core.String));
1268 return result;
1269 };
1270 String.prototype.get = function(i) {
1271 return this[i];
1272 };
1273 String.prototype.codeUnitAt = function(i) {
1274 return this.charCodeAt(i);
1275 };
1276 String.prototype.replaceAllMapped = function(from, cb) {
1277 return this.replace(from.multiple, function() {
1278 // Remove offset & string from the result array
1279 var matches = arguments;
1280 matches.splice(-2, 2);
1281 // The callback receives match, p1, ..., pn
1282 return cb(matches);
1283 });
1284 };
1285 String.prototype['+'] = function(arg) { return this.valueOf() + arg; };
1286
1287 Boolean.prototype['!'] = function() { return !this.valueOf(); };
1288 Boolean.prototype['&&'] = function(arg) { return this.valueOf() && arg; };
1289 Boolean.prototype['||'] = function(arg) { return this.valueOf() || arg; };
1290 Number.prototype['<'] = function(arg) { return this.valueOf() < arg; };
1291 Number.prototype['<='] = function(arg) { return this.valueOf() <= arg; };
1292 Number.prototype['>'] = function(arg) { return this.valueOf() > arg; };
1293 Number.prototype['+'] = function(arg) { return this.valueOf() + arg; };
1294
1295 // TODO(vsm): DOM facades? 1310 // TODO(vsm): DOM facades?
1296 // See: https://github.com/dart-lang/dev_compiler/issues/173 1311 // See: https://github.com/dart-lang/dev_compiler/issues/173
1297 NodeList.prototype.get = function(i) { return this[i]; }; 1312 NodeList.prototype.get = function(i) { return this[i]; };
1298 NamedNodeMap.prototype.get = function(i) { return this[i]; }; 1313 NamedNodeMap.prototype.get = function(i) { return this[i]; };
1299 DOMTokenList.prototype.get = function(i) { return this[i]; }; 1314 DOMTokenList.prototype.get = function(i) { return this[i]; };
1300 1315
1316 /** Dart extension members. */
1317 dartx = dartx || {};
1318
1301 })(dart || (dart = {})); 1319 })(dart || (dart = {}));
OLDNEW
« no previous file with comments | « lib/runtime/dart/typed_data.js ('k') | lib/src/checker/resolver.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698