Index: lib/runtime/dart_runtime.js |
diff --git a/lib/runtime/dart_runtime.js b/lib/runtime/dart_runtime.js |
index 8f48253d762d6cca2dd7ef5f2b5c182940d518bf..ac24ada78f9fbafa61e3bfbfc811c6a87fedef94 100644 |
--- a/lib/runtime/dart_runtime.js |
+++ b/lib/runtime/dart_runtime.js |
@@ -2,15 +2,10 @@ |
// for details. All rights reserved. Use of this source code is governed by a |
// BSD-style license that can be found in the LICENSE file. |
-var dart, _js_helper, _js_primitives, dartx; |
+var dart, dartx; |
(function (dart) { |
'use strict'; |
- // TODO(vsm): This is referenced (as init.globalState) from |
- // isolate_helper.dart. Where should it go? |
- // See: https://github.com/dart-lang/dev_compiler/issues/164 |
- dart.globalState = null; |
- |
const defineProperty = Object.defineProperty; |
const getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; |
const getOwnPropertyNames = Object.getOwnPropertyNames; |
@@ -35,7 +30,7 @@ var dart, _js_helper, _js_primitives, dartx; |
// types. hasOwnProperty doesn't chase the proto chain. |
// Also, do we want an NSM on regular JS objects? |
// See: https://github.com/dart-lang/dev_compiler/issues/169 |
- var result = obj[field]; |
+ let result = obj[field]; |
// TODO(vsm): Check this more robustly. |
if (typeof result == "function" && !hasOwnProperty.call(obj, field)) { |
@@ -108,7 +103,7 @@ var dart, _js_helper, _js_primitives, dartx; |
let _extensionType = Symbol('extensionType'); |
function _canonicalFieldName(obj, name, args, displayName) { |
if (obj[_extensionType]) { |
- var extension = dartx[name]; |
+ let extension = dartx[name]; |
if (extension) return extension; |
// TODO(jmesserly): in the future we might have types that "overlay" Dart |
// methods while also exposing the full native API, e.g. dart:html vs |
@@ -144,11 +139,11 @@ var dart, _js_helper, _js_primitives, dartx; |
function typeToString(type) { |
if (typeof(type) == "function") { |
- var name = type.name; |
- var args = type[dart.typeArguments]; |
+ let name = type.name; |
+ let args = type[dart.typeArguments]; |
if (args) { |
name += '<'; |
- for (var i = 0; i < args.length; ++i) { |
+ for (let i = 0; i < args.length; ++i) { |
if (i > 0) name += ', '; |
name += typeToString(args[i]); |
} |
@@ -209,7 +204,7 @@ var dart, _js_helper, _js_primitives, dartx; |
* Currently this will return null for non-Dart objects. |
*/ |
function realRuntimeType(obj) { |
- var result = checkPrimitiveType(obj); |
+ let result = checkPrimitiveType(obj); |
if (result !== null) return result; |
// TODO(vsm): Should we treat Dart and JS objects differently here? |
// E.g., we can check if obj instanceof core.Object to differentiate. |
@@ -321,7 +316,7 @@ var dart, _js_helper, _js_primitives, dartx; |
} |
function safeGetOwnProperty(obj, name) { |
- var desc = getOwnPropertyDescriptor(obj, name); |
+ let desc = getOwnPropertyDescriptor(obj, name); |
if (desc) return desc.value; |
} |
@@ -402,7 +397,7 @@ var dart, _js_helper, _js_primitives, dartx; |
for (let i = 0; i < type.optionals.length; ++i) { |
if (!_isBottom(type.optionals[i], true)) return false; |
} |
- var names = getOwnPropertyNames(type.named); |
+ let names = getOwnPropertyNames(type.named); |
for (let i = 0; i < names.length; ++i) { |
if (!_isBottom(type.named[names[i]], true)) return false; |
} |
@@ -441,7 +436,7 @@ var dart, _js_helper, _js_primitives, dartx; |
function _typeName(type) { |
if (type === void 0) throwRuntimeError('Undefined type'); |
- var name = type.name; |
+ let name = type.name; |
if (!name) throwRuntimeError('Unexpected type: ' + type); |
return name; |
} |
@@ -455,7 +450,7 @@ var dart, _js_helper, _js_primitives, dartx; |
/// actuals. |
checkApply(actuals) { |
if (actuals.length < this.args.length) return false; |
- var index = 0; |
+ let index = 0; |
for(let i = 0; i < this.args.length; ++i) { |
if (!instanceOfOrNull(actuals[i], this.args[i])) return false; |
++index; |
@@ -491,7 +486,7 @@ var dart, _js_helper, _js_primitives, dartx; |
get name() { |
if (this._stringValue) return this._stringValue; |
- var buffer = '('; |
+ let buffer = '('; |
for (let i = 0; i < this.args.length; ++i) { |
if (i > 0) { |
buffer += ', '; |
@@ -550,7 +545,7 @@ var dart, _js_helper, _js_primitives, dartx; |
defineLazyProperty(closure, _runtimeType, {get : arguments[1]}); |
return closure; |
} |
- var t; |
+ let t; |
if (arguments.length == 1) { |
// No type arguments, it's all dynamic |
let len = closure.length; |
@@ -574,8 +569,8 @@ var dart, _js_helper, _js_primitives, dartx; |
function functionType(returnType, args, extra) { |
// TODO(vsm): Cache / memomize? |
- var optionals; |
- var named; |
+ let optionals; |
+ let named; |
if (extra === void 0) { |
optionals = []; |
named = {}; |
@@ -638,7 +633,7 @@ var dart, _js_helper, _js_primitives, dartx; |
function getFunctionType(obj) { |
// TODO(vsm): Encode this properly on the function for Dart-generated code. |
- var args = Array.apply(null, new Array(obj.length)).map(() => core.Object); |
+ let args = Array.apply(null, new Array(obj.length)).map(() => core.Object); |
return functionType(dart.bottom, args); |
} |
@@ -682,7 +677,7 @@ var dart, _js_helper, _js_primitives, dartx; |
return false; |
} |
- var j = 0; |
+ let j = 0; |
for (let i = args1.length; i < args2.length; ++i, ++j) { |
if (!isSubtype_(args2[i], optionals1[j], true)) { |
return false; |
@@ -839,9 +834,9 @@ var dart, _js_helper, _js_primitives, dartx; |
// annotations) any time we copy a method as part of our metaprogramming. |
// It might be more friendly to JS metaprogramming if we include this info |
// on the function. |
- var originalSigFn = getOwnPropertyDescriptor(type, _methodSig).get; |
+ let originalSigFn = getOwnPropertyDescriptor(type, _methodSig).get; |
defineMemoizedGetter(type, _methodSig, function() { |
- var sig = originalSigFn(); |
+ let sig = originalSigFn(); |
for (let name of methodNames) { |
sig[getExtensionSymbol(name)] = sig[name]; |
} |
@@ -1148,7 +1143,7 @@ var dart, _js_helper, _js_primitives, dartx; |
* returns the result. If the value is not found, [valueFn] will be called to |
* add it. For example: |
* |
- * var map = new Map(); |
+ * let map = new Map(); |
* putIfAbsent(map, [1, 2, 'hi ', 'there '], () => 'world'); |
* |
* ... will create a Map with a structure like: |
@@ -1247,7 +1242,7 @@ var dart, _js_helper, _js_primitives, dartx; |
dart.hashCode = hashCode; |
function runtimeType(obj) { |
- var result = checkPrimitiveType(obj); |
+ let result = checkPrimitiveType(obj); |
if (result !== null) return result; |
return obj.runtimeType; |
} |
@@ -1283,7 +1278,7 @@ var dart, _js_helper, _js_primitives, dartx; |
} |
next() { |
let i = this.dartIterator; |
- var done = !i.moveNext(); |
+ let done = !i.moveNext(); |
return { done: done, value: done ? void 0 : i.current }; |
} |
} |
@@ -1298,97 +1293,145 @@ var dart, _js_helper, _js_primitives, dartx; |
dart.global = window || global; |
dart.JsSymbol = Symbol; |
- // All libraries, including those that have referenced (lazyImport), |
- // but not yet loaded. |
- var libraries = new Map(); |
- |
- // Completed libraries. |
- var loadedLibraries = new Set(); |
- |
- // Import a library by name. |
- // This is exported for REPL / JS interop convenience. |
- function import_(name) { |
- let loaded = loadedLibraries.has(name); |
- let value = libraries[name]; |
- // TODO(vsm): Change this to a hard throw. |
- // For now, we're missing some libraries. E.g., dart:js: |
- // https://github.com/dart-lang/dev_compiler/issues/168 |
- if (!loaded) { |
- console.warn('Missing required module: ' + name); |
- } else if (!value) { |
- throwRuntimeError('Library import error: ' + name) |
+ // Module support. This is a simplified module system for Dart. |
+ // Longer term, we can easily migrate to an existing JS module system: |
+ // ES6, AMD, RequireJS, .... |
+ |
+ class LibraryLoader { |
+ constructor(name, defaultValue, imports, lazyImports, loader) { |
+ this._name = name; |
+ this._library = defaultValue ? defaultValue : {}; |
+ this._imports = imports; |
+ this._lazyImports = lazyImports; |
+ this._loader = loader; |
+ |
+ // Cyclic import detection |
+ this._state = LibraryLoader.NOT_LOADED; |
} |
- return value; |
- } |
- dart.import = import_; |
- function initializeLibraryStub(name) { |
- // Create the library object if necessary. |
- if (!libraries[name]) { |
- libraries[name] = {}; |
+ loadImports(pendingSet) { |
+ return this.handleImports(this._imports, (lib) => lib.load(pendingSet)); |
+ } |
+ |
+ deferLazyImports(pendingSet) { |
+ return this.handleImports(this._lazyImports, |
+ (lib) => { |
+ pendingSet.add(lib._name); |
+ return lib.stub(); |
+ }); |
} |
- return libraries[name]; |
- } |
- const lazyImport = initializeLibraryStub; |
- function defineLibrary(name, defaultValue) { |
- if (loadedLibraries.has(name)) { |
- throwRuntimeError('Library is already defined: ' + name); |
+ loadLazyImports(pendingSet) { |
+ return this.handleImports(pendingSet, (lib) => lib.load()); |
} |
- var value; |
- if (defaultValue) { |
- var oldValue = libraries[name]; |
- if (oldValue && oldValue != defaultValue) { |
- throwRuntimeError( |
- `Library ${name} cannot be redefined to ${defaultValue}`); |
+ |
+ handleImports(list, handler) { |
+ let results = []; |
+ for (let name of list) { |
+ let lib = libraries[name]; |
+ if (!lib) { |
+ throwRuntimeError('Library not available: ' + name); |
+ } |
+ results.push(handler(lib)); |
} |
- libraries[name] = value = defaultValue; |
- } else { |
- value = initializeLibraryStub(name); |
+ return results; |
} |
- loadedLibraries.add(name); |
- return value; |
- } |
- function library(name, defaultValue, imports, lazyImports, module) { |
- var args = []; |
- var lib = defineLibrary(name, defaultValue); |
- args.push(lib); |
- for (var i = 0; i < imports.length; ++i) { |
- lib = import_(imports[i]); |
- args.push(lib); |
+ load(inheritedPendingSet) { |
+ // Check for cycles |
+ if (this._state == LibraryLoader.LOADING) { |
+ throwRuntimeError('Circular dependence on library: ' + this._name); |
+ } else if (this._state >= LibraryLoader.LOADED) { |
+ return this._library; |
+ } |
+ this._state = LibraryLoader.LOADING; |
+ |
+ // Handle imports and record lazy imports |
+ let pendingSet = inheritedPendingSet ? inheritedPendingSet : new Set(); |
+ let args = this.loadImports(pendingSet); |
+ args = args.concat(this.deferLazyImports(pendingSet)); |
+ |
+ // Load the library |
+ args.unshift(this._library); |
+ this._loader.apply(null, args); |
+ this._state = LibraryLoader.LOADED; |
+ |
+ // Handle lazy imports |
+ if (inheritedPendingSet === void 0) { |
+ // Drain the queue |
+ this.loadLazyImports(pendingSet); |
+ } |
+ this._state = LibraryLoader.READY; |
+ return this._library; |
} |
- for (var i = 0; i < lazyImports.length; ++i) { |
- lib = lazyImport(lazyImports[i]); |
- args.push(lib); |
+ |
+ stub() { |
+ return this._library; |
} |
- module.apply(null, args); |
+ } |
+ LibraryLoader.NOT_LOADED = 0; |
+ LibraryLoader.LOADING = 1; |
+ LibraryLoader.LOADED = 2; |
+ LibraryLoader.READY = 3; |
+ |
+ // Map from name to LibraryLoader |
+ let libraries = new Map(); |
+ |
+ function library(name, defaultValue, imports, lazyImports, loader) { |
+ libraries[name] = |
+ new LibraryLoader(name, defaultValue, imports, lazyImports, loader); |
} |
dart.library = library; |
+ function import_(libraryName) { |
+ bootstrap(); |
+ let loader = libraries[libraryName]; |
+ return loader.load(); |
+ } |
+ dart.import = import_; |
+ |
function start(libraryName) { |
- let lib = import_(libraryName); |
- _isolate_helper.startRootIsolate(lib.main, []); |
+ let library = import_(libraryName); |
+ _isolate_helper.startRootIsolate(library.main, []); |
} |
dart.start = start; |
- let core = lazyImport('dart/core'); |
- let collection = lazyImport('dart/collection'); |
- let async = lazyImport('dart/async'); |
- let _interceptors = lazyImport('dart/_interceptors'); |
- let _isolate_helper = lazyImport('dart/_isolate_helper'); |
- let _js_helper = lazyImport('dart/_js_helper'); |
- _js_helper.checkNum = notNull; |
- let _js_primitives = lazyImport('dart/_js_primitives'); |
- _js_primitives.printString = (s) => console.log(s); |
- |
- // TODO(vsm): DOM facades? |
- // See: https://github.com/dart-lang/dev_compiler/issues/173 |
- NodeList.prototype.get = function(i) { return this[i]; }; |
- NamedNodeMap.prototype.get = function(i) { return this[i]; }; |
- DOMTokenList.prototype.get = function(i) { return this[i]; }; |
- |
- /** Dart extension members. */ |
- dartx = dartx || {}; |
- |
+ // Libraries used in this file. |
+ let core; |
+ let collection; |
+ let async; |
+ let _interceptors; |
+ let _isolate_helper; |
+ let _js_helper; |
+ let _js_primitives; |
+ |
+ function bootstrap() { |
+ if (core) return; |
+ |
+ let lazyImport = (name) => libraries[name].stub(); |
+ |
+ core = lazyImport('dart/core'); |
+ collection = lazyImport('dart/collection'); |
+ async = lazyImport('dart/async'); |
+ _interceptors = lazyImport('dart/_interceptors'); |
+ _isolate_helper = lazyImport('dart/_isolate_helper'); |
+ _js_helper = lazyImport('dart/_js_helper'); |
+ _js_helper.checkNum = notNull; |
+ _js_primitives = lazyImport('dart/_js_primitives'); |
+ _js_primitives.printString = (s) => console.log(s); |
+ |
+ // TODO(vsm): DOM facades? |
+ // See: https://github.com/dart-lang/dev_compiler/issues/173 |
+ NodeList.prototype.get = function(i) { return this[i]; }; |
+ NamedNodeMap.prototype.get = function(i) { return this[i]; }; |
+ DOMTokenList.prototype.get = function(i) { return this[i]; }; |
+ |
+ // TODO(vsm): This is referenced (as init.globalState) from |
+ // isolate_helper.dart. Where should it go? |
+ // See: https://github.com/dart-lang/dev_compiler/issues/164 |
+ dart.globalState = null; |
+ |
+ /** Dart extension members. */ |
+ dartx = dartx || {}; |
+ } |
})(dart || (dart = {})); |