typescript-to-lua
Version:
A generic TypeScript to Lua transpiler. Write your code in TypeScript and publish Lua!
168 lines • 7.83 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.sourceMapTracebackBundlePlaceholder = void 0;
exports.printStackTraceBundleOverride = printStackTraceBundleOverride;
exports.getBundleResult = getBundleResult;
const path = __importStar(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)" : "...";
// Avoid producing a tail-call (which removes the bundle's stack frame) by assigning the `require` result to a local and returning it.
const entryPath = createModulePath(entryModuleFilePath !== null && entryModuleFilePath !== void 0 ? entryModuleFilePath : entryModule, program);
const entryPoint = `local ____entry = require(${entryPath}, ${args})\nreturn ____entry\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