diff --git a/src/transpilation/resolve.ts b/src/transpilation/resolve.ts index bc5d098c4..59639e2c7 100644 --- a/src/transpilation/resolve.ts +++ b/src/transpilation/resolve.ts @@ -129,6 +129,7 @@ function resolveFileDependencies(file: ProcessedFile, context: ResolutionContext for (const required of findRequiredPaths(file.code)) { // Do no resolve lualib if (required === "lualib_bundle") { + dependencies.push({ fileName: "lualib_bundle", code: "" }); continue; } diff --git a/src/transpilation/transpiler.ts b/src/transpilation/transpiler.ts index b19790b37..e30410f73 100644 --- a/src/transpilation/transpiler.ts +++ b/src/transpilation/transpiler.ts @@ -73,21 +73,24 @@ export class Transpiler { console.log("Constructing emit plan"); } - const lualibRequired = files.some(f => f.code.includes('require("lualib_bundle")')); + // Resolve imported modules and modify output Lua requires + const resolutionResult = resolveDependencies(program, files, this.emitHost); + diagnostics.push(...resolutionResult.diagnostics); + + const lualibRequired = resolutionResult.resolvedFiles.some(f => f.fileName === "lualib_bundle"); if (lualibRequired) { + // Remove lualib placeholders from resolution result + resolutionResult.resolvedFiles = resolutionResult.resolvedFiles.filter(f => f.fileName !== "lualib_bundle"); + if (options.tstlVerbose) { console.log("Including lualib bundle"); } // Add lualib bundle to source dir 'virtually', will be moved to correct output dir in emitPlan const fileName = normalizeSlashes(path.resolve(getSourceDir(program), "lualib_bundle.lua")); - files.unshift({ fileName, code: getLuaLibBundle(this.emitHost) }); + resolutionResult.resolvedFiles.unshift({ fileName, code: getLuaLibBundle(this.emitHost) }); } - // Resolve imported modules and modify output Lua requires - const resolutionResult = resolveDependencies(program, files, this.emitHost); - diagnostics.push(...resolutionResult.diagnostics); - let emitPlan: EmitFile[]; if (isBundleEnabled(options)) { const [bundleDiagnostics, bundleFile] = getBundleResult(program, resolutionResult.resolvedFiles); diff --git a/test/transpile/module-resolution.spec.ts b/test/transpile/module-resolution.spec.ts index f23f77988..80e08ac46 100644 --- a/test/transpile/module-resolution.spec.ts +++ b/test/transpile/module-resolution.spec.ts @@ -394,6 +394,7 @@ test("module resolution uses baseURL to resolve imported files", () => { export const fooResult = foo(); export const barResult = bar(); + export const bazResult = baz(); ` .addExtraFile( "myproject/mydeps/dep1.ts", @@ -423,5 +424,34 @@ test("module resolution uses baseURL to resolve imported files", () => { .expectToEqual({ fooResult: "foo", barResult: "bar", + bazResult: "baz", + }); +}); + +// https://github.com/TypeScriptToLua/TypeScriptToLua/issues/1071 +test("includes lualib_bundle when external lua requests it", () => { + util.testModule` + export { foo } from "./lualibuser"; + ` + .addExtraFile( + "lualibuser.d.ts", + ` + export const foo: string[]; + ` + ) + .addExtraFile( + "lualibuser.lua", + ` + require("lualib_bundle") + + local result = {} + __TS__ArrayPush(result, "foo") + __TS__ArrayPush(result, "bar") + + return { foo = result } + ` + ) + .expectToEqual({ + foo: ["foo", "bar"], }); }); diff --git a/test/util.ts b/test/util.ts index b7f285777..55f06d6ac 100644 --- a/test/util.ts +++ b/test/util.ts @@ -9,7 +9,7 @@ import * as ts from "typescript"; import * as vm from "vm"; import * as tstl from "../src"; import { createEmitOutputCollector } from "../src/transpilation/output-collector"; -import { getEmitOutDir, transpileProject } from "../src"; +import { EmitHost, getEmitOutDir, transpileProject } from "../src"; import { formatPathToLuaPath, normalizeSlashes } from "../src/utils"; const jsonLib = fs.readFileSync(path.join(__dirname, "json.lua"), "utf8"); @@ -190,11 +190,22 @@ export abstract class TestBuilder { ); } + private getEmitHost(): EmitHost { + return { + fileExists: (path: string) => normalizeSlashes(path) in this.extraFiles, + directoryExists: (path: string) => + Object.keys(this.extraFiles).some(f => f.startsWith(normalizeSlashes(path))), + getCurrentDirectory: () => ".", + readFile: (path: string) => this.extraFiles[normalizeSlashes(path)] ?? ts.sys.readFile(path), + writeFile() {}, + }; + } + @memoize public getLuaResult(): tstl.TranspileVirtualProjectResult { const program = this.getProgram(); const collector = createEmitOutputCollector(); - const { diagnostics: transpileDiagnostics } = new tstl.Transpiler().emit({ + const { diagnostics: transpileDiagnostics } = new tstl.Transpiler({ emitHost: this.getEmitHost() }).emit({ program, customTransformers: this.customTransformers, writeFile: collector.writeFile,