typescript-to-lua
Version:
A generic TypeScript to Lua transpiler. Write your code in TypeScript and publish Lua!
133 lines • 6.25 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.sourceMapTracebackBundlePlaceholder = void 0;
exports.printStackTraceBundleOverride = printStackTraceBundleOverride;
exports.getBundleResult = getBundleResult;
const path = require("path");
const source_map_1 = require("source-map");
const CompilerOptions_1 = require("../CompilerOptions");
const LuaPrinter_1 = require("../LuaPrinter");
const utils_1 = require("../utils");
const diagnostics_1 = require("./diagnostics");
const transpiler_1 = require("./transpiler");
const createModulePath = (pathToResolve, program) => (0, LuaPrinter_1.escapeString)((0, utils_1.formatPathToLuaPath)((0, utils_1.trimExtension)((0, transpiler_1.getEmitPathRelativeToOutDir)(pathToResolve, program))));
// Override `require` to read from ____modules table.
function requireOverride(options) {
const runModule = options.luaTarget === CompilerOptions_1.LuaTarget.Lua50
? "if (table.getn(arg) > 0) then value = module(unpack(arg)) else value = module(file) end"
: 'if (select("#", ...) > 0) then value = module(...) else value = module(file) end';
return `
local ____modules = {}
local ____moduleCache = {}
local ____originalRequire = require
local function require(file, ...)
if ____moduleCache[file] then
return ____moduleCache[file].value
end
if ____modules[file] then
local module = ____modules[file]
local value = nil
${runModule}
____moduleCache[file] = { value = value }
return value
else
if ____originalRequire then
return ____originalRequire(file)
else
error("module '" .. file .. "' not found")
end
end
end
`;
}
exports.sourceMapTracebackBundlePlaceholder = "{#SourceMapTracebackBundle}";
function printStackTraceBundleOverride(rootNode) {
const map = {};
const getLineNumber = (line, fallback) => {
const data = map[line];
if (data === undefined) {
return fallback;
}
if (typeof data === "number") {
return data;
}
return data.line;
};
const transformLineData = (data) => {
if (typeof data === "number") {
return data;
}
return `{line = ${data.line}, file = "${data.file}"}`;
};
let currentLine = 1;
rootNode.walk((chunk, mappedPosition) => {
if (mappedPosition.line !== undefined && mappedPosition.line > 0) {
const line = getLineNumber(currentLine, mappedPosition.line);
map[currentLine] = {
line,
file: path.basename(mappedPosition.source),
};
}
currentLine += chunk.split("\n").length - 1;
});
const mapItems = Object.entries(map).map(([line, original]) => `["${line}"] = ${transformLineData(original)}`);
const mapString = "{" + mapItems.join(",") + "}";
return `__TS__SourceMapTraceBack(debug.getinfo(1).short_src, ${mapString});`;
}
function getBundleResult(program, files) {
var _a, _b, _c;
const diagnostics = [];
const options = program.getCompilerOptions();
const bundleFile = (0, utils_1.cast)(options.luaBundle, utils_1.isNonNull);
const entryModule = (0, utils_1.cast)(options.luaBundleEntry, utils_1.isNonNull);
// Resolve project settings relative to project file.
const resolvedEntryModule = path.resolve((0, transpiler_1.getProjectRoot)(program), entryModule);
const outputPath = path.resolve((0, transpiler_1.getEmitOutDir)(program), bundleFile);
const entryModuleFilePath = (_b = (_a = program.getSourceFile(entryModule)) === null || _a === void 0 ? void 0 : _a.fileName) !== null && _b !== void 0 ? _b : (_c = program.getSourceFile(resolvedEntryModule)) === null || _c === void 0 ? void 0 : _c.fileName;
if (entryModuleFilePath === undefined) {
diagnostics.push((0, diagnostics_1.couldNotFindBundleEntryPoint)(entryModule));
}
// For each file: ["<module path>"] = function() <lua content> end,
const moduleTableEntries = files.map(f => moduleSourceNode(f, createModulePath(f.fileName, program)));
// Create ____modules table containing all entries from moduleTableEntries
const moduleTable = createModuleTableNode(moduleTableEntries);
// return require("<entry module path>")
const args = options.luaTarget === CompilerOptions_1.LuaTarget.Lua50 ? "unpack(arg == nil and {} or arg)" : "...";
const entryPoint = `return require(${createModulePath(entryModuleFilePath !== null && entryModuleFilePath !== void 0 ? entryModuleFilePath : entryModule, program)}, ${args})\n`;
const footers = [];
if (options.sourceMapTraceback) {
// Generates SourceMapTraceback for the entire file
footers.push('local __TS__SourceMapTraceBack = require("lualib_bundle").__TS__SourceMapTraceBack\n');
footers.push(`${exports.sourceMapTracebackBundlePlaceholder}\n`);
}
const sourceChunks = [requireOverride(options), moduleTable, ...footers, entryPoint];
if (!options.noHeader) {
sourceChunks.unshift(LuaPrinter_1.tstlHeader);
}
const bundleNode = joinSourceChunks(sourceChunks);
let { code, map } = bundleNode.toStringWithSourceMap();
code = code.replace(exports.sourceMapTracebackBundlePlaceholder, printStackTraceBundleOverride(bundleNode));
return [
diagnostics,
{
outputPath,
code,
sourceMap: map.toString(),
sourceFiles: files.flatMap(x => { var _a; return (_a = x.sourceFiles) !== null && _a !== void 0 ? _a : []; }),
},
];
}
function moduleSourceNode({ code, sourceMapNode }, modulePath) {
const tableEntryHead = `[${modulePath}] = function(...) \n`;
const tableEntryTail = " end,\n";
return joinSourceChunks([tableEntryHead, sourceMapNode !== null && sourceMapNode !== void 0 ? sourceMapNode : code, tableEntryTail]);
}
function createModuleTableNode(fileChunks) {
const tableHead = "____modules = {\n";
const tableEnd = "}\n";
return joinSourceChunks([tableHead, ...fileChunks, tableEnd]);
}
function joinSourceChunks(chunks) {
return new source_map_1.SourceNode(null, null, null, chunks);
}
//# sourceMappingURL=bundle.js.map