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

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

Issue 1050723002: partially implement instance of checks and some codegen fixes (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 5 years, 8 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; 5 var dart, _js_helper;
6 (function (dart) { 6 (function (dart) {
7 'use strict'; 7 'use strict';
8 8
9 var defineProperty = Object.defineProperty; 9 let defineProperty = Object.defineProperty;
10 var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; 10 let getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
11 var getOwnPropertyNames = Object.getOwnPropertyNames; 11 let getOwnPropertyNames = Object.getOwnPropertyNames;
12 12
13 // Adapted from Angular.js 13 // Adapted from Angular.js
14 var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m; 14 let FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
15 var FN_ARG_SPLIT = /,/; 15 let FN_ARG_SPLIT = /,/;
16 var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/; 16 let FN_ARG = /^\s*(_?)(\S+?)\1\s*$/;
17 var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg; 17 let STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
18 18
19 function formalParameterList(fn) { 19 function formalParameterList(fn) {
20 var fnText,argDecl; 20 let fnText,argDecl;
21 var args=[]; 21 let args=[];
22 fnText = fn.toString().replace(STRIP_COMMENTS, ''); 22 fnText = fn.toString().replace(STRIP_COMMENTS, '');
23 argDecl = fnText.match(FN_ARGS); 23 argDecl = fnText.match(FN_ARGS);
24 24
25 var r = argDecl[1].split(FN_ARG_SPLIT); 25 let r = argDecl[1].split(FN_ARG_SPLIT);
26 for(var a in r) { 26 for(let a in r) {
27 var arg = r[a]; 27 let arg = r[a];
28 arg.replace(FN_ARG, function(all, underscore, name){ 28 arg.replace(FN_ARG, function(all, underscore, name){
29 args.push(name); 29 args.push(name);
30 }); 30 });
31 } 31 }
32 return args; 32 return args;
33 } 33 }
34 34
35 function dload(obj, field) { 35 function dload(obj, field) {
36 if (!(field in obj)) { 36 if (!(field in obj)) {
37 throw new core.NoSuchMethodError(obj, field); 37 throw new core.NoSuchMethodError(obj, field);
38 } 38 }
39 return obj[field]; 39 return obj[field];
40 } 40 }
41 dart.dload = dload; 41 dart.dload = dload;
42 42
43 // TODO(jmesserly): this should call noSuchMethod, not throw. 43 // TODO(jmesserly): this should call noSuchMethod, not throw.
44 function throwNoSuchMethod(obj, name, args, opt_func) { 44 function throwNoSuchMethod(obj, name, args, opt_func) {
45 if (obj === void 0) obj = opt_func; 45 if (obj === void 0) obj = opt_func;
46 throw new core.NoSuchMethodError(obj, name, args); 46 throw new core.NoSuchMethodError(obj, name, args);
47 } 47 }
48 48
49 function checkAndCall(f, obj, args, name) { 49 function checkAndCall(f, obj, args, name) {
50 if (!(f instanceof Function)) { 50 if (!(f instanceof Function)) {
51 // Grab the `call` method if it's not a function. 51 // Grab the `call` method if it's not a function.
52 if (f !== null) f = f.call; 52 if (f !== null) f = f.call;
53 if (!(f instanceof Function)) { 53 if (!(f instanceof Function)) {
54 throwNoSuchMethod(obj, method, args); 54 throwNoSuchMethod(obj, method, args);
55 } 55 }
56 } 56 }
57 var formals = formalParameterList(f); 57 let formals = formalParameterList(f);
58 // TODO(vsm): Type check args! We need to encode sufficient type info on f. 58 // TODO(vsm): Type check args! We need to encode sufficient type info on f.
59 if (formals.length < args.length) { 59 if (formals.length < args.length) {
60 throwNoSuchMethod(obj, name, args, f); 60 throwNoSuchMethod(obj, name, args, f);
61 } else if (formals.length > args.length) { 61 } else if (formals.length > args.length) {
62 for (var i = args.length; i < formals.length; ++i) { 62 for (let i = args.length; i < formals.length; ++i) {
63 if (formals[i].indexOf("opt$") != 0) { 63 if (formals[i].indexOf("opt$") != 0) {
64 throwNoSuchMethod(obj, name, args, f); 64 throwNoSuchMethod(obj, name, args, f);
65 } 65 }
66 } 66 }
67 } 67 }
68 return f.apply(obj, args); 68 return f.apply(obj, args);
69 } 69 }
70 70
71 function dinvokef(f/*, ...args*/) { 71 function dinvokef(f/*, ...args*/) {
72 var args = Array.prototype.slice.call(arguments, 1); 72 let args = Array.prototype.slice.call(arguments, 1);
73 return checkAndCall(f, void 0, args, 'call'); 73 return checkAndCall(f, void 0, args, 'call');
74 } 74 }
75 dart.dinvokef = dinvokef; 75 dart.dinvokef = dinvokef;
76 76
77 function dinvoke(obj, method/*, ...args*/) { 77 function dinvoke(obj, method/*, ...args*/) {
78 var args = Array.prototype.slice.call(arguments, 2); 78 let args = Array.prototype.slice.call(arguments, 2);
79 return checkAndCall(obj[method], obj, args, method); 79 return checkAndCall(obj[method], obj, args, method);
80 } 80 }
81 dart.dinvoke = dinvoke; 81 dart.dinvoke = dinvoke;
82 82
83 function dindex(obj, index) { 83 function dindex(obj, index) {
84 return checkAndCall(obj.get, obj, [index], '[]'); 84 return checkAndCall(obj.get, obj, [index], '[]');
85 } 85 }
86 dart.dindex = dindex; 86 dart.dindex = dindex;
87 87
88 function dsetindex(obj, index, value) { 88 function dsetindex(obj, index, value) {
89 return checkAndCall(obj.set, obj, [index, value], '[]='); 89 return checkAndCall(obj.set, obj, [index, value], '[]=');
90 } 90 }
91 dart.dsetindex = dindex; 91 dart.dsetindex = dindex;
92 92
93 function dbinary(left, op, right) { 93 function dbinary(left, op, right) {
94 return checkAndCall(left[op], left, [right], op); 94 return checkAndCall(left[op], left, [right], op);
95 } 95 }
96 dart.dbinary = dbinary; 96 dart.dbinary = dbinary;
97 97
98 function as_(obj, type) { 98 function cast(obj, type) {
99 // TODO(vsm): Implement. 99 if (obj == null) return obj;
vsm 2015/04/01 15:38:00 Can you add a TODO(vsm) here about handling non-nu
Jennifer Messerly 2015/04/01 15:57:32 sure thing :)
100 // if (obj == null || is(obj, type)) return obj; 100 let actual = getRuntimeType(obj);
101 // throw new core.CastError(); 101 if (isSubtype(actual, type)) return obj;
102 return obj; 102 throw new _js_helper.CastErrorImplementation(actual, type);
103 } 103 }
104 dart.as = as_; 104 dart.as = cast;
105 105
106 function is(obj, type) { 106 /**
107 // TODO(vsm): Implement. 107 * Returns the runtime type of obj. This is the same as `obj.runtimeType`
108 throw new core.UnimplementedError(); 108 * but will not call an overridden getter.
109 *
110 * Currently this will return null for non-Dart objects.
111 */
112 function getRuntimeType(obj) {
113 switch (typeof obj) {
114 case "undefined":
115 return core.Null;
116 case "number":
117 return Math.floor(obj) == obj ? core.int : core.double;
118 case "boolean":
119 return core.bool;
120 case "string":
121 return core.String;
122 case "symbol":
123 return Symbol;
124 }
125 // Undefined is handled above. For historical reasons,
126 // typeof null == "object" in JS.
127 if (obj === null) return core.Null;
128 return obj.constructor;
109 } 129 }
110 dart.is = is; 130 dart.getRuntimeType = getRuntimeType;
131
132 function instanceOf(obj, type) {
vsm 2015/04/01 15:38:00 This needs a test for null: if (obj == null) {
Jennifer Messerly 2015/04/01 15:57:32 yeah, I saw that code, but it seems like null is a
vsm 2015/04/01 16:29:40 The problem is the opposite case: isSubtype(core
Jennifer Messerly 2015/04/01 16:41:22 chatted about this & added a test case. I think we
133 return isSubtype(getRuntimeType(obj), type);
134 }
135 dart.is = instanceOf;
136
137 /**
138 * Computes the canonical type.
139 * This maps JS types onto their corresponding Dart Type.
140 */
141 // TODO(jmesserly): lots more needs to be done here.
142 function canonicalType(t) {
143 if (t === Object) return core.Object;
144 if (t === Function) return core.Function;
145 if (t === Array) return core.List;
146
147 // We shouldn't normally get here with these types, unless something strange
148 // happens like subclassing Number in JS and passing it to Dart.
149 if (t === String) return core.String;
150 if (t === Number) return core.double;
151 if (t === Boolean) return core.bool;
152 return t;
153 }
154
155 let subtypeMap = new Map();
156 function isSubtype(t1, t2) {
157 // See if we already know the answer
158 // TODO(jmesserly): general purpose memoize function?
159 let map = subtypeMap.get(t1);
160 let result;
161 if (map) {
162 result = map.get(t2);
163 if (result !== void 0) return result;
164 } else {
165 subtypeMap.set(t1, map = new Map());
166 }
167 map.set(t2, result = isSubtype_(t1, t2));
168 return result;
169 }
170 dart.isSubtype = isSubtype;
171
172 function isSubtype_(t1, t2) {
173 t1 = canonicalType(t1);
174 t2 = canonicalType(t2);
175 if (t1 == t2) return true;
176
177 // In Dart, dynamic is effectively both top and bottom.
178 // Here, we treat dynamic as top - the base type of everything.
vsm 2015/04/01 15:38:00 We'll need to update as per recent CL. Both dynam
Jennifer Messerly 2015/04/01 15:57:32 sounds good. happy to update either now or after y
179 if (t1 == dart.dynamic) return false;
180 if (t2 == dart.dynamic) return true;
181
182 if (t2 == core.Object) return true;
183 if (t1 == core.Object) return false;
184
185 // "Traditional" name-based subtype check.
186 if (isClassSubType(t1, t2)) {
187 return true;
188 }
189
190 // Function subtyping.
191 // TODO(jmesserly): implement.
192 return false;
193 }
194
195 function safeGetOwnProperty(obj, name) {
196 var desc = getOwnPropertyDescriptor(obj, name);
197 if (desc) return desc.value;
198 }
199
200 function isClassSubType(t1, t2) {
201 // We support Dart's covariant generics with the caveat that we do not
202 // substitute bottom for dynamic in subtyping rules.
203 // I.e., given T1, ..., Tn where at least one Ti != dynamic we disallow:
204 // - S !<: S<T1, ..., Tn>
205 // - S<dynamic, ..., dynamic> !<: S<T1, ..., Tn>
206 if (t1 == t2) return true;
207
208 if (t1 == core.Object) return false;
209
210 // Check if t1 and t2 have the same raw type. If so, check covariance on
211 // type parameters.
212 let raw1 = safeGetOwnProperty(t1, dart.originalDeclaration);
213 let raw2 = safeGetOwnProperty(t2, dart.originalDeclaration);
214 if (raw1 != null && raw1 == raw2) {
215 let typeArguments1 = safeGetOwnProperty(t1, dart.typeArguments);
216 let typeArguments2 = safeGetOwnProperty(t2, dart.typeArguments);
217 let length = typeArguments1.length;
218 if (typeArguments2.length == 0) {
219 // t2 is the raw form of t1
220 return true;
221 } else if (length == 0) {
222 // t1 is raw, but t2 is not
223 return false;
224 }
225 assert(length == typeArguments2.length);
226 for (let i = 0; i < length; ++i) {
227 if (!isSubtype(typeArguments1[i], typeArguments2[i])) {
228 return false;
229 }
230 }
231 return true;
232 }
233
234 // Check superclass.
235 if (isClassSubType(t1.__proto__, t2)) return true;
vsm 2015/04/01 15:37:59 This won't cover mixins, right? The application o
Jennifer Messerly 2015/04/01 15:57:32 doh! Good catch. It seems like the Dart code might
vsm 2015/04/01 16:29:40 Yeah, updating my CL too. :-)
236
237 // Check interfaces.
238 let getInterfaces = safeGetOwnProperty(t1, dart.implements);
239 if (getInterfaces) {
240 for (let i1 of getInterfaces()) {
241 // TODO(jmesserly): remove the != null check once we can load core libs.
242 if (i1 != null && isClassSubType(i1, t2)) return true;
243 }
244 }
245
246 return false;
247 }
111 248
112 function closureWrap(obj, type) { 249 function closureWrap(obj, type) {
113 // TODO(vsm): Remove this once we handle in the checker. 250 // TODO(vsm): Remove this once we handle in the checker.
114 return obj; 251 return obj;
115 } 252 }
116 dart.closureWrap = closureWrap; 253 dart.closureWrap = closureWrap;
117 254
255 // TODO(jmesserly): do we need this function?
vsm 2015/04/01 15:38:00 We may want to keep this around if we want to reje
Jennifer Messerly 2015/04/01 15:57:32 sounds good. Updated the comment
118 function isGroundType(type) { 256 function isGroundType(type) {
119 // TODO(vsm): Implement. 257 let typeArgs = safeGetOwnProperty(type, dart.typeArguments);
120 throw new core.UnimplementedError(); 258 if (!typeArgs) return true;
259 for (let t of typeArgs) {
260 if (t != core.Object && t != dart.dynamic) return false;
261 }
262 return true;
121 } 263 }
122 dart.isGroundType = isGroundType; 264 dart.isGroundType = isGroundType;
123 265
124 function arity(f) { 266 function arity(f) {
125 // TODO(vsm): Implement. 267 // TODO(jmesserly): need to parse optional params.
126 throw new core.UnimplementedError(); 268 // In ES6, length is the number of required arguments.
269 return { min: f.length, max: f.length };
127 } 270 }
128 dart.arity = arity; 271 dart.arity = arity;
129 272
130 function equals(x, y) { 273 function equals(x, y) {
131 if (x == null || y == null) return x == y; 274 if (x == null || y == null) return x == y;
132 var eq = x['==']; 275 let eq = x['=='];
133 return eq ? eq.call(x, y) : x == y; 276 return eq ? eq.call(x, y) : x == y;
134 } 277 }
135 dart.equals = equals; 278 dart.equals = equals;
136 279
137 /** Checks that `x` is not null or undefined. */ 280 /** Checks that `x` is not null or undefined. */
138 function notNull(x) { 281 function notNull(x) {
139 if (x == null) throw 'expected not-null value'; 282 if (x == null) throw 'expected not-null value';
140 return x; 283 return x;
141 } 284 }
142 dart.notNull = notNull; 285 dart.notNull = notNull;
143 286
144 /** 287 /**
145 * Defines a lazy property. 288 * Defines a lazy property.
146 * After initial get or set, it will replace itself with a value property. 289 * After initial get or set, it will replace itself with a value property.
147 */ 290 */
148 // TODO(jmesserly): is this the best implementation for JS engines? 291 // TODO(jmesserly): is this the best implementation for JS engines?
149 // TODO(jmesserly): reusing descriptor objects has been shown to improve 292 // TODO(jmesserly): reusing descriptor objects has been shown to improve
150 // performance in other projects (e.g. webcomponents.js ShadowDOM polyfill). 293 // performance in other projects (e.g. webcomponents.js ShadowDOM polyfill).
151 function defineLazyProperty(to, name, desc) { 294 function defineLazyProperty(to, name, desc) {
152 var init = desc.get; 295 let init = desc.get;
153 var writable = !!desc.set; 296 let writable = !!desc.set;
154 function lazySetter(value) { 297 function lazySetter(value) {
155 defineProperty(to, name, { value: value, writable: writable }); 298 defineProperty(to, name, { value: value, writable: writable });
156 } 299 }
157 function lazyGetter() { 300 function lazyGetter() {
158 // Clear the init function to detect circular initialization. 301 // Clear the init function to detect circular initialization.
159 var f = init; 302 let f = init;
160 if (f === null) throw 'circular initialization for field ' + name; 303 if (f === null) throw 'circular initialization for field ' + name;
161 init = null; 304 init = null;
162 305
163 // Compute and store the value. 306 // Compute and store the value.
164 var value = f(); 307 let value = f();
165 lazySetter(value); 308 lazySetter(value);
166 return value; 309 return value;
167 } 310 }
168 desc.get = lazyGetter; 311 desc.get = lazyGetter;
169 desc.configurable = true; 312 desc.configurable = true;
170 if (writable) desc.set = lazySetter; 313 if (writable) desc.set = lazySetter;
171 defineProperty(to, name, desc); 314 defineProperty(to, name, desc);
172 } 315 }
173 316
174 function defineLazy(to, from) { 317 function defineLazy(to, from) {
175 var names = getOwnPropertyNames(from); 318 let names = getOwnPropertyNames(from);
176 for (var i = 0; i < names.length; i++) { 319 for (let i = 0; i < names.length; i++) {
177 var name = names[i]; 320 let name = names[i];
178 defineLazyProperty(to, name, getOwnPropertyDescriptor(from, name)); 321 defineLazyProperty(to, name, getOwnPropertyDescriptor(from, name));
179 } 322 }
180 } 323 }
181 // TODO(jmesserly): these are identical, but this makes it easier to grep for. 324 // TODO(jmesserly): these are identical, but this makes it easier to grep for.
182 dart.defineLazyClass = defineLazy; 325 dart.defineLazyClass = defineLazy;
183 dart.defineLazyProperties = defineLazy; 326 dart.defineLazyProperties = defineLazy;
184 dart.defineLazyClassGeneric = defineLazyProperty; 327 dart.defineLazyClassGeneric = defineLazyProperty;
185 328
186 /** 329 /**
187 * Copy properties from source to destination object. 330 * Copy properties from source to destination object.
188 * This operation is commonly called `mixin` in JS. 331 * This operation is commonly called `mixin` in JS.
189 */ 332 */
190 function copyProperties(to, from) { 333 function copyProperties(to, from) {
191 var names = getOwnPropertyNames(from); 334 let names = getOwnPropertyNames(from);
192 for (var i = 0; i < names.length; i++) { 335 for (let i = 0; i < names.length; i++) {
193 var name = names[i]; 336 let name = names[i];
194 defineProperty(to, name, getOwnPropertyDescriptor(from, name)); 337 defineProperty(to, name, getOwnPropertyDescriptor(from, name));
195 } 338 }
196 return to; 339 return to;
197 } 340 }
198 dart.copyProperties = copyProperties; 341 dart.copyProperties = copyProperties;
199 342
200 343
201 /** The Symbol for storing type arguments on a specialized generic type. */ 344 /** The Symbol for storing type arguments on a specialized generic type. */
202 dart.mixins = Symbol('mixins'); 345 dart.mixins = Symbol('mixins');
203 dart.implements = Symbol('implements') 346 dart.implements = Symbol('implements');
204 347
205 /** 348 /**
206 * Returns a new type that mixes members from base and all mixins. 349 * Returns a new type that mixes members from base and all mixins.
207 * 350 *
208 * Each mixin applies in sequence, with further to the right ones overriding 351 * Each mixin applies in sequence, with further to the right ones overriding
209 * previous entries. 352 * previous entries.
210 * 353 *
211 * For each mixin, we only take its own properties, not anything from its 354 * For each mixin, we only take its own properties, not anything from its
212 * superclass (prototype). 355 * superclass (prototype).
213 */ 356 */
214 function mixin(base/*, ...mixins*/) { 357 function mixin(base/*, ...mixins*/) {
215 // Create an initializer for the mixin, so when derived constructor calls 358 // Create an initializer for the mixin, so when derived constructor calls
216 // super, we can correctly initialize base and mixins. 359 // super, we can correctly initialize base and mixins.
217 var mixins = Array.prototype.slice.call(arguments, 1); 360 let mixins = Array.prototype.slice.call(arguments, 1);
218 361
219 // Create a class that will hold all of the mixin methods. 362 // Create a class that will hold all of the mixin methods.
220 class Mixin extends base { 363 class Mixin extends base {
221 // Initializer method: run mixin initializers, then the base. 364 // Initializer method: run mixin initializers, then the base.
222 [base.name](/*...args*/) { 365 [base.name](/*...args*/) {
223 // Run mixin initializers. They cannot have arguments. 366 // Run mixin initializers. They cannot have arguments.
224 // Run them backwards so most-derived mixin is initialized first. 367 // Run them backwards so most-derived mixin is initialized first.
225 for (var i = mixins.length - 1; i >= 0; i--) { 368 for (let i = mixins.length - 1; i >= 0; i--) {
226 var mixin = mixins[i]; 369 let mixin = mixins[i];
227 mixin.prototype[mixin.name].call(this); 370 mixin.prototype[mixin.name].call(this);
228 } 371 }
229 // Run base initializer. 372 // Run base initializer.
230 base.prototype[base.name].apply(this, arguments); 373 base.prototype[base.name].apply(this, arguments);
231 } 374 }
232 } 375 }
233 // Copy each mixin's methods, with later ones overwriting earlier entries. 376 // Copy each mixin's methods, with later ones overwriting earlier entries.
234 for (var i = 0; i < mixins.length; i++) { 377 for (let m of mixins) {
235 copyProperties(Mixin.prototype, mixins[i].prototype); 378 copyProperties(Mixin.prototype, m.prototype);
236 } 379 }
237 // Save mixins for reflection 380 // Save mixins for reflection
238 Mixin[dart.mixins] = mixins; 381 Mixin[dart.mixins] = mixins;
239 return Mixin; 382 return Mixin;
240 } 383 }
241 dart.mixin = mixin; 384 dart.mixin = mixin;
242 385
243 /** 386 /**
244 * Creates a dart:collection LinkedHashMap. 387 * Creates a dart:collection LinkedHashMap.
245 * 388 *
246 * For a map with string keys an object literal can be used, for example 389 * For a map with string keys an object literal can be used, for example
247 * `map({'hi': 1, 'there': 2})`. 390 * `map({'hi': 1, 'there': 2})`.
248 * 391 *
249 * Otherwise an array should be used, for example `map([1, 2, 3, 4])` will 392 * Otherwise an array should be used, for example `map([1, 2, 3, 4])` will
250 * create a map with keys [1, 3] and values [2, 4]. Each key-value pair 393 * create a map with keys [1, 3] and values [2, 4]. Each key-value pair
251 * should be adjacent entries in the array. 394 * should be adjacent entries in the array.
252 * 395 *
253 * For a map with no keys the function can be called with no arguments, for 396 * For a map with no keys the function can be called with no arguments, for
254 * example `map()`. 397 * example `map()`.
255 */ 398 */
256 // TODO(jmesserly): this could be faster 399 // TODO(jmesserly): this could be faster
257 function map(values) { 400 function map(values) {
258 var map = new collection.LinkedHashMap(); 401 let map = new collection.LinkedHashMap();
259 if (Array.isArray(values)) { 402 if (Array.isArray(values)) {
260 for (var i = 0, end = values.length - 1; i < end; i += 2) { 403 for (let i = 0, end = values.length - 1; i < end; i += 2) {
261 var key = values[i]; 404 let key = values[i];
262 var value = values[i + 1]; 405 let value = values[i + 1];
263 map.set(key, value); 406 map.set(key, value);
264 } 407 }
265 } else if (typeof values === 'object') { 408 } else if (typeof values === 'object') {
266 var keys = Object.getOwnPropertyNames(values); 409 for (let key of Object.getOwnPropertyNames(values)) {
267 for (var i = 0; i < keys.length; i++) { 410 map.set(key, values[key]);
268 var key = keys[i];
269 var value = values[key];
270 map.set(key, value);
271 } 411 }
272 } 412 }
273 return map; 413 return map;
274 } 414 }
275 dart.map = map; 415 dart.map = map;
276 416
277 function assert(condition) { 417 function assert(condition) {
278 // TODO(jmesserly): throw assertion error. 418 // TODO(jmesserly): throw assertion error.
279 if (!condition) throw 'assertion failed'; 419 if (!condition) throw 'assertion failed';
280 } 420 }
281 dart.assert = assert; 421 dart.assert = assert;
282 422
283 function throw_(obj) { throw obj; } 423 function throw_(obj) { throw obj; }
284 dart.throw_ = throw_; 424 dart.throw_ = throw_;
285 425
286 /** 426 /**
287 * Given a class and an initializer method name, creates a constructor 427 * Given a class and an initializer method name, creates a constructor
288 * function with the same name. For example `new SomeClass.name(args)`. 428 * function with the same name. For example `new SomeClass.name(args)`.
289 */ 429 */
290 function defineNamedConstructor(clazz, name) { 430 function defineNamedConstructor(clazz, name) {
291 var proto = clazz.prototype; 431 let proto = clazz.prototype;
292 var initMethod = proto[name]; 432 let initMethod = proto[name];
293 var ctor = function() { return initMethod.apply(this, arguments); } 433 let ctor = function() { return initMethod.apply(this, arguments); }
294 ctor.prototype = proto; 434 ctor.prototype = proto;
295 clazz[name] = ctor; 435 clazz[name] = ctor;
296 } 436 }
297 dart.defineNamedConstructor = defineNamedConstructor; 437 dart.defineNamedConstructor = defineNamedConstructor;
298 438
299 function stackTrace(exception) { 439 function stackTrace(exception) {
300 throw new core.UnimplementedError(); 440 throw new core.UnimplementedError();
301 } 441 }
302 dart.stackTrace = stackTrace; 442 dart.stackTrace = stackTrace;
303 443
304 /** The Symbol for storing type arguments on a specialized generic type. */ 444 /** The Symbol for storing type arguments on a specialized generic type. */
305 dart.typeSignature = Symbol('typeSignature'); 445 dart.typeArguments = Symbol('typeArguments');
446 dart.originalDeclaration = Symbol('originalDeclaration');
Jennifer Messerly 2015/04/01 00:32:35 better name suggestions?
306 447
307 /** Memoize a generic type constructor function. */ 448 /** Memoize a generic type constructor function. */
308 function generic(typeConstructor) { 449 function generic(typeConstructor) {
309 var length = typeConstructor.length; 450 let length = typeConstructor.length;
310 if (length < 1) throw 'must have at least one generic type argument'; 451 if (length < 1) throw Error('must have at least one generic type argument');
311 452
312 var resultMap = new Map(); 453 let resultMap = new Map();
313 function makeGenericType(/*...arguments*/) { 454 function makeGenericType(/*...arguments*/) {
314 if (arguments.length != length && arguments.length != 0) { 455 if (arguments.length != length && arguments.length != 0) {
315 throw 'requires ' + length + ' or 0 type arguments'; 456 throw Error('requires ' + length + ' or 0 type arguments');
316 } 457 }
458 let args = Array.prototype.slice.call(arguments);
459 while (args.length < length) args.push(dart.dynamic);
317 460
318 var value = resultMap; 461 let value = resultMap;
319 for (var i = 0; i < length; i++) { 462 for (let i = 0; i < length; i++) {
320 var arg = arguments[i]; 463 let arg = args[i];
321 if (arg === void 0) arg = dart.dynamic; 464 if (arg == null) {
322 465 throw Error('type arguments should not be null: ' + typeConstructor);
323 var map = value; 466 }
467 let map = value;
324 value = map.get(arg); 468 value = map.get(arg);
325 if (value === void 0) { 469 if (value === void 0) {
326 if (i + 1 == length) { 470 if (i + 1 == length) {
327 value = typeConstructor.apply(null, arguments); 471 value = typeConstructor.apply(null, args);
328 // Save the type constructor and arguments for reflection. 472 // Save the type constructor and arguments for reflection.
329 if (value) { 473 if (value) {
330 var args = Array.prototype.slice.call(arguments); 474 value[dart.typeArguments] = args;
331 value[dart.typeSignature] = [makeGenericType].concat(args); 475 value[dart.originalDeclaration] = makeGenericType;
332 } 476 }
333 } else { 477 } else {
334 value = new Map(); 478 value = new Map();
335 } 479 }
336 map.set(arg, value); 480 map.set(arg, value);
337 } 481 }
338 } 482 }
339 return value; 483 return value;
340 } 484 }
341 return makeGenericType; 485 return makeGenericType;
342 } 486 }
343 dart.generic = generic; 487 dart.generic = generic;
344 488
345 // TODO(jmesserly): right now this is a sentinel. It should be a type object 489 // TODO(jmesserly): right now this is a sentinel. It should be a type object
346 // of some sort, assuming we keep around `dynamic` at runtime. 490 // of some sort, assuming we keep around `dynamic` at runtime.
347 dart.dynamic = Object.create(null); 491 dart.dynamic = { toString() { return 'dynamic'; } };
348 492
349 dart.JsSymbol = Symbol; 493 dart.JsSymbol = Symbol;
350 494
351 // TODO(jmesserly): hack to bootstrap the SDK 495 // TODO(jmesserly): hack to bootstrap the SDK
352 _js_helper = _js_helper || {}; 496 _js_helper = _js_helper || {};
353 _js_helper.checkNum = notNull; 497 _js_helper.checkNum = notNull;
354 498
355 })(dart || (dart = {})); 499 })(dart || (dart = {}));
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698