diff --git a/js/compiler.ts b/js/compiler.ts index 84330490fa..fcbfc7c5ef 100644 --- a/js/compiler.ts +++ b/js/compiler.ts @@ -17,11 +17,6 @@ type AmdErrback = (err: any) => void; export type AmdFactory = (...args: any[]) => object | void; // tslint:enable:no-any export type AmdDefine = (deps: string[], factory: AmdFactory) => void; -type AmdRequire = ( - deps: string[], - callback: AmdCallback, - errback?: AmdErrback -) => void; // The location that a module is being loaded from. This could be a directory, // like ".", or it could be a module specifier like @@ -264,44 +259,42 @@ export class DenoCompiler implements ts.LanguageServiceHost { const localDefine = (deps: string[], factory: AmdFactory): void => { // TypeScript will emit a local require dependency when doing dynamic // `import()` - const localRequire: AmdRequire = ( + const { _log: log } = this; + const localExports = moduleMetaData.exports; + + // tslint:disable-next-line:no-any + const resolveDependencies = (deps: string[]): any[] => { + return deps.map(dep => { + if (dep === "require") { + return localRequire; + } else if (dep === "exports") { + return localExports; + } else if (dep in DenoCompiler._builtins) { + return DenoCompiler._builtins[dep]; + } else { + const depModuleMetaData = this.run(dep, moduleMetaData.fileName); + return depModuleMetaData.exports; + } + }); + }; + + // this is a function because we need hoisting + function localRequire( deps: string[], callback: AmdCallback, - errback?: AmdErrback - ): void => { - this._log("localRequire", deps); + errback: AmdErrback + ): void { + log("localRequire", deps); try { - const args = deps.map(dep => { - if (dep in DenoCompiler._builtins) { - return DenoCompiler._builtins[dep]; - } else { - const depModuleMetaData = this.run(dep, moduleMetaData.fileName); - return depModuleMetaData.exports; - } - }); + const args = resolveDependencies(deps); callback(...args); } catch (e) { - if (errback) { - errback(e); - } else { - throw e; - } + errback(e); } - }; - const localExports = moduleMetaData.exports; + } + this._log("localDefine", moduleMetaData.fileName, deps, localExports); - const args = deps.map(dep => { - if (dep === "require") { - return localRequire; - } else if (dep === "exports") { - return localExports; - } else if (dep in DenoCompiler._builtins) { - return DenoCompiler._builtins[dep]; - } else { - const depModuleMetaData = this.run(dep, moduleMetaData.fileName); - return depModuleMetaData.exports; - } - }); + const args = resolveDependencies(deps); factory(...args); }; return localDefine; diff --git a/js/compiler_test.ts b/js/compiler_test.ts index d8861e2a98..cc3cda4062 100644 --- a/js/compiler_test.ts +++ b/js/compiler_test.ts @@ -108,6 +108,12 @@ const moduleMap: { "/root/project/foo/bar.ts", fooBarTsSource, fooBarTsOutput + ), + "./qat.ts": mockModuleInfo( + "foo/qat", + "/root/project/foo/qat.ts", + "export const foo = 'bar'", + null ) } }; @@ -275,6 +281,33 @@ test(function compilerMakeDefine() { // external modules, this is implicitly tested though in // `compilerRunMultiModule` +test(function compilerLocalRequire() { + const moduleMetaData = new ModuleMetaData( + "/root/project/foo/baz.ts", + fooBazTsSource, + fooBazTsOutput + ); + const localDefine = compilerInstance.makeDefine(moduleMetaData); + let requireCallbackCalled = false; + localDefine( + ["require", "exports"], + (_require, _exports, _compiler): void => { + assertEqual(typeof _require, "function"); + _require( + ["./qat.ts"], + _qat => { + requireCallbackCalled = true; + assert(_qat); + }, + () => { + throw new Error("Should not error"); + } + ); + } + ); + assert(requireCallbackCalled, "Factory expected to be called"); +}); + test(function compilerRun() { // equal to `deno foo/bar.ts` reset(); diff --git a/tests/error_005_missing_dynamic_import.ts b/tests/error_005_missing_dynamic_import.ts new file mode 100644 index 0000000000..3cb081a276 --- /dev/null +++ b/tests/error_005_missing_dynamic_import.ts @@ -0,0 +1,3 @@ +(async () => { + const badModule = await import("bad-module.ts"); +})(); diff --git a/tests/error_005_missing_dynamic_import.ts.out b/tests/error_005_missing_dynamic_import.ts.out new file mode 100644 index 0000000000..b28875bc56 --- /dev/null +++ b/tests/error_005_missing_dynamic_import.ts.out @@ -0,0 +1,12 @@ +Error: Cannot resolve module "bad-module.ts" from "[WILDCARD]deno/tests/error_005_missing_dynamic_import.ts". + os.codeFetch message: [WILDCARD] (os error 2) + at throwResolutionError (deno/js/compiler.ts:[WILDCARD]) + at DenoCompiler.resolveModule (deno/js/compiler.ts:[WILDCARD]) + at DenoCompiler.resolveModuleName (deno/js/compiler.ts:[WILDCARD]) + at moduleNames.map.name (deno/js/compiler.ts:[WILDCARD]) + at Array.map () + at DenoCompiler.resolveModuleNames (deno/js/compiler.ts:[WILDCARD]) + at Object.compilerHost.resolveModuleNames (deno/third_party/node_modules/typescript/lib/typescript.js:[WILDCARD]) + at resolveModuleNamesWorker (deno/third_party/node_modules/typescript/lib/typescript.js:[WILDCARD]) + at resolveModuleNamesReusingOldState (deno/third_party/node_modules/typescript/lib/typescript.js:[WILDCARD]) + at processImportedModules (deno/third_party/node_modules/typescript/lib/typescript.js:[WILDCARD])