Index: lib/runtime/dart_runtime.js |
diff --git a/lib/runtime/dart_runtime.js b/lib/runtime/dart_runtime.js |
index 8f48253d762d6cca2dd7ef5f2b5c182940d518bf..f10d927ad0ec2b35a9f5f07e583fb3c4d4b87273 100644 |
--- a/lib/runtime/dart_runtime.js |
+++ b/lib/runtime/dart_runtime.js |
@@ -1298,97 +1298,140 @@ 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(); |
+ // 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; |
- // 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) |
+ // 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)); |
} |
- return libraries[name]; |
- } |
- const lazyImport = initializeLibraryStub; |
- function defineLibrary(name, defaultValue) { |
- if (loadedLibraries.has(name)) { |
- throwRuntimeError('Library is already defined: ' + name); |
+ deferLazyImports(pendingSet) { |
+ return this.handleImports(this._lazyImports, |
+ (lib) => { |
+ pendingSet.add(lib._name); |
+ return lib.stub(); |
+ }); |
} |
- var value; |
- if (defaultValue) { |
- var oldValue = libraries[name]; |
- if (oldValue && oldValue != defaultValue) { |
- throwRuntimeError( |
- `Library ${name} cannot be redefined to ${defaultValue}`); |
+ |
+ loadLazyImports(pendingSet) { |
+ return this.handleImports(pendingSet, (lib) => lib.load()); |
+ } |
+ |
+ handleImports(list, handler) { |
+ var results = []; |
+ for (let name of list) { |
+ var lib = libraries[name]; |
Jennifer Messerly
2015/06/09 14:51:52
let?
|
+ 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(); |
+ var args = this.loadImports(pendingSet); |
Jennifer Messerly
2015/06/09 14:51:51
here too
|
+ 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 |
+ var libraries = new Map(); |
+ |
+ function library(name, defaultValue, imports, lazyImports, loader) { |
+ libraries[name] = new LibraryLoader(name, defaultValue, imports, lazyImports, loader); |
Jennifer Messerly
2015/06/09 14:51:51
long line
|
} |
dart.library = library; |
+ function import_(libraryName) { |
+ bootstrap(); |
+ let loader = libraries[libraryName]; |
+ let library = loader.load(); |
+ return library; |
Jennifer Messerly
2015/06/09 14:51:52
very minor, but, the webstorm editor has a hint fo
|
+ } |
+ 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. |
+ var core; |
Jennifer Messerly
2015/06/09 14:51:51
I think these could be `let` too?
Main benefit of
|
+ var collection; |
+ var async; |
+ var _interceptors; |
+ var _isolate_helper; |
+ var _js_helper; |
+ var _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]; }; |
+ |
+ /** Dart extension members. */ |
+ dartx = dartx || {}; |
+ } |
})(dart || (dart = {})); |