Chromium Code Reviews| 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 = {})); |