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

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

Issue 1182653002: Refactor runtime into libraries, better type reps (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Address comments 2 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_library.js ('k') | lib/runtime/dart_utils.js » ('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, dartx; 5 dart_library.library('dart_runtime/dart', null, /* Imports */[
6 (function (dart) { 6 'dart_runtime/_classes',
7 'dart_runtime/_errors',
8 'dart_runtime/_operations',
9 'dart_runtime/_rtti',
10 'dart_runtime/_types',
11 ], /* Lazy Imports */[
12 'dart/_js_helper'
13 ], function(exports, classes, errors, operations, rtti, types, _js_helper) {
7 'use strict'; 14 'use strict';
8 15
9 const defineProperty = Object.defineProperty; 16 function _export(value) {
10 const getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; 17 if (value) return value;
11 const getOwnPropertyNames = Object.getOwnPropertyNames; 18 console.log("Re-exporting null field: " + name);
12 const getOwnPropertySymbols = Object.getOwnPropertySymbols; 19 throw "Bad export";
13 const hasOwnProperty = Object.prototype.hasOwnProperty;
14 const slice = [].slice;
15
16 let _constructorSig = Symbol('sigCtor');
17 let _methodSig = Symbol("sig");
18 let _staticSig = Symbol("sigStatic");
19
20 function getOwnNamesAndSymbols(obj) {
21 return getOwnPropertyNames(obj).concat(getOwnPropertySymbols(obj));
22 } 20 }
23 21
24 function dload(obj, field) { 22 function exportFrom(value, names) {
25 field = _canonicalFieldName(obj, field, [], field); 23 for (let name of names) {
26 if (_getMethodType(obj, field) !== void 0) { 24 exports[name] = _export(value[name]);
27 return dart.bind(obj, field);
28 }
29 // TODO(vsm): Implement NSM robustly. An 'in' check breaks on certain
30 // types. hasOwnProperty doesn't chase the proto chain.
31 // Also, do we want an NSM on regular JS objects?
32 // See: https://github.com/dart-lang/dev_compiler/issues/169
33 let result = obj[field];
34
35 // TODO(vsm): Check this more robustly.
36 if (typeof result == "function" && !hasOwnProperty.call(obj, field)) {
37 // This appears to be a method tearoff. Bind this.
38 return result.bind(obj);
39 }
40 return result;
41 }
42 dart.dload = dload;
43
44 function dput(obj, field, value) {
45 field = _canonicalFieldName(obj, field, [value], field);
46 // TODO(vsm): Implement NSM and type checks.
47 // See: https://github.com/dart-lang/dev_compiler/issues/170
48 obj[field] = value;
49 }
50 dart.dput = dput;
51
52 function throwRuntimeError(message) {
53 throw Error(message);
54 }
55
56 // TODO(jmesserly): this should call noSuchMethod, not throw.
57 function throwNoSuchMethod(obj, name, args, opt_func) {
58 if (obj === void 0) obj = opt_func;
59 throw new core.NoSuchMethodError(obj, name, args);
60 }
61
62 function checkAndCall(f, ftype, obj, args, name) {
63 if (!(f instanceof Function)) {
64 // We're not a function (and hence not a method either)
65 // Grab the `call` method if it's not a function.
66 if (f !== null) {
67 ftype = _getMethodType(f, 'call');
68 f = f.call;
69 }
70 if (!(f instanceof Function)) {
71 throwNoSuchMethod(obj, name, args);
72 }
73 }
74 // If f is a function, but not a method (no method type)
75 // then it should have been a function valued field, so
76 // get the type from the function.
77 if (ftype === void 0) {
78 ftype = _getFunctionType(f);
79 }
80
81 if (!ftype) {
82 // TODO(leafp): Allow JS objects to go through?
83 // This includes the DOM.
84 return f.apply(obj, args);
85 }
86
87 if (ftype.checkApply(args)) {
88 return f.apply(obj, args);
89 }
90
91 // TODO(leafp): throw a type error (rather than NSM)
92 // if the arity matches but the types are wrong.
93 throwNoSuchMethod(obj, name, args, f);
94 }
95
96 function dcall(f/*, ...args*/) {
97 let args = slice.call(arguments, 1);
98 let ftype = _getFunctionType(f);
99 return checkAndCall(f, ftype, void 0, args, 'call');
100 }
101 dart.dcall = dcall;
102
103 let _extensionType = Symbol('extensionType');
104 function _canonicalFieldName(obj, name, args, displayName) {
105 if (obj[_extensionType]) {
106 let extension = dartx[name];
107 if (extension) return extension;
108 // TODO(jmesserly): in the future we might have types that "overlay" Dart
109 // methods while also exposing the full native API, e.g. dart:html vs
110 // dart:dom. To support that we'd need to fall back to the normal name
111 // if an extension method wasn't found.
112 throwNoSuchMethod(obj, displayName, args);
113 }
114 return name;
115 }
116
117 /** Shared code for dsend, dindex, and dsetindex. */
118 function callMethod(obj, name, args, displayName) {
119 let symbol = _canonicalFieldName(obj, name, args, displayName);
120 let f = obj[symbol];
121 let ftype = _getMethodType(obj, name);
122 return checkAndCall(f, ftype, obj, args, displayName);
123 }
124
125 function dsend(obj, method/*, ...args*/) {
126 return callMethod(obj, method, slice.call(arguments, 2));
127 }
128 dart.dsend = dsend;
129
130 function dindex(obj, index) {
131 return callMethod(obj, 'get', [index], '[]');
132 }
133 dart.dindex = dindex;
134
135 function dsetindex(obj, index, value) {
136 return callMethod(obj, 'set', [index, value], '[]=');
137 }
138 dart.dsetindex = dsetindex;
139
140 function _typeName(type) {
141 if (typeof(type) == "function") {
142 let name = type.name;
143 let args = type[dart.typeArguments];
144 if (args) {
145 name += '<';
146 for (let i = 0; i < args.length; ++i) {
147 if (i > 0) name += ', ';
148 name += _typeName(args[i]);
149 }
150 name += '>';
151 }
152 return name;
153 } else {
154 return type.toString();
155 }
156 }
157 dart.typeName = _typeName;
158
159 function _ignoreTypeFailure(actual, type) {
160 // TODO(vsm): Remove this hack ...
161 // This is primarily due to the lack of generic methods,
162 // but we need to triage all the errors.
163 if (isSubtype(type, core.Iterable) && isSubtype(actual, core.Iterable) ||
164 isSubtype(type, async.Future) && isSubtype(actual, async.Future) ||
165 isSubtype(type, core.Map) && isSubtype(actual, core.Map) ||
166 isSubtype(type, core.Function) && isSubtype(actual, core.Function)) {
167 console.error('Ignoring cast fail from ' + _typeName(actual) +
168 ' to ' + _typeName(type));
169 return true;
170 }
171 return false;
172 }
173
174 function cast(obj, type) {
175 // TODO(vsm): handle non-nullable types
176 if (obj == null) return obj;
177 let actual = realRuntimeType(obj);
178 if (isSubtype(actual, type)) return obj;
179 if (_ignoreTypeFailure(actual, type)) return obj;
180 throw new _js_helper.CastErrorImplementation(actual, type);
181 }
182 dart.as = cast;
183
184
185 // TODO(vsm): How should we encode the runtime type?
186 const _runtimeType = Symbol('_runtimeType');
187
188 function checkPrimitiveType(obj) {
189 switch (typeof obj) {
190 case "undefined":
191 return core.Null;
192 case "number":
193 return Math.floor(obj) == obj ? core.int : core.double;
194 case "boolean":
195 return core.bool;
196 case "string":
197 return core.String;
198 case "symbol":
199 return Symbol;
200 }
201 // Undefined is handled above. For historical reasons,
202 // typeof null == "object" in JS.
203 if (obj === null) return core.Null;
204 return null;
205 }
206
207 /**
208 * Returns the runtime type of obj. This is the same as `obj.realRuntimeType`
209 * but will not call an overridden getter.
210 *
211 * Currently this will return null for non-Dart objects.
212 */
213 function realRuntimeType(obj) {
214 let result = checkPrimitiveType(obj);
215 if (result !== null) return result;
216 // TODO(vsm): Should we treat Dart and JS objects differently here?
217 // E.g., we can check if obj instanceof core.Object to differentiate.
218 result = obj[_runtimeType];
219 if (result) return result;
220 result = obj.constructor;
221 if (result == Function) {
222 return getFunctionType(obj);
223 }
224 return result;
225 }
226 dart.realRuntimeType = realRuntimeType;
227
228 function instanceOf(obj, type) {
229 return isSubtype(realRuntimeType(obj), type);
230 }
231 dart.is = instanceOf;
232
233 function instanceOfOrNull(obj, type) {
234 // FIXME(vsm): This is used only in checkApply.
235 // Just log failures due to generics for now.
236 if ((obj == null) || instanceOf(obj, type)) return true;
237 let actual = realRuntimeType(obj);
238 if (_ignoreTypeFailure(actual, type)) return true;
239 return false;
240 }
241
242 /**
243 * Computes the canonical type.
244 * This maps JS types onto their corresponding Dart Type.
245 */
246 // TODO(jmesserly): lots more needs to be done here.
247 function canonicalType(t) {
248 if (t === Object) return core.Object;
249 if (t === Function) return core.Function;
250 if (t === Array) return core.List;
251
252 // We shouldn't normally get here with these types, unless something strange
253 // happens like subclassing Number in JS and passing it to Dart.
254 if (t === String) return core.String;
255 if (t === Number) return core.double;
256 if (t === Boolean) return core.bool;
257 return t;
258 }
259
260 const subtypeMap = new Map();
261 function isSubtype(t1, t2) {
262 // See if we already know the answer
263 // TODO(jmesserly): general purpose memoize function?
264 let map = subtypeMap.get(t1);
265 let result;
266 if (map) {
267 result = map.get(t2);
268 if (result !== void 0) return result;
269 } else {
270 subtypeMap.set(t1, map = new Map());
271 }
272 if (t2 == core.Type) {
273 // Special case Types.
274 result = t1.prototype instanceof core.Type ||
275 t1 instanceof AbstractFunctionType ||
276 isSubtype_(t1, t2);
277 } else {
278 result = isSubtype_(t1, t2)
279 }
280 map.set(t2, result);
281 return result;
282 }
283 dart.isSubtype = isSubtype;
284
285 function _isBottom(type, dynamicIsBottom) {
286 return (type == dart.dynamic && dynamicIsBottom) || type == dart.bottom;
287 }
288
289 function _isTop(type, dynamicIsBottom) {
290 return type == core.Object || (type == dart.dynamic && !dynamicIsBottom);
291 }
292
293 function isSubtype_(t1, t2, opt_dynamicIsBottom) {
294 let dynamicIsBottom =
295 opt_dynamicIsBottom === void 0 ? false : opt_dynamicIsBottom;
296
297 t1 = canonicalType(t1);
298 t2 = canonicalType(t2);
299 if (t1 == t2) return true;
300
301 // In Dart, dynamic is effectively both top and bottom.
302 // Here, we treat dynamic as one or the other depending on context,
303 // but not both.
304
305 // Trivially true.
306 if (_isTop(t2, dynamicIsBottom) || _isBottom(t1, dynamicIsBottom)) {
307 return true;
308 }
309
310 // Trivially false.
311 if (_isTop(t1, dynamicIsBottom) || _isBottom(t2, dynamicIsBottom)) {
312 return false;
313 }
314
315 // "Traditional" name-based subtype check.
316 if (isClassSubType(t1, t2)) {
317 return true;
318 }
319
320 // Function subtyping.
321 // TODO(vsm): Handle Objects with call methods. Those are functions
322 // even if they do not *nominally* subtype core.Function.
323 if (isFunctionType(t1) &&
324 isFunctionType(t2)) {
325 return isFunctionSubType(t1, t2);
326 }
327 return false;
328 }
329
330 function safeGetOwnProperty(obj, name) {
331 let desc = getOwnPropertyDescriptor(obj, name);
332 if (desc) return desc.value;
333 }
334
335 function isClassSubType(t1, t2) {
336 // We support Dart's covariant generics with the caveat that we do not
337 // substitute bottom for dynamic in subtyping rules.
338 // I.e., given T1, ..., Tn where at least one Ti != dynamic we disallow:
339 // - S !<: S<T1, ..., Tn>
340 // - S<dynamic, ..., dynamic> !<: S<T1, ..., Tn>
341 t1 = canonicalType(t1);
342 assert(t2 == canonicalType(t2));
343 if (t1 == t2) return true;
344
345 if (t1 == core.Object) return false;
346
347 // If t1 is a JS Object, we may not hit core.Object.
348 if (t1 == null) return t2 == core.Object || t2 == dart.dynamic;
349
350 // Check if t1 and t2 have the same raw type. If so, check covariance on
351 // type parameters.
352 let raw1 = safeGetOwnProperty(t1, dart.originalDeclaration);
353 let raw2 = safeGetOwnProperty(t2, dart.originalDeclaration);
354 if (raw1 != null && raw1 == raw2) {
355 let typeArguments1 = safeGetOwnProperty(t1, dart.typeArguments);
356 let typeArguments2 = safeGetOwnProperty(t2, dart.typeArguments);
357 let length = typeArguments1.length;
358 if (typeArguments2.length == 0) {
359 // t2 is the raw form of t1
360 return true;
361 } else if (length == 0) {
362 // t1 is raw, but t2 is not
363 return false;
364 }
365 assert(length == typeArguments2.length);
366 for (let i = 0; i < length; ++i) {
367 if (!isSubtype(typeArguments1[i], typeArguments2[i])) {
368 return false;
369 }
370 }
371 return true;
372 }
373
374 // Check superclass.
375 if (isClassSubType(t1.__proto__, t2)) return true;
376
377 // Check mixins.
378 let mixins = safeGetOwnProperty(t1, dart.mixins);
379 if (mixins) {
380 for (let m1 of mixins) {
381 // TODO(jmesserly): remove the != null check once we can load core libs.
382 if (m1 != null && isClassSubType(m1, t2)) return true;
383 }
384 }
385
386 // Check interfaces.
387 let getInterfaces = safeGetOwnProperty(t1, dart.implements);
388 if (getInterfaces) {
389 for (let i1 of getInterfaces()) {
390 // TODO(jmesserly): remove the != null check once we can load core libs.
391 if (i1 != null && isClassSubType(i1, t2)) return true;
392 }
393 }
394
395 return false;
396 }
397
398 // TODO(jmesserly): this isn't currently used, but it could be if we want
399 // `obj is NonGroundType<T,S>` to be rejected at runtime instead of compile
400 // time.
401 function isGroundType(type) {
402 // TODO(vsm): Cache this if we start using it at runtime.
403
404 if (type instanceof AbstractFunctionType) {
405 if (!_isTop(type.returnType, false)) return false;
406 for (let i = 0; i < type.args.length; ++i) {
407 if (!_isBottom(type.args[i], true)) return false;
408 }
409 for (let i = 0; i < type.optionals.length; ++i) {
410 if (!_isBottom(type.optionals[i], true)) return false;
411 }
412 let names = getOwnPropertyNames(type.named);
413 for (let i = 0; i < names.length; ++i) {
414 if (!_isBottom(type.named[names[i]], true)) return false;
415 }
416 return true;
417 }
418
419 let typeArgs = safeGetOwnProperty(type, dart.typeArguments);
420 if (!typeArgs) return true;
421 for (let t of typeArgs) {
422 if (t != core.Object && t != dart.dynamic) return false;
423 }
424 return true;
425 }
426 dart.isGroundType = isGroundType;
427
428 function arity(f) {
429 // TODO(jmesserly): need to parse optional params.
430 // In ES6, length is the number of required arguments.
431 return { min: f.length, max: f.length };
432 }
433 dart.arity = arity;
434
435 function equals(x, y) {
436 if (x == null || y == null) return x == y;
437 let eq = x['=='];
438 return eq ? eq.call(x, y) : x === y;
439 }
440 dart.equals = equals;
441
442 /** Checks that `x` is not null or undefined. */
443 function notNull(x) {
444 if (x == null) throwRuntimeError('expected not-null value');
445 return x;
446 }
447 dart.notNull = notNull;
448
449 class AbstractFunctionType {
450 constructor() {
451 this._stringValue = null;
452 }
453
454 /// Check that a function of this type can be applied to
455 /// actuals.
456 checkApply(actuals) {
457 if (actuals.length < this.args.length) return false;
458 let index = 0;
459 for(let i = 0; i < this.args.length; ++i) {
460 if (!instanceOfOrNull(actuals[i], this.args[i])) return false;
461 ++index;
462 }
463 if (actuals.length == this.args.length) return true;
464 let extras = actuals.length - this.args.length;
465 if (this.optionals.length > 0) {
466 if (extras > this.optionals.length) return false;
467 for(let i = 0, j=index; i < extras; ++i, ++j) {
468 if (!instanceOfOrNull(actuals[j], this.optionals[i])) return false;
469 }
470 return true;
471 }
472 // TODO(leafp): We can't tell when someone might be calling
473 // something expecting an optional argument with named arguments
474
475 if (extras != 1) return false;
476 // An empty named list means no named arguments
477 if (getOwnPropertyNames(this.named).length == 0) return false;
478 let opts = actuals[index];
479 let names = getOwnPropertyNames(opts);
480 // This is something other than a map
481 if (names.length == 0) return false;
482 for (name of names) {
483 if (!(Object.prototype.hasOwnProperty.call(this.named, name))) {
484 return false;
485 }
486 if (!instanceOfOrNull(opts[name], this.named[name])) return false;
487 }
488 return true;
489 }
490
491 toString() { return this.name; }
492
493 get name() {
494 if (this._stringValue) return this._stringValue;
495
496 let buffer = '(';
497 for (let i = 0; i < this.args.length; ++i) {
498 if (i > 0) {
499 buffer += ', ';
500 }
501 buffer += _typeName(this.args[i]);
502 }
503 if (this.optionals.length > 0) {
504 if (this.args.length > 0) buffer += ', ';
505 buffer += '[';
506 for (let i = 0; i < this.optionals.length; ++i) {
507 if (i > 0) {
508 buffer += ', ';
509 }
510 buffer += _typeName(this.optionals[i]);
511 }
512 buffer += ']';
513 } else if (Object.keys(this.named).length > 0) {
514 if (this.args.length > 0) buffer += ', ';
515 buffer += '{';
516 let names = getOwnPropertyNames(this.named).sort();
517 for (let i = 0; i < names.length; ++i) {
518 if (i > 0) {
519 buffer += ', ';
520 }
521 buffer += names[i] + ': ' + _typeName(this.named[names[i]]);
522 }
523 buffer += '}';
524 }
525
526 buffer += ') -> ' + _typeName(this.returnType);
527 this._stringValue = buffer;
528 return buffer;
529 } 25 }
530 } 26 }
531 27
532 class FunctionType extends AbstractFunctionType { 28 exports.global = window || global;
533 constructor(returnType, args, optionals, named) { 29 exports.JsSymbol = _export(Symbol);
534 super();
535 this.returnType = returnType;
536 this.args = args;
537 this.optionals = optionals;
538 this.named = named;
539 }
540 }
541 30
542 /// Tag a closure with a type, using one of three forms: 31 // TODO(vsm): This is referenced (as init.globalState) from
543 /// dart.fn(cls) marks cls has having no optional or named 32 // isolate_helper.dart. Where should it go?
544 /// parameters, with all argument and return types as dynamic 33 // See: https://github.com/dart-lang/dev_compiler/issues/164
545 /// dart.fn(cls, func) marks cls with the lazily computed 34 exports.globalState = null;
546 /// runtime type as computed by func() 35 _js_helper.checkNum = operations.notNull;
547 /// dart.fn(cls, rType, argsT, extras) marks cls as having the
548 /// runtime type dart.functionType(rType, argsT, extras)
549 function fn(closure/* ...args*/) {
550 // Closure and a lazy type constructor
551 if (arguments.length == 2) {
552 defineLazyProperty(closure, _runtimeType, {get : arguments[1]});
553 return closure;
554 }
555 let t;
556 if (arguments.length == 1) {
557 // No type arguments, it's all dynamic
558 let len = closure.length;
559 let build = () => {
560 let args = Array.apply(null, new Array(len)).map(() => core.Object);
561 return functionType(core.Object, args);
562 };
563 // We could be called before Object is defined.
564 if (core.Object === void 0) return fn(closure, build);
565 t = build();
566 } else {
567 // We're passed the piecewise components of the function type,
568 // construct it.
569 let args = slice.call(arguments, 1);
570 t = functionType.apply(null, args);
571 }
572 setRuntimeType(closure, t);
573 return closure;
574 }
575 dart.fn = fn;
576 36
577 function functionType(returnType, args, extra) { 37 // Re-exports
578 // TODO(vsm): Cache / memomize?
579 let optionals;
580 let named;
581 if (extra === void 0) {
582 optionals = [];
583 named = {};
584 } else if (extra instanceof Array) {
585 optionals = extra;
586 named = {};
587 } else {
588 optionals = [];
589 named = extra;
590 }
591 return new FunctionType(returnType, args, optionals, named);
592 }
593 dart.functionType = functionType;
594 38
595 class Typedef extends AbstractFunctionType { 39 // From classes
596 constructor(name, closure) { 40 exportFrom(classes, [
597 super(); 41 'bind',
598 this._name = name; 42 'classGetConstructorType',
599 this._closure = closure; 43 'dartx',
600 this._functionType = null; 44 'defineNamedConstructor',
601 } 45 'defineExtensionNames',
46 'defineExtensionMembers',
47 'generic',
48 'implements',
49 'list',
50 'metadata',
51 'mixin',
52 'registerExtension',
53 'setBaseClass',
54 'setSignature',
55 'virtualField',
56 ])
602 57
603 get name() { 58 // From dart_utils
604 return this._name; 59 exportFrom(dart_utils, ['copyProperties']);
605 } 60 // Renames
61 exports.defineLazyClass = _export(dart_utils.defineLazy);
62 exports.defineLazyProperties = _export(dart_utils.defineLazy);
63 exports.defineLazyClassGeneric = _export(dart_utils.defineLazyProperty);
606 64
607 get functionType() { 65 // From operations
608 if (!this._functionType) { 66 exportFrom(operations, [
609 this._functionType = this._closure(); 67 'JsIterator',
610 } 68 'arity',
611 return this._functionType; 69 'assert',
612 } 70 'const',
71 'dcall',
72 'dindex',
73 'dload',
74 'dput',
75 'dsend',
76 'dsetindex',
77 'equals',
78 'hashCode',
79 'map',
80 'noSuchMethod',
81 'notNull',
82 'stackTrace',
83 'throw_',
84 'toString',
85 ])
86 // Renames
87 exports.as = _export(operations.cast);
88 exports.is = _export(operations.instanceOf);
613 89
614 get returnType() { 90 // From types
615 return this.functionType.returnType; 91 exportFrom(types, [
616 } 92 'bottom',
93 'dynamic',
94 'functionType',
95 'typedef',
96 'typeName',
97 'void',
98 ]);
617 99
618 get args() { 100 // From rtti
619 return this.functionType.args; 101 exportFrom(rtti, [
620 } 102 'fn',
103 'realRuntimeType',
104 'runtimeType',
105 ]);
621 106
622 get optionals() { 107 });
623 return this.functionType.optionals;
624 }
625
626 get named() {
627 return this.functionType.named;
628 }
629 }
630
631 function typedef(name, closure) {
632 return new Typedef(name, closure);
633 }
634 dart.typedef = typedef;
635
636 function isFunctionType(type) {
637 return isClassSubType(type, core.Function) ||
638 type instanceof AbstractFunctionType;
639 }
640
641 function getFunctionType(obj) {
642 // TODO(vsm): Encode this properly on the function for Dart-generated code.
643 let args = Array.apply(null, new Array(obj.length)).map(() => core.Object);
644 return functionType(dart.bottom, args);
645 }
646
647 function isFunctionSubType(ft1, ft2) {
648 if (ft2 == core.Function) {
649 return true;
650 }
651
652 let ret1 = ft1.returnType;
653 let ret2 = ft2.returnType;
654
655 if (!isSubtype_(ret1, ret2)) {
656 // Covariant return types
657 // Note, void (which can only appear as a return type) is effectively
658 // treated as dynamic. If the base return type is void, we allow any
659 // subtype return type.
660 // E.g., we allow:
661 // () -> int <: () -> void
662 if (ret2 != dart.void) {
663 return false;
664 }
665 }
666
667 let args1 = ft1.args;
668 let args2 = ft2.args;
669
670 if (args1.length > args2.length) {
671 return false;
672 }
673
674 for (let i = 0; i < args1.length; ++i) {
675 if (!isSubtype_(args2[i], args1[i], true)) {
676 return false;
677 }
678 }
679
680 let optionals1 = ft1.optionals;
681 let optionals2 = ft2.optionals;
682
683 if (args1.length + optionals1.length < args2.length + optionals2.length) {
684 return false;
685 }
686
687 let j = 0;
688 for (let i = args1.length; i < args2.length; ++i, ++j) {
689 if (!isSubtype_(args2[i], optionals1[j], true)) {
690 return false;
691 }
692 }
693
694 for (let i = 0; i < optionals2.length; ++i, ++j) {
695 if (!isSubtype_(optionals2[i], optionals1[j], true)) {
696 return false;
697 }
698 }
699
700 let named1 = ft1.named;
701 let named2 = ft2.named;
702
703 let names = getOwnPropertyNames(named2);
704 for (let i = 0; i < names.length; ++i) {
705 let name = names[i];
706 let n1 = named1[name];
707 let n2 = named2[name];
708 if (n1 === void 0) {
709 return false;
710 }
711 if (!isSubtype_(n2, n1, true)) {
712 return false;
713 }
714 }
715
716 return true;
717 }
718
719 /**
720 * Defines a lazy property.
721 * After initial get or set, it will replace itself with a value property.
722 */
723 // TODO(jmesserly): is this the best implementation for JS engines?
724 // TODO(jmesserly): reusing descriptor objects has been shown to improve
725 // performance in other projects (e.g. webcomponents.js ShadowDOM polyfill).
726 function defineLazyProperty(to, name, desc) {
727 let init = desc.get;
728 let writable = !!desc.set;
729 function lazySetter(value) {
730 defineProperty(to, name, { value: value, writable: writable });
731 }
732 function lazyGetter() {
733 // Clear the init function to detect circular initialization.
734 let f = init;
735 if (f === null) throwRuntimeError('circular initialization for field ' + n ame);
736 init = null;
737
738 // Compute and store the value.
739 let value = f();
740 lazySetter(value);
741 return value;
742 }
743 desc.get = lazyGetter;
744 desc.configurable = true;
745 if (writable) desc.set = lazySetter;
746 defineProperty(to, name, desc);
747 }
748
749 function defineLazy(to, from) {
750 for (let name of getOwnNamesAndSymbols(from)) {
751 defineLazyProperty(to, name, getOwnPropertyDescriptor(from, name));
752 }
753 }
754 // TODO(jmesserly): these are identical, but this makes it easier to grep for.
755 dart.defineLazyClass = defineLazy;
756 dart.defineLazyProperties = defineLazy;
757 dart.defineLazyClassGeneric = defineLazyProperty;
758
759 function defineMemoizedGetter(obj, name, get) {
760 let cache = null;
761 function getter() {
762 if (cache != null) return cache;
763 cache = get();
764 get = null;
765 return cache;
766 }
767 defineProperty(obj, name, {get: getter, configurable: true});
768 }
769
770 function copyPropertiesHelper(to, from, names) {
771 for (let name of names) {
772 defineProperty(to, name, getOwnPropertyDescriptor(from, name));
773 }
774 return to;
775 }
776
777 /**
778 * Copy properties from source to destination object.
779 * This operation is commonly called `mixin` in JS.
780 */
781 function copyProperties(to, from) {
782 return copyPropertiesHelper(to, from, getOwnNamesAndSymbols(from));
783 }
784 dart.copyProperties = copyProperties;
785
786 function getExtensionSymbol(name) {
787 let sym = dartx[name];
788 if (!sym) dartx[name] = sym = Symbol('dartx.' + name);
789 return sym;
790 }
791
792 function defineExtensionNames(names) {
793 names.forEach(getExtensionSymbol);
794 }
795 dart.defineExtensionNames = defineExtensionNames;
796
797 /**
798 * Copy symbols from the prototype of the source to destination.
799 * These are the only properties safe to copy onto an existing public
800 * JavaScript class.
801 */
802 function registerExtension(jsType, dartExtType) {
803 let extProto = dartExtType.prototype;
804 let jsProto = jsType.prototype;
805
806 // Mark the JS type's instances so we can easily check for extensions.
807 assert(jsProto[_extensionType] === void 0);
808 jsProto[_extensionType] = extProto;
809
810 let dartObjProto = core.Object.prototype;
811 while (extProto !== dartObjProto && extProto !== jsProto) {
812 copyPropertiesHelper(jsProto, extProto, getOwnPropertySymbols(extProto));
813 extProto = extProto.__proto__;
814 }
815 }
816 dart.registerExtension = registerExtension;
817
818 /**
819 * Mark a concrete type as implementing extension methods.
820 * For example: `class MyIter implements Iterable`.
821 *
822 * This takes a list of names, which are the extension methods implemented.
823 * It will add a forwarder, so the extension method name redirects to the
824 * normal Dart method name. For example:
825 *
826 * defineExtensionMembers(MyType, ['add', 'remove']);
827 *
828 * Results in:
829 *
830 * MyType.prototype[dartx.add] = MyType.prototype.add;
831 * MyType.prototype[dartx.remove] = MyType.prototype.remove;
832 */
833 // TODO(jmesserly): essentially this gives two names to the same method.
834 // This benefit is roughly equivalent call performance either way, but the
835 // cost is we need to call defineExtensionMEmbers any time a subclass override s
836 // one of these methods.
837 function defineExtensionMembers(type, methodNames) {
838 let proto = type.prototype;
839 for (let name of methodNames) {
840 let method = getOwnPropertyDescriptor(proto, name);
841 defineProperty(proto, getExtensionSymbol(name), method);
842 }
843 // Ensure the signature is available too.
844 // TODO(jmesserly): not sure if we can do this in a cleaner way. Essentially
845 // we need to copy the signature (and in the future, other data like
846 // annotations) any time we copy a method as part of our metaprogramming.
847 // It might be more friendly to JS metaprogramming if we include this info
848 // on the function.
849 let originalSigFn = getOwnPropertyDescriptor(type, _methodSig).get;
850 defineMemoizedGetter(type, _methodSig, function() {
851 let sig = originalSigFn();
852 for (let name of methodNames) {
853 sig[getExtensionSymbol(name)] = sig[name];
854 }
855 return sig;
856 });
857 }
858 dart.defineExtensionMembers = defineExtensionMembers;
859
860 function setBaseClass(derived, base) {
861 // Link the extension to the type it's extending as a base class.
862 derived.prototype.__proto__ = base.prototype;
863 }
864 dart.setBaseClass = setBaseClass;
865
866 /**
867 * This is called whenever a derived class needs to introduce a new field,
868 * shadowing a field or getter/setter pair on its parent.
869 *
870 * This is important because otherwise, trying to read or write the field
871 * would end up calling the getter or setter, and one of those might not even
872 * exist, resulting in a runtime error. Even if they did exist, that's the
873 * wrong behavior if a new field was declared.
874 */
875 function virtualField(subclass, fieldName) {
876 // If the field is already overridden, do nothing.
877 let prop = getOwnPropertyDescriptor(subclass.prototype, fieldName);
878 if (prop) return;
879
880 let symbol = Symbol(subclass.name + '.' + fieldName);
881 defineProperty(subclass.prototype, fieldName, {
882 get: function() { return this[symbol]; },
883 set: function(x) { this[symbol] = x; }
884 });
885 }
886 dart.virtualField = virtualField;
887
888 /** The Symbol for storing type arguments on a specialized generic type. */
889 dart.mixins = Symbol('mixins');
890 dart.implements = Symbol('implements');
891 dart.metadata = Symbol('metadata');
892
893 /**
894 * Returns a new type that mixes members from base and all mixins.
895 *
896 * Each mixin applies in sequence, with further to the right ones overriding
897 * previous entries.
898 *
899 * For each mixin, we only take its own properties, not anything from its
900 * superclass (prototype).
901 */
902 function mixin(base/*, ...mixins*/) {
903 // Create an initializer for the mixin, so when derived constructor calls
904 // super, we can correctly initialize base and mixins.
905 let mixins = slice.call(arguments, 1);
906
907 // Create a class that will hold all of the mixin methods.
908 class Mixin extends base {
909 // Initializer method: run mixin initializers, then the base.
910 [base.name](/*...args*/) {
911 // Run mixin initializers. They cannot have arguments.
912 // Run them backwards so most-derived mixin is initialized first.
913 for (let i = mixins.length - 1; i >= 0; i--) {
914 let mixin = mixins[i];
915 let init = mixin.prototype[mixin.name];
916 if (init) init.call(this);
917 }
918 // Run base initializer.
919 let init = base.prototype[base.name];
920 if (init) init.apply(this, arguments);
921 }
922 }
923 // Copy each mixin's methods, with later ones overwriting earlier entries.
924 for (let m of mixins) {
925 copyProperties(Mixin.prototype, m.prototype);
926 }
927
928 // Set the signature of the Mixin class to be the composition
929 // of the signatures of the mixins.
930 dart.setSignature(Mixin, {
931 methods: () => {
932 let s = {};
933 for (let m of mixins) {
934 copyProperties(s, m[_methodSig]);
935 }
936 return s;
937 }
938 });
939
940 // Save mixins for reflection
941 Mixin[dart.mixins] = mixins;
942 return Mixin;
943 }
944 dart.mixin = mixin;
945
946 /**
947 * Creates a dart:collection LinkedHashMap.
948 *
949 * For a map with string keys an object literal can be used, for example
950 * `map({'hi': 1, 'there': 2})`.
951 *
952 * Otherwise an array should be used, for example `map([1, 2, 3, 4])` will
953 * create a map with keys [1, 3] and values [2, 4]. Each key-value pair
954 * should be adjacent entries in the array.
955 *
956 * For a map with no keys the function can be called with no arguments, for
957 * example `map()`.
958 */
959 // TODO(jmesserly): this could be faster
960 function map(values) {
961 let map = collection.LinkedHashMap.new();
962 if (Array.isArray(values)) {
963 for (let i = 0, end = values.length - 1; i < end; i += 2) {
964 let key = values[i];
965 let value = values[i + 1];
966 map.set(key, value);
967 }
968 } else if (typeof values === 'object') {
969 for (let key of getOwnPropertyNames(values)) {
970 map.set(key, values[key]);
971 }
972 }
973 return map;
974 }
975 dart.map = map;
976
977 function assert(condition) {
978 if (!condition) throw new core.AssertionError();
979 }
980 dart.assert = assert;
981
982 function throw_(obj) { throw obj; }
983 dart.throw_ = throw_;
984
985 /**
986 * Given a class and an initializer method name, creates a constructor
987 * function with the same name. For example `new SomeClass.name(args)`.
988 */
989 function defineNamedConstructor(clazz, name) {
990 let proto = clazz.prototype;
991 let initMethod = proto[name];
992 let ctor = function() { return initMethod.apply(this, arguments); };
993 ctor.prototype = proto;
994 // Use defineProperty so we don't hit a property defined on Function,
995 // like `caller` and `arguments`.
996 defineProperty(clazz, name, { value: ctor, configurable: true });
997 }
998 dart.defineNamedConstructor = defineNamedConstructor;
999
1000 function stackTrace(exception) {
1001 return _js_helper.getTraceFromException(exception);
1002 }
1003 dart.stackTrace = stackTrace;
1004
1005 /** The Symbol for storing type arguments on a specialized generic type. */
1006 dart.typeArguments = Symbol('typeArguments');
1007 dart.originalDeclaration = Symbol('originalDeclaration');
1008
1009 /** Memoize a generic type constructor function. */
1010 function generic(typeConstructor) {
1011 let length = typeConstructor.length;
1012 if (length < 1) throwRuntimeError('must have at least one generic type argum ent');
1013
1014 let resultMap = new Map();
1015 function makeGenericType(/*...arguments*/) {
1016 if (arguments.length != length && arguments.length != 0) {
1017 throwRuntimeError('requires ' + length + ' or 0 type arguments');
1018 }
1019 let args = slice.call(arguments);
1020 // TODO(leafp): This should really be core.Object for
1021 // consistency, but Object is not attached to core
1022 // until the entire core library has been processed,
1023 // which is too late.
1024 while (args.length < length) args.push(dart.dynamic);
1025
1026 let value = resultMap;
1027 for (let i = 0; i < length; i++) {
1028 let arg = args[i];
1029 if (arg == null) {
1030 throwRuntimeError('type arguments should not be null: ' + typeConstruc tor);
1031 }
1032 let map = value;
1033 value = map.get(arg);
1034 if (value === void 0) {
1035 if (i + 1 == length) {
1036 value = typeConstructor.apply(null, args);
1037 // Save the type constructor and arguments for reflection.
1038 if (value) {
1039 value[dart.typeArguments] = args;
1040 value[dart.originalDeclaration] = makeGenericType;
1041 }
1042 } else {
1043 value = new Map();
1044 }
1045 map.set(arg, value);
1046 }
1047 }
1048 return value;
1049 }
1050 return makeGenericType;
1051 }
1052 dart.generic = generic;
1053
1054 /// Get the type of a function using the store runtime type
1055 function _getFunctionType(f) {
1056 return f[_runtimeType];
1057 }
1058
1059 /// Get the type of a method using the stored signature
1060 function _getMethodType(obj, name) {
1061 if (obj === void 0) return void 0;
1062 if (obj == null) return void 0;
1063 let sigObj = obj.__proto__.constructor[_methodSig];
1064 if (sigObj === void 0) return void 0;
1065 let parts = sigObj[name];
1066 if (parts === void 0) return void 0;
1067 return functionType.apply(null, parts);
1068 }
1069
1070 /// Get the type of a constructor from a class using the stored signature
1071 /// If name is undefined, returns the type of the default constructor
1072 /// Returns undefined if the constructor is not found.
1073 function _getConstructorType(cls, name) {
1074 if(!name) name = cls.name;
1075 if (cls === void 0) return void 0;
1076 if (cls == null) return void 0;
1077 let sigCtor = cls[_constructorSig];
1078 if (sigCtor === void 0) return void 0;
1079 let parts = sigCtor[name];
1080 if (parts === void 0) return void 0;
1081 return functionType.apply(null, parts);
1082 }
1083 dart.classGetConstructorType = _getConstructorType;
1084
1085 /// Given an object and a method name, tear off the method.
1086 /// Sets the runtime type of the torn off method appropriately,
1087 /// and also binds the object.
1088 /// TODO(leafp): Consider caching the tearoff on the object?
1089 function bind(obj, name) {
1090 let f = obj[name].bind(obj);
1091 let sig = _getMethodType(obj, name);
1092 assert(sig);
1093 setRuntimeType(f, sig);
1094 return f;
1095 }
1096 dart.bind = bind;
1097
1098 // Set up the method signature field on the constructor
1099 function _setMethodSignature(f, sigF) {
1100 defineMemoizedGetter(f, _methodSig, () => {
1101 let sigObj = sigF();
1102 sigObj.__proto__ = f.__proto__[_methodSig];
1103 return sigObj;
1104 });
1105 }
1106
1107 // Set up the constructor signature field on the constructor
1108 function _setConstructorSignature(f, sigF) {
1109 defineMemoizedGetter(f, _constructorSig, sigF);
1110 }
1111
1112 // Set up the static signature field on the constructor
1113 function _setStaticSignature(f, sigF) {
1114 defineMemoizedGetter(f, _staticSig, sigF);
1115 }
1116
1117 // Set the lazily computed runtime type field on static methods
1118 function _setStaticTypes(f, names) {
1119 for (let name of names) {
1120 defineProperty(f[name], _runtimeType, { get: function() {
1121 let parts = f[_staticSig][name];
1122 return functionType.apply(null, parts);
1123 }});
1124 }
1125 }
1126
1127 /// Set up the type signature of a class (constructor object)
1128 /// f is a constructor object
1129 /// signature is an object containing optional properties as follows:
1130 /// methods: A function returning an object mapping method names
1131 /// to method types. The function is evaluated lazily and cached.
1132 /// statics: A function returning an object mapping static method
1133 /// names to types. The function is evalutated lazily and cached.
1134 /// names: An array of the names of the static methods. Used to
1135 /// permit eagerly setting the runtimeType field on the methods
1136 /// while still lazily computing the type descriptor object.
1137 function setSignature(f, signature) {
1138 let constructors =
1139 ('constructors' in signature) ? signature.constructors : () => ({});
1140 let methods =
1141 ('methods' in signature) ? signature.methods : () => ({});
1142 let statics =
1143 ('statics' in signature) ? signature.statics : () => ({});
1144 let names =
1145 ('names' in signature) ? signature.names : [];
1146 _setConstructorSignature(f, constructors);
1147 _setMethodSignature(f, methods);
1148 _setStaticSignature(f, statics);
1149 _setStaticTypes(f, names);
1150 }
1151 dart.setSignature = setSignature;
1152
1153 let _value = Symbol('_value');
1154 /**
1155 * Looks up a sequence of [keys] in [map], recursively, and
1156 * returns the result. If the value is not found, [valueFn] will be called to
1157 * add it. For example:
1158 *
1159 * let map = new Map();
1160 * putIfAbsent(map, [1, 2, 'hi ', 'there '], () => 'world');
1161 *
1162 * ... will create a Map with a structure like:
1163 *
1164 * { 1: { 2: { 'hi ': { 'there ': 'world' } } } }
1165 */
1166 function multiKeyPutIfAbsent(map, keys, valueFn) {
1167 for (let k of keys) {
1168 let value = map.get(k);
1169 if (!value) {
1170 // TODO(jmesserly): most of these maps are very small (e.g. 1 item),
1171 // so it may be worth optimizing for that.
1172 map.set(k, value = new Map());
1173 }
1174 map = value;
1175 }
1176 if (map.has(_value)) return map.get(_value);
1177 let value = valueFn();
1178 map.set(_value, value);
1179 return value;
1180 }
1181
1182 /** The global constant table. */
1183 const constants = new Map();
1184
1185 /**
1186 * Canonicalize a constant object.
1187 *
1188 * Preconditions:
1189 * - `obj` is an objects or array, not a primitive.
1190 * - nested values of the object are themselves already canonicalized.
1191 */
1192 function constant(obj) {
1193 let objectKey = [realRuntimeType(obj)];
1194 // TODO(jmesserly): there's no guarantee in JS that names/symbols are
1195 // returned in the same order.
1196 //
1197 // We could probably get the same order if we're judicious about
1198 // initializing fields in a consistent order across all const constructors.
1199 // Alternatively we need a way to sort them to make consistent.
1200 //
1201 // Right now we use the (name,value) pairs in sequence, which prevents
1202 // an object with incorrect field values being returned, but won't
1203 // canonicalize correctly if key order is different.
1204 for (let name of getOwnNamesAndSymbols(obj)) {
1205 objectKey.push(name);
1206 objectKey.push(obj[name]);
1207 }
1208 return multiKeyPutIfAbsent(constants, objectKey, () => obj);
1209 }
1210 dart.const = constant;
1211
1212 // TODO(vsm): Rationalize these type methods. We're currently using the
1213 // setType / proto scheme for nominal types (e.g., classes) and the
1214 // setRuntimeType / field scheme for structural types (e.g., functions
1215 // - and only in tests for now).
1216 // See: https://github.com/dart-lang/dev_compiler/issues/172
1217
1218 /** Sets the type of `obj` to be `type` */
1219 function setType(obj, type) {
1220 obj.__proto__ = type.prototype;
1221 return obj;
1222 }
1223 dart.setType = setType;
1224
1225 /** Sets the element type of a list literal. */
1226 function list(obj, elementType) {
1227 return setType(obj, _interceptors.JSArray$(elementType));
1228 }
1229 dart.list = list;
1230
1231 /** Sets the internal runtime type of `obj` to be `type` */
1232 function setRuntimeType(obj, type) {
1233 obj[_runtimeType] = type;
1234 }
1235 dart.setRuntimeType = setRuntimeType;
1236
1237 // The following are helpers for Object methods when the receiver
1238 // may be null or primitive. These should only be generated by
1239 // the compiler.
1240 function hashCode(obj) {
1241 if (obj == null) {
1242 return 0;
1243 }
1244 // TODO(vsm): What should we do for primitives and non-Dart objects?
1245 switch (typeof obj) {
1246 case "number":
1247 case "boolean":
1248 return obj & 0x1FFFFFFF;
1249 case "string":
1250 // TODO(vsm): Call the JSString hashCode?
1251 return obj.length;
1252 }
1253 return obj.hashCode;
1254 }
1255 dart.hashCode = hashCode;
1256
1257 function runtimeType(obj) {
1258 let result = checkPrimitiveType(obj);
1259 if (result !== null) return result;
1260 return obj.runtimeType;
1261 }
1262 dart.runtimeType = runtimeType;
1263
1264 function toString(obj) {
1265 if (obj == null) {
1266 return "null";
1267 }
1268 return obj.toString();
1269 }
1270 dart.toString = toString;
1271
1272 function noSuchMethod(obj, invocation) {
1273 if (obj == null) {
1274 throw new core.NoSuchMethodError(obj, invocation.memberName,
1275 invocation.positionalArguments, invocation.namedArguments);
1276 }
1277 switch (typeof obj) {
1278 case "number":
1279 case "boolean":
1280 case "string":
1281 throw new core.NoSuchMethodError(obj, invocation.memberName,
1282 invocation.positionalArguments, invocation.namedArguments);
1283 }
1284 return obj.noSuchMethod(invocation);
1285 }
1286 dart.noSuchMethod = noSuchMethod;
1287
1288 class JsIterator {
1289 constructor(dartIterator) {
1290 this.dartIterator = dartIterator;
1291 }
1292 next() {
1293 let i = this.dartIterator;
1294 let done = !i.moveNext();
1295 return { done: done, value: done ? void 0 : i.current };
1296 }
1297 }
1298 dart.JsIterator = JsIterator;
1299
1300 // TODO(jmesserly/vsm): Right now these are sentinels. They should be type
1301 // objects of some sort, assuming we keep them at runtime.
1302 function _sentinel(_name) {
1303 return {
1304 toString() { return _name; },
1305 get name() { return this.toString(); }
1306 };
1307 }
1308 dart.dynamic = _sentinel('dynamic');
1309 dart.void = _sentinel('void');
1310 dart.bottom = _sentinel('bottom');
1311
1312 dart.global = window || global;
1313 dart.JsSymbol = Symbol;
1314
1315 // Module support. This is a simplified module system for Dart.
1316 // Longer term, we can easily migrate to an existing JS module system:
1317 // ES6, AMD, RequireJS, ....
1318
1319 class LibraryLoader {
1320 constructor(name, defaultValue, imports, lazyImports, loader) {
1321 this._name = name;
1322 this._library = defaultValue ? defaultValue : {};
1323 this._imports = imports;
1324 this._lazyImports = lazyImports;
1325 this._loader = loader;
1326
1327 // Cyclic import detection
1328 this._state = LibraryLoader.NOT_LOADED;
1329 }
1330
1331 loadImports(pendingSet) {
1332 return this.handleImports(this._imports, (lib) => lib.load(pendingSet));
1333 }
1334
1335 deferLazyImports(pendingSet) {
1336 return this.handleImports(this._lazyImports,
1337 (lib) => {
1338 pendingSet.add(lib._name);
1339 return lib.stub();
1340 });
1341 }
1342
1343 loadLazyImports(pendingSet) {
1344 return this.handleImports(pendingSet, (lib) => lib.load());
1345 }
1346
1347 handleImports(list, handler) {
1348 let results = [];
1349 for (let name of list) {
1350 let lib = libraries[name];
1351 if (!lib) {
1352 throwRuntimeError('Library not available: ' + name);
1353 }
1354 results.push(handler(lib));
1355 }
1356 return results;
1357 }
1358
1359 load(inheritedPendingSet) {
1360 // Check for cycles
1361 if (this._state == LibraryLoader.LOADING) {
1362 throwRuntimeError('Circular dependence on library: ' + this._name);
1363 } else if (this._state >= LibraryLoader.LOADED) {
1364 return this._library;
1365 }
1366 this._state = LibraryLoader.LOADING;
1367
1368 // Handle imports and record lazy imports
1369 let pendingSet = inheritedPendingSet ? inheritedPendingSet : new Set();
1370 let args = this.loadImports(pendingSet);
1371 args = args.concat(this.deferLazyImports(pendingSet));
1372
1373 // Load the library
1374 args.unshift(this._library);
1375 this._loader.apply(null, args);
1376 this._state = LibraryLoader.LOADED;
1377
1378 // Handle lazy imports
1379 if (inheritedPendingSet === void 0) {
1380 // Drain the queue
1381 this.loadLazyImports(pendingSet);
1382 }
1383 this._state = LibraryLoader.READY;
1384 return this._library;
1385 }
1386
1387 stub() {
1388 return this._library;
1389 }
1390 }
1391 LibraryLoader.NOT_LOADED = 0;
1392 LibraryLoader.LOADING = 1;
1393 LibraryLoader.LOADED = 2;
1394 LibraryLoader.READY = 3;
1395
1396 // Map from name to LibraryLoader
1397 let libraries = new Map();
1398
1399 function library(name, defaultValue, imports, lazyImports, loader) {
1400 return libraries[name] =
1401 new LibraryLoader(name, defaultValue, imports, lazyImports, loader);
1402 }
1403 dart.library = library;
1404
1405 function import_(libraryName) {
1406 bootstrap();
1407 let loader = libraries[libraryName];
1408 return loader.load();
1409 }
1410 dart.import = import_;
1411
1412 function start(libraryName) {
1413 let library = import_(libraryName);
1414 _isolate_helper.startRootIsolate(library.main, []);
1415 }
1416 dart.start = start;
1417
1418 // Libraries used in this file.
1419 let core;
1420 let collection;
1421 let async;
1422 let _interceptors;
1423 let _isolate_helper;
1424 let _js_helper;
1425 let _js_primitives;
1426
1427 let _bootstrapped = false;
1428 function bootstrap() {
1429 if (_bootstrapped) return;
1430 _bootstrapped = true;
1431
1432 // Setup stubs for top-level symbols.
1433 let lazyImport = (name) => libraries[name].stub();
1434 core = lazyImport('dart/core');
1435 collection = lazyImport('dart/collection');
1436 async = lazyImport('dart/async');
1437 _interceptors = lazyImport('dart/_interceptors');
1438 _isolate_helper = lazyImport('dart/_isolate_helper');
1439 _js_helper = lazyImport('dart/_js_helper');
1440 _js_helper.checkNum = notNull;
1441 _js_primitives = lazyImport('dart/_js_primitives');
1442 _js_primitives.printString = (s) => console.log(s);
1443
1444 // Create namespace for dart extension members.
1445 dartx = dartx || {};
1446
1447 // Force import of core.
1448 import_('dart/core');
1449
1450 // TODO(vsm): DOM facades?
1451 // See: https://github.com/dart-lang/dev_compiler/issues/173
1452 NodeList.prototype.get = function(i) { return this[i]; };
1453 NamedNodeMap.prototype.get = function(i) { return this[i]; };
1454 DOMTokenList.prototype.get = function(i) { return this[i]; };
1455 HTMLCollection.prototype.get = function(i) { return this[i]; };
1456
1457 // TODO(vsm): This is referenced (as init.globalState) from
1458 // isolate_helper.dart. Where should it go?
1459 // See: https://github.com/dart-lang/dev_compiler/issues/164
1460 dart.globalState = null;
1461 }
1462 })(dart || (dart = {}));
OLDNEW
« no previous file with comments | « lib/runtime/dart_library.js ('k') | lib/runtime/dart_utils.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698