diff options
author | Evan Welsh <contact@evanwelsh.com> | 2020-11-14 14:36:27 -0600 |
---|---|---|
committer | Philip Chimento <philip.chimento@gmail.com> | 2021-02-08 19:49:06 -0800 |
commit | 97c2fd83488d567c1d83481478ac7bee2335505b (patch) | |
tree | fcae6afc155843387ea664088f08952d0259af7a /modules/internal | |
parent | 126b93e9a3e1772f609e9676caf9a3b204cc1962 (diff) | |
download | gjs-97c2fd83488d567c1d83481478ac7bee2335505b.tar.gz |
Implement dynamic imports
(Changes from Philip folded in: tests, moving file operations into
internal.cpp, some added comments)
Diffstat (limited to 'modules/internal')
-rw-r--r-- | modules/internal/.eslintrc.yml | 1 | ||||
-rw-r--r-- | modules/internal/loader.js | 80 |
2 files changed, 81 insertions, 0 deletions
diff --git a/modules/internal/.eslintrc.yml b/modules/internal/.eslintrc.yml index b06bc212..2889cc64 100644 --- a/modules/internal/.eslintrc.yml +++ b/modules/internal/.eslintrc.yml @@ -19,6 +19,7 @@ globals: compileModule: readonly compileInternalModule: readonly loadResourceOrFile: readonly + loadResourceOrFileAsync: readonly parseURI: readonly uriExists: readonly resolveRelativeResourceOrFile: readonly diff --git a/modules/internal/loader.js b/modules/internal/loader.js index fde96eb0..f28814c9 100644 --- a/modules/internal/loader.js +++ b/modules/internal/loader.js @@ -122,6 +122,79 @@ class ModuleLoader extends InternalModuleLoader { return this.resolveBareSpecifier(specifier); } + + moduleResolveAsyncHook(importingModulePriv, specifier) { + // importingModulePriv may be falsy in the case of gjs_context_eval() + if (!importingModulePriv || !importingModulePriv.uri) + throw new ImportError('Cannot resolve relative imports from an unknown file.'); + + return this.resolveModuleAsync(specifier, importingModulePriv.uri); + } + + /** + * Resolves a module import with optional handling for relative imports asynchronously. + * + * @param {string} specifier the specifier (e.g. relative path, root package) to resolve + * @param {string | null} importingModuleURI the URI of the module + * triggering this resolve + * @returns {import("../types").Module} + */ + async resolveModuleAsync(specifier, importingModuleURI) { + const registry = getRegistry(this.global); + + // Check if the module has already been loaded + let module = registry.get(specifier); + if (module) + return module; + + // 1) Resolve path and URI-based imports. + const uri = this.resolveSpecifier(specifier, importingModuleURI); + if (uri) { + module = registry.get(uri.uri); + + // Check if module is already loaded (relative handling) + if (module) + return module; + + const result = await this.loadURIAsync(uri); + if (!result) + return null; + + const [text, internal = false] = result; + + const priv = new ModulePrivate(uri.uri, uri.uri, internal); + const compiled = this.compileModule(priv, text); + + registry.set(uri.uri, compiled); + return compiled; + } + + // 2) Resolve internal imports. + + return this.resolveBareSpecifier(specifier); + } + + /** + * Loads a file or resource URI asynchronously + * + * @param {Uri} uri the file or resource URI to load + * @returns {Promise<[string] | [string, boolean] | null>} + */ + async loadURIAsync(uri) { + if (uri.scheme) { + const loader = this.schemeHandlers.get(uri.scheme); + + if (loader) + return loader.loadAsync(uri); + } + + if (uri.scheme === 'file' || uri.scheme === 'resource') { + const result = await loadResourceOrFileAsync(uri.uri); + return [result]; + } + + return null; + } } const moduleLoader = new ModuleLoader(moduleGlobalThis); @@ -167,4 +240,11 @@ moduleLoader.registerScheme('gi', { return [generateGIModule(namespace, version), true]; }, + /** + * @param {import("./internalLoader.js").Uri} uri the URI to load asynchronously + */ + loadAsync(uri) { + // gi: only does string manipulation, so it is safe to use the same code for sync and async. + return this.load(uri); + }, }); |