@tilua/compiler 8.1.0 → 9.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +108 -13
- package/dist/{chunk-WOBHMGGC.js → chunk-VUIF62OE.js} +406 -56
- package/dist/cli.cjs +572 -95
- package/dist/cli.js +156 -24
- package/dist/index.cjs +415 -63
- package/dist/index.d.cts +52 -9
- package/dist/index.d.ts +52 -9
- package/dist/index.js +14 -5
- package/package.json +3 -3
|
@@ -384,6 +384,10 @@ var SharedRuntime = class {
|
|
|
384
384
|
return { declare, define };
|
|
385
385
|
}
|
|
386
386
|
};
|
|
387
|
+
function moduleArguments(context, name) {
|
|
388
|
+
const loader2 = context.loader?.(name);
|
|
389
|
+
return loader2 ? [string(name), loader2] : [string(name)];
|
|
390
|
+
}
|
|
387
391
|
function lower(program2, scopes, options = {}) {
|
|
388
392
|
const result2 = new Lowerer(program2, scopes, options).run();
|
|
389
393
|
dropUnreachable(result2.statements);
|
|
@@ -700,6 +704,7 @@ var Lowerer = class {
|
|
|
700
704
|
const plugin3 = lowerings[i].plugin;
|
|
701
705
|
if (!plugin3.methodCall) continue;
|
|
702
706
|
const answer = plugin3.methodCall({
|
|
707
|
+
options: lowerings[i].options ?? {},
|
|
703
708
|
method,
|
|
704
709
|
receiver,
|
|
705
710
|
receiverGlobal,
|
|
@@ -731,6 +736,7 @@ var Lowerer = class {
|
|
|
731
736
|
const plugin3 = lowerings[i].plugin;
|
|
732
737
|
if (!plugin3.globalCall) continue;
|
|
733
738
|
const answer = plugin3.globalCall({
|
|
739
|
+
options: lowerings[i].options ?? {},
|
|
734
740
|
name,
|
|
735
741
|
at: this.callSite(node.callee),
|
|
736
742
|
get arguments() {
|
|
@@ -750,6 +756,7 @@ var Lowerer = class {
|
|
|
750
756
|
if (name === void 0) return void 0;
|
|
751
757
|
for (let i = lowerings.length - 1; i >= 0; i--) {
|
|
752
758
|
const answer = lowerings[i].plugin.globalValue?.({
|
|
759
|
+
options: lowerings[i].options ?? {},
|
|
753
760
|
name,
|
|
754
761
|
at: this.callSite(node),
|
|
755
762
|
use: (runtime2) => this.loweringRuntime(i, runtime2)
|
|
@@ -1003,12 +1010,12 @@ end`).body.statements, out);
|
|
|
1003
1010
|
local2 = this.names.fresh(moduleName(key));
|
|
1004
1011
|
moduleLocals.set(key, local2);
|
|
1005
1012
|
locals.push(local2);
|
|
1006
|
-
requires.push(assign([identifier(local2)], [call(context.require,
|
|
1013
|
+
requires.push(assign([identifier(local2)], [call(context.require, moduleArguments(context, key))]));
|
|
1007
1014
|
}
|
|
1008
1015
|
return local2;
|
|
1009
1016
|
};
|
|
1010
1017
|
const load = (key) => {
|
|
1011
|
-
if (!moduleLocals.has(key)) requires.push(callStatement(call(context.require,
|
|
1018
|
+
if (!moduleLocals.has(key)) requires.push(callStatement(call(context.require, moduleArguments(context, key))));
|
|
1012
1019
|
};
|
|
1013
1020
|
const exportBinding = (node, exported) => {
|
|
1014
1021
|
const binding = node && this.bindingByDeclaration.get(node);
|
|
@@ -1117,20 +1124,22 @@ end`).body.statements, out);
|
|
|
1117
1124
|
continue;
|
|
1118
1125
|
}
|
|
1119
1126
|
if (declaration.type === "ClassDeclaration") {
|
|
1120
|
-
body.push(...this.classDeclaration(declaration, "assign"));
|
|
1127
|
+
body.push(...this.classDeclaration(declaration, "assign").map((s) => this.from(s, declaration)));
|
|
1121
1128
|
continue;
|
|
1122
1129
|
}
|
|
1123
1130
|
switch (declaration.type) {
|
|
1131
|
+
// Stamped with where they were written, as any statement is:
|
|
1132
|
+
// an error in a top-level `const` names its line.
|
|
1124
1133
|
case "VariableDeclaration":
|
|
1125
|
-
body.push(...this.variableDeclaration(declaration, "assign"));
|
|
1134
|
+
body.push(...this.variableDeclaration(declaration, "assign").map((s) => this.from(s, declaration)));
|
|
1126
1135
|
break;
|
|
1127
1136
|
case "ExportDefaultStatement": {
|
|
1128
1137
|
const exported = declaration.declaration;
|
|
1129
1138
|
if (exported.type === "ClassDeclaration") {
|
|
1130
|
-
body.push(...this.classDeclaration(exported, "assign"));
|
|
1131
|
-
body.push(assign([member(exportsTable(), "default")], [this.reference(exported.name)]));
|
|
1139
|
+
body.push(...this.classDeclaration(exported, "assign").map((s) => this.from(s, exported)));
|
|
1140
|
+
body.push(this.from(assign([member(exportsTable(), "default")], [this.reference(exported.name)]), declaration));
|
|
1132
1141
|
} else {
|
|
1133
|
-
body.push(assign([member(exportsTable(), "default")], [this.expression(exported)]));
|
|
1142
|
+
body.push(this.from(assign([member(exportsTable(), "default")], [this.expression(exported)]), declaration));
|
|
1134
1143
|
}
|
|
1135
1144
|
break;
|
|
1136
1145
|
}
|
|
@@ -1168,7 +1177,7 @@ end`).body.statements, out);
|
|
|
1168
1177
|
this.report(source, `Cannot find module '${source.value}'`);
|
|
1169
1178
|
return nil();
|
|
1170
1179
|
}
|
|
1171
|
-
return call(context.import ?? context.require,
|
|
1180
|
+
return call(context.import ?? context.require, moduleArguments(context, key));
|
|
1172
1181
|
}
|
|
1173
1182
|
isRewritten(node) {
|
|
1174
1183
|
const binding = this.bindingByDeclaration.get(node);
|
|
@@ -1367,9 +1376,9 @@ end`).body.statements, out);
|
|
|
1367
1376
|
return this.assignment(node);
|
|
1368
1377
|
case "CompoundAssignmentStatement": {
|
|
1369
1378
|
if (node.operator === "??=") return this.nullishAssignment(node);
|
|
1370
|
-
const
|
|
1371
|
-
if (
|
|
1372
|
-
const operator =
|
|
1379
|
+
const join2 = node.operator === "+=" ? this.options.types?.joins.get(node) : void 0;
|
|
1380
|
+
if (join2 === "dynamic") return this.dynamicAddition(node);
|
|
1381
|
+
const operator = join2 === "concat" ? "..=" : node.operator;
|
|
1373
1382
|
if (!this.syntax.has("compoundAssignment")) return this.compoundAssignment51(node, operator);
|
|
1374
1383
|
return [{
|
|
1375
1384
|
type: "CompoundAssignmentStatement",
|
|
@@ -2055,9 +2064,9 @@ end
|
|
|
2055
2064
|
return call(this.helper("instanceof"), [this.keptToOne(left), this.keptToOne(right)]);
|
|
2056
2065
|
}
|
|
2057
2066
|
if (node.operator === "+") {
|
|
2058
|
-
const
|
|
2059
|
-
if (
|
|
2060
|
-
if (
|
|
2067
|
+
const join2 = this.options.types?.joins.get(node);
|
|
2068
|
+
if (join2 === "concat") return binary("..", left, right);
|
|
2069
|
+
if (join2 === "dynamic") return call(this.helper("add"), [this.keptToOne(left), this.keptToOne(right)]);
|
|
2061
2070
|
}
|
|
2062
2071
|
if (!this.syntax.has("floorDivision") && node.operator === "//") return this.floorDivide(left, right);
|
|
2063
2072
|
return binary(node.operator, left, right);
|
|
@@ -2774,7 +2783,7 @@ async function loadLowerings(modules) {
|
|
|
2774
2783
|
});
|
|
2775
2784
|
continue;
|
|
2776
2785
|
}
|
|
2777
|
-
lowerings.push({ plugin: plugin3, from: module.from, library: module.library });
|
|
2786
|
+
lowerings.push({ plugin: plugin3, from: module.from, library: module.library, options: module.options });
|
|
2778
2787
|
} catch (error) {
|
|
2779
2788
|
problems.push({
|
|
2780
2789
|
file: module.file,
|
|
@@ -2786,8 +2795,8 @@ async function loadLowerings(modules) {
|
|
|
2786
2795
|
}
|
|
2787
2796
|
|
|
2788
2797
|
// src/bundle.ts
|
|
2789
|
-
import { readFileSync as readFileSync3, statSync } from "fs";
|
|
2790
|
-
import { basename, dirname, extname, posix, relative, resolve as resolve2 } from "path";
|
|
2798
|
+
import { readdirSync, readFileSync as readFileSync3, statSync } from "fs";
|
|
2799
|
+
import { basename, dirname, extname, isAbsolute, join, posix, relative, resolve as resolve2 } from "path";
|
|
2791
2800
|
import {
|
|
2792
2801
|
parse,
|
|
2793
2802
|
analyzeScopes,
|
|
@@ -2804,7 +2813,7 @@ import {
|
|
|
2804
2813
|
LexError,
|
|
2805
2814
|
luauString as luauString4
|
|
2806
2815
|
} from "@tilua/parser";
|
|
2807
|
-
import { parse as parseLuau2, parseExpressionFromSource as parseExpressionFromSource2, print } from "luau-parser";
|
|
2816
|
+
import { parse as parseLuau2, parseExpressionFromSource as parseExpressionFromSource2, print as print2 } from "luau-parser";
|
|
2808
2817
|
|
|
2809
2818
|
// src/treeshake.ts
|
|
2810
2819
|
function walk(node, visit, parent) {
|
|
@@ -3072,23 +3081,29 @@ function ownExport(f, name) {
|
|
|
3072
3081
|
// src/linemap.ts
|
|
3073
3082
|
import { luauString as luauString3 } from "@tilua/parser";
|
|
3074
3083
|
function statementsOf(node) {
|
|
3075
|
-
|
|
3076
|
-
|
|
3084
|
+
return statementTree(node).statements;
|
|
3085
|
+
}
|
|
3086
|
+
function statementTree(node) {
|
|
3087
|
+
const statements = [];
|
|
3088
|
+
const parents = [];
|
|
3089
|
+
const visit = (value, parent) => {
|
|
3077
3090
|
if (!value || typeof value !== "object") return;
|
|
3078
|
-
if (Array.isArray(value)) return void value.forEach(visit);
|
|
3091
|
+
if (Array.isArray(value)) return void value.forEach((item) => visit(item, parent));
|
|
3079
3092
|
const record = value;
|
|
3093
|
+
let inside = parent;
|
|
3080
3094
|
if (typeof record.type === "string" && record.type.endsWith("Statement")) {
|
|
3081
|
-
|
|
3095
|
+
inside = statements.push(value) - 1;
|
|
3096
|
+
parents.push(parent);
|
|
3082
3097
|
}
|
|
3083
3098
|
for (const [key, child] of Object.entries(record)) {
|
|
3084
|
-
if (key !== "line" && key !== "column") visit(child);
|
|
3099
|
+
if (key !== "line" && key !== "column") visit(child, inside);
|
|
3085
3100
|
}
|
|
3086
3101
|
};
|
|
3087
|
-
visit(node);
|
|
3088
|
-
return
|
|
3102
|
+
visit(node, -1);
|
|
3103
|
+
return { statements, parents };
|
|
3089
3104
|
}
|
|
3090
3105
|
function buildLineMap(emitted, printed, origins) {
|
|
3091
|
-
const before =
|
|
3106
|
+
const { statements: before, parents } = statementTree(emitted);
|
|
3092
3107
|
const after = statementsOf(printed);
|
|
3093
3108
|
if (before.length !== after.length) return /* @__PURE__ */ new Map();
|
|
3094
3109
|
const map = /* @__PURE__ */ new Map();
|
|
@@ -3099,6 +3114,18 @@ function buildLineMap(emitted, printed, origins) {
|
|
|
3099
3114
|
const line = after[i].line.start;
|
|
3100
3115
|
if (!map.has(line)) map.set(line, origin);
|
|
3101
3116
|
}
|
|
3117
|
+
const holds = /* @__PURE__ */ new Set();
|
|
3118
|
+
for (let i = 0; i < before.length; i++) {
|
|
3119
|
+
if (!origins.has(before[i])) continue;
|
|
3120
|
+
for (let up = parents[i]; up >= 0 && !holds.has(up); up = parents[up]) holds.add(up);
|
|
3121
|
+
}
|
|
3122
|
+
for (let i = 0; i < before.length; i++) {
|
|
3123
|
+
const origin = origins.get(before[i]);
|
|
3124
|
+
if (!origin || holds.has(i)) continue;
|
|
3125
|
+
for (let line = after[i].line.start + 1; line <= after[i].line.end; line++) {
|
|
3126
|
+
if (!map.has(line)) map.set(line, origin);
|
|
3127
|
+
}
|
|
3128
|
+
}
|
|
3102
3129
|
return map;
|
|
3103
3130
|
}
|
|
3104
3131
|
var VLQ_DIGITS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
@@ -3130,18 +3157,59 @@ function lineMapSource(map, unpack) {
|
|
|
3130
3157
|
return `${unpack}({${files.map(luauString3).join(",")}},${luauString3(data)})`;
|
|
3131
3158
|
}
|
|
3132
3159
|
|
|
3160
|
+
// src/output.ts
|
|
3161
|
+
import { print, PrintError } from "luau-parser";
|
|
3162
|
+
var WRITTEN = /* @__PURE__ */ new Set([
|
|
3163
|
+
"compoundAssignment",
|
|
3164
|
+
"continue",
|
|
3165
|
+
"ifExpression",
|
|
3166
|
+
"floorDivision",
|
|
3167
|
+
"attributes",
|
|
3168
|
+
"numberLiterals"
|
|
3169
|
+
]);
|
|
3170
|
+
function printOptions(syntax, format = {}) {
|
|
3171
|
+
return {
|
|
3172
|
+
syntax: [...syntax].some((s) => WRITTEN.has(s)) ? "luau" : "lua51",
|
|
3173
|
+
compact: format.minify ?? false,
|
|
3174
|
+
...format.indent !== void 0 && { indent: format.indent }
|
|
3175
|
+
};
|
|
3176
|
+
}
|
|
3177
|
+
function printOutput(node, options) {
|
|
3178
|
+
try {
|
|
3179
|
+
return { code: print(node, options) };
|
|
3180
|
+
} catch (error) {
|
|
3181
|
+
if (!(error instanceof PrintError)) throw error;
|
|
3182
|
+
return {
|
|
3183
|
+
problem: `The output cannot be written as Lua 5.1: ${error.message.replace(/ \(\d+:\d+\)$/, "")}. Nothing in 'types' says the project's Lua has it \u2014 "luau" does, and "roblox" brings "luau"`
|
|
3184
|
+
};
|
|
3185
|
+
}
|
|
3186
|
+
}
|
|
3187
|
+
|
|
3133
3188
|
// src/bundle.ts
|
|
3189
|
+
var WRITTEN_BY_TILUA = "-- Written by tilua";
|
|
3134
3190
|
async function bundle(options) {
|
|
3135
|
-
const entry = resolve2(options.entry);
|
|
3136
3191
|
const diagnostics = [];
|
|
3192
|
+
const from = options.entry !== void 0 ? resolve2(options.entry) : resolve2(options.root ?? process.cwd(), "tilua.config.json");
|
|
3137
3193
|
const inline = options.config !== void 0 && typeof options.config !== "string";
|
|
3138
|
-
const { config, problems } = resolveConfig(options.config,
|
|
3194
|
+
const { config, problems } = resolveConfig(options.config, from, options.root ?? (inline ? dirname(from) : process.cwd()));
|
|
3139
3195
|
for (const p of problems) diagnostics.push({ file: p.file, message: p.message, line: p.line ?? 1, column: p.column ?? 1, category: "config" });
|
|
3140
|
-
const root = resolve2(options.root ?? config?.directory ?? dirname(
|
|
3196
|
+
const root = resolve2(options.root ?? config?.directory ?? dirname(from));
|
|
3141
3197
|
const nameOf = (file) => relative(root, file).replace(/\\/g, "/").replace(/\.tilua$/, "");
|
|
3198
|
+
const mode = options.output ?? config?.output ?? "single";
|
|
3199
|
+
const perFile = mode === "files";
|
|
3200
|
+
const rootDir = resolve2(config?.rootDir ?? root);
|
|
3201
|
+
const entry = options.entry !== void 0 ? resolve2(options.entry) : void 0;
|
|
3202
|
+
const anchor = entry ?? config?.path ?? from;
|
|
3203
|
+
const stop = (message, file = anchor) => ({
|
|
3204
|
+
files: [],
|
|
3205
|
+
modules: [],
|
|
3206
|
+
diagnostics: [...diagnostics, { file, message, line: 1, column: 1, category: "config" }]
|
|
3207
|
+
});
|
|
3208
|
+
if (!perFile && entry === void 0) return stop('No entry to build: only "output": "files" builds without one');
|
|
3142
3209
|
const sources = /* @__PURE__ */ new Map();
|
|
3143
3210
|
const directives = /* @__PURE__ */ new Map();
|
|
3144
|
-
const queue = [entry];
|
|
3211
|
+
const queue = perFile ? tiluaFiles(rootDir) : [entry];
|
|
3212
|
+
if (perFile && !queue.length) return stop(`No .tilua file under ${relative(process.cwd(), rootDir) || "."}`);
|
|
3145
3213
|
while (queue.length) {
|
|
3146
3214
|
const file = queue.shift();
|
|
3147
3215
|
if (sources.has(file)) continue;
|
|
@@ -3159,6 +3227,22 @@ async function bundle(options) {
|
|
|
3159
3227
|
if (target && !target.endsWith(".d.tilua")) queue.push(target);
|
|
3160
3228
|
}
|
|
3161
3229
|
}
|
|
3230
|
+
if (perFile) {
|
|
3231
|
+
const outside = [...sources.keys()].filter((file) => isOutside(rootDir, file));
|
|
3232
|
+
if (outside.length) {
|
|
3233
|
+
return {
|
|
3234
|
+
files: [],
|
|
3235
|
+
modules: [],
|
|
3236
|
+
diagnostics: [...diagnostics, ...outside.map((file) => ({
|
|
3237
|
+
file,
|
|
3238
|
+
message: `This file is imported, but it is outside rootDir (${relative(root, rootDir) || "."}), where every file of "files" output has to be`,
|
|
3239
|
+
line: 1,
|
|
3240
|
+
column: 1,
|
|
3241
|
+
category: "module"
|
|
3242
|
+
}))]
|
|
3243
|
+
};
|
|
3244
|
+
}
|
|
3245
|
+
}
|
|
3162
3246
|
const analysis = analyzeModules([...sources.values()], config);
|
|
3163
3247
|
const { lowerings, problems: loweringProblems } = await loadLowerings(analysis.lowerings);
|
|
3164
3248
|
for (const p of loweringProblems) {
|
|
@@ -3169,19 +3253,56 @@ async function bundle(options) {
|
|
|
3169
3253
|
const G = names.fresh("G");
|
|
3170
3254
|
const requireExpression = member(identifier(G), "require");
|
|
3171
3255
|
const importExpression = member(identifier(G), "import");
|
|
3172
|
-
const mode = options.output ?? config?.output ?? "single";
|
|
3173
3256
|
const byPath = syntaxOf(lowerings).has("requireByPath");
|
|
3257
|
+
if (perFile && !byPath) {
|
|
3258
|
+
return stop(`"output": "files" needs a Lua that requires a file by its path, which Lua 5.1 does not \u2014 add "luau" to 'types' ("roblox" loads it)`, config?.path ?? anchor);
|
|
3259
|
+
}
|
|
3260
|
+
const outputPath = (file) => relative(rootDir, file).replace(/\\/g, "/").replace(/\.tilua$/, ".luau");
|
|
3261
|
+
const fileOfModule = new Map([...sources.values()].map((s) => [s.name, s.file]));
|
|
3262
|
+
const outDir = resolve2(options.outDir ?? config?.outDir ?? rootDir);
|
|
3263
|
+
const written = (file) => join(outDir, outputPath(file));
|
|
3264
|
+
let host;
|
|
3265
|
+
let runtimeFile = join(outDir, "_tilua.luau");
|
|
3266
|
+
if (perFile) {
|
|
3267
|
+
const outputs = [...sources.keys()].map(written);
|
|
3268
|
+
const taken = new Set(outputs.map(pathKey));
|
|
3269
|
+
for (let n = 2; taken.has(pathKey(runtimeFile)); n++) runtimeFile = join(outDir, `_tilua${n}.luau`);
|
|
3270
|
+
for (let i = lowerings.length - 1; i >= 0 && !host; i--) {
|
|
3271
|
+
const { plugin: plugin3, options: own } = lowerings[i];
|
|
3272
|
+
host = plugin3.files?.({ options: own ?? {}, directory: config?.directory ?? root, outDir, files: outputs, runtime: runtimeFile });
|
|
3273
|
+
}
|
|
3274
|
+
for (const problem of host?.problems ?? []) {
|
|
3275
|
+
diagnostics.push({
|
|
3276
|
+
file: problem.file ?? config?.path ?? anchor,
|
|
3277
|
+
message: problem.message,
|
|
3278
|
+
line: 1,
|
|
3279
|
+
column: 1,
|
|
3280
|
+
category: "config",
|
|
3281
|
+
...problem.severity === "warning" && { severity: "warning" }
|
|
3282
|
+
});
|
|
3283
|
+
}
|
|
3284
|
+
if (host?.runtime !== void 0) {
|
|
3285
|
+
if (isOutside(outDir, resolve2(host.runtime))) return stop(`The runtime has to go inside outDir, not at ${host.runtime}`);
|
|
3286
|
+
if (taken.has(pathKey(host.runtime))) return stop(`The runtime cannot go at ${host.runtime}: a module's file is there`);
|
|
3287
|
+
runtimeFile = resolve2(host.runtime);
|
|
3288
|
+
}
|
|
3289
|
+
}
|
|
3290
|
+
const placeOf = (file) => host?.place?.(file) ?? placeInFolder(relative(outDir, file));
|
|
3291
|
+
const requireFrom = (from2, to) => pathBetween(placeOf(from2), placeOf(to), host?.root);
|
|
3292
|
+
const isScript = (file) => host?.script?.(file) ?? false;
|
|
3174
3293
|
const modules = /* @__PURE__ */ new Map();
|
|
3175
3294
|
const origins = /* @__PURE__ */ new WeakMap();
|
|
3176
3295
|
const shared = new SharedRuntime(names);
|
|
3177
3296
|
const shaking = options.treeShaking ?? config?.treeShaking ?? false;
|
|
3178
|
-
const
|
|
3297
|
+
const format = { indent: options.indent ?? config?.indent, minify: options.minify ?? config?.minify ?? false };
|
|
3298
|
+
const printing = printOptions(syntaxOf(lowerings), format);
|
|
3299
|
+
const mapping = !format.minify && (options.lineMap ?? config?.lineMap ?? true);
|
|
3179
3300
|
const resolveIn = (file) => (specifier) => {
|
|
3180
3301
|
const found = resolveModulePath(file, specifier, config);
|
|
3181
3302
|
return found !== void 0 && sources.has(found) ? found : void 0;
|
|
3182
3303
|
};
|
|
3183
|
-
const shaken = shaking ? treeShake([...sources.values()].map((s) => ({ file: s.file, program: s.program, scopes: s.scopes, resolve: resolveIn(s.file) })), entry) : void 0;
|
|
3184
|
-
const pending = [entry];
|
|
3304
|
+
const shaken = shaking && entry !== void 0 && !perFile ? treeShake([...sources.values()].map((s) => ({ file: s.file, program: s.program, scopes: s.scopes, resolve: resolveIn(s.file) })), entry) : void 0;
|
|
3305
|
+
const pending = perFile ? [...sources.keys()] : [entry];
|
|
3185
3306
|
while (pending.length) {
|
|
3186
3307
|
const file = pending.shift();
|
|
3187
3308
|
if (modules.has(file)) continue;
|
|
@@ -3217,6 +3338,13 @@ async function bundle(options) {
|
|
|
3217
3338
|
lines: !mapping ? void 0 : mode === "single" ? `${G}.lines` : `${G}.maps[${luauString4(source.name)}]`,
|
|
3218
3339
|
fail: mapping ? `${G}.fail` : void 0,
|
|
3219
3340
|
arrays: `${G}.arrays`,
|
|
3341
|
+
// The file a module is in, required from this one by its
|
|
3342
|
+
// path, written out.
|
|
3343
|
+
loader: !perFile ? void 0 : (name) => {
|
|
3344
|
+
const target = fileOfModule.get(name);
|
|
3345
|
+
if (target === void 0) return void 0;
|
|
3346
|
+
return parseExpressionFromSource2(`function() return require(${luauString4(requireFrom(written(file), written(target)))}) end`);
|
|
3347
|
+
},
|
|
3220
3348
|
resolve: (specifier, dynamic) => {
|
|
3221
3349
|
const found = resolveModulePath(file, specifier, config);
|
|
3222
3350
|
if (!found || found.endsWith(".d.tilua") || !sources.has(found)) return void 0;
|
|
@@ -3268,6 +3396,102 @@ async function bundle(options) {
|
|
|
3268
3396
|
return { files: [], modules: moduleNames, diagnostics };
|
|
3269
3397
|
}
|
|
3270
3398
|
if (shaking) shared.shake(lowered.flatMap((m) => m.statements));
|
|
3399
|
+
const unwritable = (problem) => ({
|
|
3400
|
+
files: [],
|
|
3401
|
+
modules: moduleNames,
|
|
3402
|
+
diagnostics: [...diagnostics, { file: anchor, message: problem, line: 1, column: 1, category: "config" }]
|
|
3403
|
+
});
|
|
3404
|
+
const write = (node) => {
|
|
3405
|
+
const printed2 = printOutput(node, printing);
|
|
3406
|
+
return "problem" in printed2 ? printed2 : printed2.code;
|
|
3407
|
+
};
|
|
3408
|
+
if (perFile) {
|
|
3409
|
+
const imported = [];
|
|
3410
|
+
for (const [file, source] of sources) {
|
|
3411
|
+
for (const { specifier, line, column } of importSites(source.program)) {
|
|
3412
|
+
const target = resolveIn(file)(specifier);
|
|
3413
|
+
if (target === void 0 || !isScript(written(target))) continue;
|
|
3414
|
+
imported.push({
|
|
3415
|
+
file,
|
|
3416
|
+
line,
|
|
3417
|
+
column,
|
|
3418
|
+
category: "module",
|
|
3419
|
+
message: `'${specifier}' is a script the game runs, which nothing can import: move what it shares into a module of its own`
|
|
3420
|
+
});
|
|
3421
|
+
}
|
|
3422
|
+
}
|
|
3423
|
+
if (imported.length) return { files: [], modules: moduleNames, diagnostics: [...diagnostics, ...imported] };
|
|
3424
|
+
const runtimePath = relative(outDir, runtimeFile).replace(/\\/g, "/");
|
|
3425
|
+
const files2 = [];
|
|
3426
|
+
for (const [file, module] of modules) {
|
|
3427
|
+
const path = outputPath(file);
|
|
3428
|
+
const at = written(file);
|
|
3429
|
+
const script = isScript(at);
|
|
3430
|
+
const prelude = host?.prelude?.(at);
|
|
3431
|
+
const body = [
|
|
3432
|
+
...prelude !== void 0 ? parseLuau2(prelude).body.statements : [],
|
|
3433
|
+
...parseLuau2(`local ${G} = require(${luauString4(requireFrom(at, runtimeFile))})`).body.statements
|
|
3434
|
+
];
|
|
3435
|
+
for (let i = 0; i < module.shared.length; i += 100) {
|
|
3436
|
+
const some = module.shared.slice(i, i + 100);
|
|
3437
|
+
body.push(local(some, some.map((name) => member(member(identifier(G), "shared"), name))));
|
|
3438
|
+
}
|
|
3439
|
+
if (module.usesScriptArgs) body.push(...parseLuau2(`local scriptArgs = ${G}.scriptArgs`).body.statements);
|
|
3440
|
+
body.push(assign(
|
|
3441
|
+
[index(member(identifier(G), "modules"), string(module.name))],
|
|
3442
|
+
[moduleTable(module)]
|
|
3443
|
+
));
|
|
3444
|
+
const value = `${G}.${mapping ? "run" : "require"}(${luauString4(module.name)})`;
|
|
3445
|
+
const returned2 = module.info.exports && !script ? entryReturn(lowerings, module.name, value, () => analysis.exportsOf(file)) : { statements: [], value };
|
|
3446
|
+
if ("problem" in returned2) return stop(returned2.problem.message, file);
|
|
3447
|
+
const ending = parseLuau2(`${returned2.statements.join("\n")}
|
|
3448
|
+
return ${returned2.value}`).body.statements;
|
|
3449
|
+
const chunk = program(body);
|
|
3450
|
+
if (mapping) {
|
|
3451
|
+
const text = write(chunk);
|
|
3452
|
+
if (typeof text !== "string") return unwritable(text.problem);
|
|
3453
|
+
const lines = buildLineMap(chunk, parseLuau2(text), origins);
|
|
3454
|
+
const named = host?.place?.(at) ? `${placeOf(at).join("/")}.luau` : path;
|
|
3455
|
+
body.push(...mapRegistration(G, { path: named, modules: [module] }, lineMapSource(lines, `${G}.lineMap`)));
|
|
3456
|
+
}
|
|
3457
|
+
body.push(...ending);
|
|
3458
|
+
const code = write(chunk);
|
|
3459
|
+
if (typeof code !== "string") return unwritable(code.problem);
|
|
3460
|
+
const from2 = relative(dirname(at), file).replace(/\\/g, "/");
|
|
3461
|
+
files2.push({ path, code: `${code}
|
|
3462
|
+
${WRITTEN_BY_TILUA} from ${from2}: edit that file, not this one.
|
|
3463
|
+
`, modules: [module.name] });
|
|
3464
|
+
}
|
|
3465
|
+
const runtimeProgram = parseLuau2(runtime(G, {
|
|
3466
|
+
several: true,
|
|
3467
|
+
perFile: true,
|
|
3468
|
+
byPath,
|
|
3469
|
+
files: /* @__PURE__ */ new Map(),
|
|
3470
|
+
imports: lowered.some((m) => m.dynamicImports.size > 0),
|
|
3471
|
+
mapping
|
|
3472
|
+
}));
|
|
3473
|
+
const helpers2 = shared.chunk(new Set(lowered.flatMap((m) => m.shared)));
|
|
3474
|
+
const helperNames = helpers2.declare.flatMap((statement) => statement.type === "LocalStatement" ? statement.names.map((n) => n.name) : []);
|
|
3475
|
+
runtimeProgram.body.statements.unshift(...helpers2.declare);
|
|
3476
|
+
runtimeProgram.body.statements.push(...helpers2.define);
|
|
3477
|
+
if (helperNames.length) {
|
|
3478
|
+
runtimeProgram.body.statements.push(assign(
|
|
3479
|
+
[member(identifier(G), "shared")],
|
|
3480
|
+
[table(helperNames.map((name) => field(name, identifier(name))))]
|
|
3481
|
+
));
|
|
3482
|
+
}
|
|
3483
|
+
if (lowered.some((m) => m.usesScriptArgs)) {
|
|
3484
|
+
runtimeProgram.body.statements.push(...parseLuau2(`${G}.scriptArgs = {}
|
|
3485
|
+
${G}.arrays[${G}.scriptArgs] = true`).body.statements);
|
|
3486
|
+
}
|
|
3487
|
+
runtimeProgram.body.statements.push(returns([identifier(G)]));
|
|
3488
|
+
const runtimeCode = write(runtimeProgram);
|
|
3489
|
+
if (typeof runtimeCode !== "string") return unwritable(runtimeCode.problem);
|
|
3490
|
+
files2.push({ path: runtimePath, code: `${runtimeCode}
|
|
3491
|
+
${WRITTEN_BY_TILUA}: the runtime every file of the project requires.
|
|
3492
|
+
`, modules: [] });
|
|
3493
|
+
return { code: files2[0].code, files: files2, modules: moduleNames, diagnostics };
|
|
3494
|
+
}
|
|
3271
3495
|
const several = mode !== "single";
|
|
3272
3496
|
const layout = layoutOf(mode, modules.get(entry), lowered, options.outFile);
|
|
3273
3497
|
const usesScriptArgs = lowered.some((m) => m.usesScriptArgs);
|
|
@@ -3299,17 +3523,24 @@ async function bundle(options) {
|
|
|
3299
3523
|
const result2 = names.fresh("result");
|
|
3300
3524
|
const entryName = luauString4(sources.get(entry).name);
|
|
3301
3525
|
const returnsExports = modules.get(entry).info.exports;
|
|
3302
|
-
const
|
|
3526
|
+
const returned = returnsExports ? entryReturn(lowerings, sources.get(entry).name, mapping ? result2 : `${G}.require(${entryName})`, () => analysis.exportsOf(entry)) : void 0;
|
|
3527
|
+
if (returned && "problem" in returned) return stop(returned.problem.message);
|
|
3528
|
+
const declarations = returned?.statements.join("\n") ?? "";
|
|
3529
|
+
const entryStatements = parseLuau2(!mapping ? `${declarations}
|
|
3530
|
+
${returned ? `return ${returned.value}` : `${G}.require(${entryName})`}` : `
|
|
3303
3531
|
local ${ok}, ${result2} = xpcall(function()
|
|
3304
3532
|
return ${G}.require(${entryName})
|
|
3305
3533
|
end, ${G}.fail)
|
|
3306
3534
|
if not ${ok} then
|
|
3307
3535
|
error(${result2}, 0)
|
|
3308
3536
|
end
|
|
3309
|
-
${
|
|
3537
|
+
${declarations}
|
|
3538
|
+
${returned ? `return ${returned.value}` : ""}
|
|
3310
3539
|
`).body.statements;
|
|
3311
3540
|
program2.body.statements.push(...entryStatements);
|
|
3312
|
-
|
|
3541
|
+
let printed = write(program2);
|
|
3542
|
+
if (typeof printed !== "string") return unwritable(printed.problem);
|
|
3543
|
+
const map = mapping ? buildLineMap(program2, parseLuau2(printed), origins) : /* @__PURE__ */ new Map();
|
|
3313
3544
|
if (mapping && (map.size || several)) {
|
|
3314
3545
|
const mapStatements = [assign(
|
|
3315
3546
|
[member(identifier(G), "lines")],
|
|
@@ -3319,7 +3550,9 @@ ${returnsExports ? `return ${result2}` : ""}
|
|
|
3319
3550
|
program2.body.statements.splice(program2.body.statements.length - entryStatements.length, 0, ...mapStatements);
|
|
3320
3551
|
}
|
|
3321
3552
|
program2.body.statements.splice(program2.body.statements.length - entryStatements.length, 0, ...helpers.define);
|
|
3322
|
-
|
|
3553
|
+
printed = write(program2);
|
|
3554
|
+
if (typeof printed !== "string") return unwritable(printed.problem);
|
|
3555
|
+
const files = [{ path: layout[0].path, code: printed + "\n", modules: layout[0].modules.map((m) => m.name) }];
|
|
3323
3556
|
for (const file of layout.slice(1)) {
|
|
3324
3557
|
const fileHelpers = shared.chunk(new Set(file.modules.flatMap((m) => m.shared)));
|
|
3325
3558
|
const body = [...fileHelpers.declare];
|
|
@@ -3332,14 +3565,34 @@ ${returnsExports ? `return ${result2}` : ""}
|
|
|
3332
3565
|
}
|
|
3333
3566
|
const chunk = program([returns([functionExpression(functionBody([G], body))])]);
|
|
3334
3567
|
if (mapping) {
|
|
3335
|
-
const lines = buildLineMap(chunk, parseLuau2(
|
|
3568
|
+
const lines = buildLineMap(chunk, parseLuau2(print2(chunk, printing)), origins);
|
|
3336
3569
|
body.push(...mapRegistration(G, file, lineMapSource(lines, `${G}.lineMap`)));
|
|
3337
3570
|
}
|
|
3338
3571
|
body.push(...fileHelpers.define);
|
|
3339
|
-
|
|
3572
|
+
const code = write(chunk);
|
|
3573
|
+
if (typeof code !== "string") return unwritable(code.problem);
|
|
3574
|
+
files.push({ path: file.path, code: code + "\n", modules: file.modules.map((m) => m.name) });
|
|
3340
3575
|
}
|
|
3341
3576
|
return { code: files[0].code, files, modules: moduleNames, diagnostics };
|
|
3342
3577
|
}
|
|
3578
|
+
function entryReturn(lowerings, module, value, exports) {
|
|
3579
|
+
const syntax = [...syntaxOf(lowerings)];
|
|
3580
|
+
for (let i = lowerings.length - 1; i >= 0; i--) {
|
|
3581
|
+
const { plugin: plugin3, from, options } = lowerings[i];
|
|
3582
|
+
if (!plugin3.entryExports) continue;
|
|
3583
|
+
const answer = plugin3.entryExports({ options: options ?? {}, module, value, exports: exports(), syntax });
|
|
3584
|
+
if (!answer) continue;
|
|
3585
|
+
const statements = [...answer.statements ?? []];
|
|
3586
|
+
try {
|
|
3587
|
+
parseLuau2(`${statements.join("\n")}
|
|
3588
|
+
return ${answer.value}`);
|
|
3589
|
+
} catch (error) {
|
|
3590
|
+
return { problem: { message: `'${from}' answered entryExports with Luau that does not parse: ${error.message}` } };
|
|
3591
|
+
}
|
|
3592
|
+
return { statements, value: answer.value };
|
|
3593
|
+
}
|
|
3594
|
+
return { statements: [], value };
|
|
3595
|
+
}
|
|
3343
3596
|
function moduleTable(module) {
|
|
3344
3597
|
const { names: exported, links, stars } = module.info;
|
|
3345
3598
|
const fields = [];
|
|
@@ -3359,10 +3612,6 @@ function layoutOf(mode, entry, modules, outFile) {
|
|
|
3359
3612
|
const entryStem = outFile !== void 0 ? basename(outFile, extname(outFile)) : posix.basename(entry.name);
|
|
3360
3613
|
const others = modules.filter((m) => m !== entry);
|
|
3361
3614
|
if (mode === "single") return [{ path: `${entryStem}${extension}`, modules: [entry, ...others] }];
|
|
3362
|
-
if (mode === "modules") {
|
|
3363
|
-
const pathOf = (m) => `${m.name.split("/").map((part) => part === ".." ? "__" : part).join("/")}${extension}`;
|
|
3364
|
-
return [entry, ...others].map((m) => ({ path: pathOf(m), modules: [m] }));
|
|
3365
|
-
}
|
|
3366
3615
|
const byName = new Map(modules.map((m) => [m.name, m]));
|
|
3367
3616
|
const reach = (root) => {
|
|
3368
3617
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -3398,11 +3647,70 @@ function layoutOf(mode, entry, modules, outFile) {
|
|
|
3398
3647
|
return files;
|
|
3399
3648
|
}
|
|
3400
3649
|
function loadPath(entryPath, file, byPath) {
|
|
3401
|
-
|
|
3402
|
-
|
|
3650
|
+
return byPath ? requirePath(entryPath, file) : posix.relative(posix.dirname(entryPath), file);
|
|
3651
|
+
}
|
|
3652
|
+
function placeInFolder(path) {
|
|
3653
|
+
const parts = path.replace(/\\/g, "/").replace(/\.luau?$/, "").split("/").filter((part) => part !== "");
|
|
3654
|
+
if (parts.at(-1) === "init") parts.pop();
|
|
3655
|
+
return parts;
|
|
3656
|
+
}
|
|
3657
|
+
function pathBetween(from, to, root) {
|
|
3658
|
+
if (root !== void 0 && from[0] !== to[0]) return `${root}/${to.join("/")}`;
|
|
3659
|
+
if (to.length > from.length && from.every((part, i) => to[i] === part)) return `@self/${to.slice(from.length).join("/")}`;
|
|
3660
|
+
const base = from.slice(0, -1);
|
|
3661
|
+
let shared = 0;
|
|
3662
|
+
while (shared < base.length && shared < to.length - 1 && base[shared] === to[shared]) shared++;
|
|
3663
|
+
const up = base.length - shared;
|
|
3664
|
+
return `${up === 0 ? "./" : "../".repeat(up)}${to.slice(shared).join("/")}`;
|
|
3665
|
+
}
|
|
3666
|
+
function importSites(program2) {
|
|
3667
|
+
const sites = [];
|
|
3668
|
+
for (const statement of program2.body.statements) {
|
|
3669
|
+
if (statement.type === "ImportStatement" || statement.type === "ExportAllStatement" || statement.type === "ExportNamedStatement" && statement.source) {
|
|
3670
|
+
const source = statement.source;
|
|
3671
|
+
sites.push({ specifier: source.value, line: source.line.start, column: source.column.start });
|
|
3672
|
+
}
|
|
3673
|
+
}
|
|
3674
|
+
for (const node of importExpressions(program2)) {
|
|
3675
|
+
if (node.source.type === "StringLiteral") sites.push({ specifier: node.source.value, line: node.source.line.start, column: node.source.column.start });
|
|
3676
|
+
}
|
|
3677
|
+
return sites;
|
|
3678
|
+
}
|
|
3679
|
+
function pathKey(path) {
|
|
3680
|
+
const full = resolve2(path);
|
|
3681
|
+
return process.platform === "win32" ? full.toLowerCase() : full;
|
|
3682
|
+
}
|
|
3683
|
+
function requirePath(from, to) {
|
|
3684
|
+
const path = posix.relative(posix.dirname(from), to);
|
|
3403
3685
|
const bare = path.slice(0, path.length - posix.extname(path).length);
|
|
3404
3686
|
return bare.startsWith("../") ? bare : `./${bare}`;
|
|
3405
3687
|
}
|
|
3688
|
+
function tiluaFiles(folder) {
|
|
3689
|
+
const found = [];
|
|
3690
|
+
const walk2 = (at) => {
|
|
3691
|
+
let entries;
|
|
3692
|
+
try {
|
|
3693
|
+
entries = readdirSync(at, { withFileTypes: true });
|
|
3694
|
+
} catch {
|
|
3695
|
+
return;
|
|
3696
|
+
}
|
|
3697
|
+
for (const item of entries) {
|
|
3698
|
+
if (item.name.startsWith(".")) continue;
|
|
3699
|
+
const path = join(at, item.name);
|
|
3700
|
+
if (item.isDirectory()) {
|
|
3701
|
+
if (item.name !== "node_modules") walk2(path);
|
|
3702
|
+
} else if (item.name.endsWith(".tilua") && !item.name.endsWith(".d.tilua")) {
|
|
3703
|
+
found.push(path);
|
|
3704
|
+
}
|
|
3705
|
+
}
|
|
3706
|
+
};
|
|
3707
|
+
walk2(folder);
|
|
3708
|
+
return found.sort();
|
|
3709
|
+
}
|
|
3710
|
+
function isOutside(folder, file) {
|
|
3711
|
+
const path = relative(folder, file);
|
|
3712
|
+
return path === "" || path.startsWith("..") || isAbsolute(path);
|
|
3713
|
+
}
|
|
3406
3714
|
function mapRegistration(G, file, map) {
|
|
3407
3715
|
const extension = posix.extname(file.path);
|
|
3408
3716
|
const parts = file.path.slice(0, file.path.length - extension.length).split(/[/.]/).filter((part) => part !== "");
|
|
@@ -3434,6 +3742,7 @@ function loader(G, byPath) {
|
|
|
3434
3742
|
}
|
|
3435
3743
|
function runtime(G, options) {
|
|
3436
3744
|
const { several, mapping } = options;
|
|
3745
|
+
const perFile = options.perFile ?? false;
|
|
3437
3746
|
const files = [...options.files].map(([name, file]) => `[${luauString4(name)}] = ${luauString4(file)}`).join(", ");
|
|
3438
3747
|
return `
|
|
3439
3748
|
local ${G}
|
|
@@ -3645,32 +3954,60 @@ ${several ? `
|
|
|
3645
3954
|
return map[key]
|
|
3646
3955
|
end })
|
|
3647
3956
|
end,` : ""}
|
|
3648
|
-
records = {},${several ? `
|
|
3957
|
+
records = {},${several && !perFile ? `
|
|
3649
3958
|
-- The file each module outside this one is in, as \`load\` is handed it.
|
|
3650
3959
|
files = { ${files} },
|
|
3651
|
-
loaded = {}
|
|
3960
|
+
loaded = {},` : ""}${several && mapping ? `
|
|
3652
3961
|
-- Every file's line map: by the module, and by the file's name.
|
|
3653
3962
|
maps = {},
|
|
3654
|
-
sources = {},` : ""}
|
|
3963
|
+
sources = {},` : ""}${several && !perFile ? `
|
|
3655
3964
|
-- Another of the bundle's files: a function that adds its modules here.
|
|
3656
3965
|
load = function(file)
|
|
3657
3966
|
if ${G}.loaded[file] then
|
|
3658
3967
|
return
|
|
3659
3968
|
end
|
|
3660
3969
|
${G}.loaded[file] = true${loader(G, options.byPath)}
|
|
3970
|
+
end,` : ""}${perFile && mapping ? `
|
|
3971
|
+
-- What a file returns: its module's exports. The first file asked for
|
|
3972
|
+
-- runs under \`xpcall\`, so an error nothing caught is reported in the
|
|
3973
|
+
-- project's files; the files it requires in turn are inside that already.
|
|
3974
|
+
running = false,
|
|
3975
|
+
run = function(name)
|
|
3976
|
+
if ${G}.running then
|
|
3977
|
+
return ${G}.require(name)
|
|
3978
|
+
end
|
|
3979
|
+
${G}.running = true
|
|
3980
|
+
local ok, result = xpcall(${G}.require, ${G}.fail, name)
|
|
3981
|
+
${G}.running = false
|
|
3982
|
+
if not ok then
|
|
3983
|
+
error(result, 0)
|
|
3984
|
+
end
|
|
3985
|
+
return result
|
|
3661
3986
|
end,` : ""}${options.imports ? `
|
|
3662
3987
|
-- \`import("./x")\`: the module's exports, asked for where the code runs
|
|
3663
3988
|
-- rather than before its module does. \`require\` does the rest \u2014 and
|
|
3664
3989
|
-- loads the file the module is in, if it is not this one.
|
|
3665
|
-
import = function(name)
|
|
3666
|
-
return ${G}.require(name)
|
|
3990
|
+
import = function(name${perFile ? ", load" : ""})
|
|
3991
|
+
return ${G}.require(name${perFile ? ", load" : ""})
|
|
3667
3992
|
end,` : ""}
|
|
3668
|
-
require = function(name)
|
|
3993
|
+
require = function(name${perFile ? ", load" : ""})
|
|
3669
3994
|
local record = ${G}.records[name]
|
|
3670
3995
|
if record ~= nil then
|
|
3671
3996
|
return record.exports
|
|
3672
3997
|
end
|
|
3673
|
-
local module = ${G}.modules[name]${
|
|
3998
|
+
local module = ${G}.modules[name]${perFile ? `
|
|
3999
|
+
-- Its file has not run: requiring it adds the module, and runs it.
|
|
4000
|
+
if module == nil and load ~= nil then
|
|
4001
|
+
load()
|
|
4002
|
+
record = ${G}.records[name]
|
|
4003
|
+
if record ~= nil then
|
|
4004
|
+
return record.exports
|
|
4005
|
+
end
|
|
4006
|
+
module = ${G}.modules[name]
|
|
4007
|
+
end
|
|
4008
|
+
if module == nil then
|
|
4009
|
+
error(("Cannot find module '%s': nothing has loaded the file it is in"):format(name), 2)
|
|
4010
|
+
end` : several ? `
|
|
3674
4011
|
if module == nil then
|
|
3675
4012
|
${G}.load(${G}.files[name])
|
|
3676
4013
|
module = ${G}.modules[name]
|
|
@@ -3776,7 +4113,7 @@ var moduleAnalyses = /* @__PURE__ */ new Map();
|
|
|
3776
4113
|
function analyzeModules(modules, config) {
|
|
3777
4114
|
const out = [];
|
|
3778
4115
|
const analyses = /* @__PURE__ */ new Map();
|
|
3779
|
-
const libraries = config ? resolveTypeLibraries(config) : { files: [], lowerings: [], problems: [] };
|
|
4116
|
+
const libraries = config ? resolveTypeLibraries(config) : { files: [], lowerings: [], options: [], problems: [] };
|
|
3780
4117
|
for (const p of libraries.problems) out.push({ file: p.file, message: p.message, line: p.line ?? 1, column: p.column ?? 1, category: "config" });
|
|
3781
4118
|
const libs = libraries.files.map(parsedLibrary);
|
|
3782
4119
|
const noLib = config?.noLib ?? false;
|
|
@@ -3815,7 +4152,7 @@ function analyzeModules(modules, config) {
|
|
|
3815
4152
|
const at = d.node;
|
|
3816
4153
|
said.push({ file, message: d.message, line: at.line.start, column: at.column.start, category: "type", severity: d.severity });
|
|
3817
4154
|
}
|
|
3818
|
-
const result2 = { types, diagnostics: said };
|
|
4155
|
+
const result2 = { types, diagnostics: said, scopes };
|
|
3819
4156
|
if (partials === before) {
|
|
3820
4157
|
analyzed.set(file, result2);
|
|
3821
4158
|
const read3 = readWhile.get(file) ?? /* @__PURE__ */ new Map();
|
|
@@ -3872,7 +4209,16 @@ function analyzeModules(modules, config) {
|
|
|
3872
4209
|
analyses.set(module.file, types);
|
|
3873
4210
|
out.push(...diagnostics);
|
|
3874
4211
|
}
|
|
3875
|
-
|
|
4212
|
+
const exportsOf = (file) => {
|
|
4213
|
+
const cached = exportsCache.get(file);
|
|
4214
|
+
if (cached) return cached;
|
|
4215
|
+
const module = byFile.get(file);
|
|
4216
|
+
const { types, scopes } = analyzeModule(file, module.program);
|
|
4217
|
+
const exports = moduleExports(module.program, scopes, types, resolverFor(file));
|
|
4218
|
+
exportsCache.set(file, exports);
|
|
4219
|
+
return exports;
|
|
4220
|
+
};
|
|
4221
|
+
return { types: analyses, diagnostics: out, lowerings: [...libraries.lowerings], exportsOf };
|
|
3876
4222
|
}
|
|
3877
4223
|
function allStatements(statements) {
|
|
3878
4224
|
const out = [];
|
|
@@ -3894,7 +4240,11 @@ function allStatements(statements) {
|
|
|
3894
4240
|
export {
|
|
3895
4241
|
resolveConfig,
|
|
3896
4242
|
program,
|
|
4243
|
+
syntaxOf,
|
|
3897
4244
|
lower,
|
|
4245
|
+
printOptions,
|
|
4246
|
+
printOutput,
|
|
3898
4247
|
loadLowerings,
|
|
4248
|
+
WRITTEN_BY_TILUA,
|
|
3899
4249
|
bundle
|
|
3900
4250
|
};
|