@tilua/compiler 8.0.0 → 8.1.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 +13 -3
- package/dist/{chunk-TOP7NC3Z.js → chunk-WOBHMGGC.js} +84 -18
- package/dist/cli.cjs +88 -19
- package/dist/cli.js +5 -2
- package/dist/index.cjs +84 -18
- package/dist/index.d.cts +7 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ npx tilua src/main.tilua --out build/main.luau
|
|
|
14
14
|
|
|
15
15
|
```
|
|
16
16
|
tilua <entry> [--out <file>] [--output single|chunks|modules] [--config <tilua.config.json>]
|
|
17
|
-
[--noCheck]
|
|
17
|
+
[--noCheck] [--noLineMap]
|
|
18
18
|
```
|
|
19
19
|
|
|
20
20
|
Every module the entry imports is bundled in. Problems are reported as
|
|
@@ -296,6 +296,16 @@ With several files each has its own line map, and a position is read by the
|
|
|
296
296
|
map of the file it names — matched by the end of that file's path, since the
|
|
297
297
|
Lua running it may call it by a full path, a relative one, or an Instance's.
|
|
298
298
|
|
|
299
|
+
The map is packed — the files it names once, then three base-64 VLQ numbers a
|
|
300
|
+
line, each counted from the line before — and read out the first time a line
|
|
301
|
+
is looked up, so a program that never fails never unpacks it.
|
|
302
|
+
|
|
303
|
+
For a release nobody will debug, `"lineMap": false` in `tilua.config.json`
|
|
304
|
+
(or `--noLineMap`, or `bundle({ lineMap: false })`) leaves out the map and
|
|
305
|
+
everything that reads it: the entry runs without `xpcall`, a callback handed
|
|
306
|
+
to Roblox is passed through unwrapped, and an error names the bundle's own
|
|
307
|
+
lines, as plain Luau would.
|
|
308
|
+
|
|
299
309
|
## Modules
|
|
300
310
|
|
|
301
311
|
Roblox's `require` takes an Instance, so the bundle has its own. Each module
|
|
@@ -434,12 +444,12 @@ entry's.
|
|
|
434
444
|
<!-- compatibility:start -->
|
|
435
445
|
## Compatibility
|
|
436
446
|
|
|
437
|
-
`@tilua/compiler@8.
|
|
447
|
+
`@tilua/compiler@8.1.0` works with these tilua packages. *Released with* is the
|
|
438
448
|
version it was built and tested against.
|
|
439
449
|
|
|
440
450
|
| Package | Range | Released with | |
|
|
441
451
|
| --- | --- | --- | --- |
|
|
442
|
-
| `@tilua/parser` | `^8.
|
|
452
|
+
| `@tilua/parser` | `^8.1.0` | 8.1.0 | dependency |
|
|
443
453
|
<!-- compatibility:end -->
|
|
444
454
|
|
|
445
455
|
## Development
|
|
@@ -3101,10 +3101,33 @@ function buildLineMap(emitted, printed, origins) {
|
|
|
3101
3101
|
}
|
|
3102
3102
|
return map;
|
|
3103
3103
|
}
|
|
3104
|
-
|
|
3104
|
+
var VLQ_DIGITS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
3105
|
+
function vlq(n) {
|
|
3106
|
+
let value = n < 0 ? -n * 2 + 1 : n * 2;
|
|
3107
|
+
let out = "";
|
|
3108
|
+
do {
|
|
3109
|
+
const digit = value % 32;
|
|
3110
|
+
value = Math.floor(value / 32);
|
|
3111
|
+
out += VLQ_DIGITS[value > 0 ? digit + 32 : digit];
|
|
3112
|
+
} while (value > 0);
|
|
3113
|
+
return out;
|
|
3114
|
+
}
|
|
3115
|
+
function lineMapSource(map, unpack) {
|
|
3105
3116
|
const entries = [...map.entries()].sort((a, b) => a[0] - b[0]);
|
|
3106
|
-
const
|
|
3107
|
-
|
|
3117
|
+
const files = [];
|
|
3118
|
+
const indexes = /* @__PURE__ */ new Map();
|
|
3119
|
+
let data = "";
|
|
3120
|
+
let line = 0, file = 0, source = 0;
|
|
3121
|
+
for (const [at, origin] of entries) {
|
|
3122
|
+
const name = origin.file.replace(/\\/g, "/");
|
|
3123
|
+
if (!indexes.has(name)) indexes.set(name, files.push(name));
|
|
3124
|
+
const index2 = indexes.get(name);
|
|
3125
|
+
data += vlq(at - line) + vlq(index2 - file) + vlq(origin.line - source);
|
|
3126
|
+
line = at;
|
|
3127
|
+
file = index2;
|
|
3128
|
+
source = origin.line;
|
|
3129
|
+
}
|
|
3130
|
+
return `${unpack}({${files.map(luauString3).join(",")}},${luauString3(data)})`;
|
|
3108
3131
|
}
|
|
3109
3132
|
|
|
3110
3133
|
// src/bundle.ts
|
|
@@ -3152,6 +3175,7 @@ async function bundle(options) {
|
|
|
3152
3175
|
const origins = /* @__PURE__ */ new WeakMap();
|
|
3153
3176
|
const shared = new SharedRuntime(names);
|
|
3154
3177
|
const shaking = options.treeShaking ?? config?.treeShaking ?? false;
|
|
3178
|
+
const mapping = options.lineMap ?? config?.lineMap ?? true;
|
|
3155
3179
|
const resolveIn = (file) => (specifier) => {
|
|
3156
3180
|
const found = resolveModulePath(file, specifier, config);
|
|
3157
3181
|
return found !== void 0 && sources.has(found) ? found : void 0;
|
|
@@ -3190,8 +3214,8 @@ async function bundle(options) {
|
|
|
3190
3214
|
import: importExpression,
|
|
3191
3215
|
// One file has one line map. Several have one each, and a
|
|
3192
3216
|
// module reads the one of the file it is in.
|
|
3193
|
-
lines: mode === "single" ? `${G}.lines` : `${G}.maps[${luauString4(source.name)}]`,
|
|
3194
|
-
fail: `${G}.fail
|
|
3217
|
+
lines: !mapping ? void 0 : mode === "single" ? `${G}.lines` : `${G}.maps[${luauString4(source.name)}]`,
|
|
3218
|
+
fail: mapping ? `${G}.fail` : void 0,
|
|
3195
3219
|
arrays: `${G}.arrays`,
|
|
3196
3220
|
resolve: (specifier, dynamic) => {
|
|
3197
3221
|
const found = resolveModulePath(file, specifier, config);
|
|
@@ -3255,7 +3279,8 @@ async function bundle(options) {
|
|
|
3255
3279
|
several,
|
|
3256
3280
|
byPath,
|
|
3257
3281
|
files: elsewhere,
|
|
3258
|
-
imports: lowered.some((m) => m.dynamicImports.size > 0)
|
|
3282
|
+
imports: lowered.some((m) => m.dynamicImports.size > 0),
|
|
3283
|
+
mapping
|
|
3259
3284
|
}));
|
|
3260
3285
|
const assignment = program2.body.statements[1];
|
|
3261
3286
|
if (usesScriptArgs) {
|
|
@@ -3272,21 +3297,23 @@ async function bundle(options) {
|
|
|
3272
3297
|
program2.body.statements.unshift(...helpers.declare);
|
|
3273
3298
|
const ok = names.fresh("ok");
|
|
3274
3299
|
const result2 = names.fresh("result");
|
|
3275
|
-
const
|
|
3300
|
+
const entryName = luauString4(sources.get(entry).name);
|
|
3301
|
+
const returnsExports = modules.get(entry).info.exports;
|
|
3302
|
+
const entryStatements = parseLuau2(!mapping ? `${returnsExports ? "return " : ""}${G}.require(${entryName})` : `
|
|
3276
3303
|
local ${ok}, ${result2} = xpcall(function()
|
|
3277
|
-
return ${G}.require(${
|
|
3304
|
+
return ${G}.require(${entryName})
|
|
3278
3305
|
end, ${G}.fail)
|
|
3279
3306
|
if not ${ok} then
|
|
3280
3307
|
error(${result2}, 0)
|
|
3281
3308
|
end
|
|
3282
|
-
${
|
|
3309
|
+
${returnsExports ? `return ${result2}` : ""}
|
|
3283
3310
|
`).body.statements;
|
|
3284
3311
|
program2.body.statements.push(...entryStatements);
|
|
3285
|
-
const map = buildLineMap(program2, parseLuau2(print(program2)), origins);
|
|
3286
|
-
if (map.size || several) {
|
|
3312
|
+
const map = mapping ? buildLineMap(program2, parseLuau2(print(program2)), origins) : /* @__PURE__ */ new Map();
|
|
3313
|
+
if (mapping && (map.size || several)) {
|
|
3287
3314
|
const mapStatements = [assign(
|
|
3288
3315
|
[member(identifier(G), "lines")],
|
|
3289
|
-
[parseExpressionFromSource2(lineMapSource(map))]
|
|
3316
|
+
[parseExpressionFromSource2(lineMapSource(map, `${G}.lineMap`))]
|
|
3290
3317
|
)];
|
|
3291
3318
|
if (several) mapStatements.push(...mapRegistration(G, layout[0], `${G}.lines`));
|
|
3292
3319
|
program2.body.statements.splice(program2.body.statements.length - entryStatements.length, 0, ...mapStatements);
|
|
@@ -3304,8 +3331,11 @@ ${modules.get(entry).info.exports ? `return ${result2}` : ""}
|
|
|
3304
3331
|
));
|
|
3305
3332
|
}
|
|
3306
3333
|
const chunk = program([returns([functionExpression(functionBody([G], body))])]);
|
|
3307
|
-
|
|
3308
|
-
|
|
3334
|
+
if (mapping) {
|
|
3335
|
+
const lines = buildLineMap(chunk, parseLuau2(print(chunk)), origins);
|
|
3336
|
+
body.push(...mapRegistration(G, file, lineMapSource(lines, `${G}.lineMap`)));
|
|
3337
|
+
}
|
|
3338
|
+
body.push(...fileHelpers.define);
|
|
3309
3339
|
files.push({ path: file.path, code: print(chunk) + "\n", modules: file.modules.map((m) => m.name) });
|
|
3310
3340
|
}
|
|
3311
3341
|
return { code: files[0].code, files, modules: moduleNames, diagnostics };
|
|
@@ -3403,7 +3433,7 @@ function loader(G, byPath) {
|
|
|
3403
3433
|
require(file)(${G})`;
|
|
3404
3434
|
}
|
|
3405
3435
|
function runtime(G, options) {
|
|
3406
|
-
const { several } = options;
|
|
3436
|
+
const { several, mapping } = options;
|
|
3407
3437
|
const files = [...options.files].map(([name, file]) => `[${luauString4(name)}] = ${luauString4(file)}`).join(", ");
|
|
3408
3438
|
return `
|
|
3409
3439
|
local ${G}
|
|
@@ -3411,7 +3441,7 @@ ${G} = {
|
|
|
3411
3441
|
modules = {},
|
|
3412
3442
|
-- Every array the program made, so \`typeof\` can tell one from an object.
|
|
3413
3443
|
-- The keys are held weakly: being written down keeps no array alive.
|
|
3414
|
-
arrays = setmetatable({}, { __mode = "k" })
|
|
3444
|
+
arrays = setmetatable({}, { __mode = "k" }),${mapping ? `
|
|
3415
3445
|
-- Filled in just before the entry runs: bundle line -> { file, line }.
|
|
3416
3446
|
lines = nil,
|
|
3417
3447
|
-- What an error nothing caught says, in the project's files: the bundle's
|
|
@@ -3579,13 +3609,49 @@ ${several ? `
|
|
|
3579
3609
|
end
|
|
3580
3610
|
return mapped .. "\\n" .. table.concat(frames, "\\n")
|
|
3581
3611
|
end,
|
|
3612
|
+
-- A line map as it is written: the files it names, and base-64 VLQ
|
|
3613
|
+
-- numbers, three to a line \u2014 how far down the bundle, which file, how far
|
|
3614
|
+
-- down that file, each counted from the line before. It is read out the
|
|
3615
|
+
-- first time a line is looked up, which is when something went wrong.
|
|
3616
|
+
lineMap = function(files, data)
|
|
3617
|
+
local map = {}
|
|
3618
|
+
return setmetatable(map, { __index = function(_, key)
|
|
3619
|
+
setmetatable(map, nil)
|
|
3620
|
+
local digits = {}
|
|
3621
|
+
for i = 1, 64 do
|
|
3622
|
+
digits[("${VLQ_DIGITS}"):byte(i)] = i - 1
|
|
3623
|
+
end
|
|
3624
|
+
local at = 1
|
|
3625
|
+
local function read()
|
|
3626
|
+
local value, scale = 0, 1
|
|
3627
|
+
repeat
|
|
3628
|
+
local digit = digits[data:byte(at)]
|
|
3629
|
+
at = at + 1
|
|
3630
|
+
value = value + digit % 32 * scale
|
|
3631
|
+
scale = scale * 32
|
|
3632
|
+
until digit < 32
|
|
3633
|
+
if value % 2 == 1 then
|
|
3634
|
+
return -math.floor(value / 2)
|
|
3635
|
+
end
|
|
3636
|
+
return math.floor(value / 2)
|
|
3637
|
+
end
|
|
3638
|
+
local line, file, source = 0, 0, 0
|
|
3639
|
+
while at <= #data do
|
|
3640
|
+
line = line + read()
|
|
3641
|
+
file = file + read()
|
|
3642
|
+
source = source + read()
|
|
3643
|
+
map[line] = { files[file], source }
|
|
3644
|
+
end
|
|
3645
|
+
return map[key]
|
|
3646
|
+
end })
|
|
3647
|
+
end,` : ""}
|
|
3582
3648
|
records = {},${several ? `
|
|
3583
3649
|
-- The file each module outside this one is in, as \`load\` is handed it.
|
|
3584
3650
|
files = { ${files} },
|
|
3585
|
-
loaded = {}
|
|
3651
|
+
loaded = {},${mapping ? `
|
|
3586
3652
|
-- Every file's line map: by the module, and by the file's name.
|
|
3587
3653
|
maps = {},
|
|
3588
|
-
sources = {}
|
|
3654
|
+
sources = {},` : ""}
|
|
3589
3655
|
-- Another of the bundle's files: a function that adds its modules here.
|
|
3590
3656
|
load = function(file)
|
|
3591
3657
|
if ${G}.loaded[file] then
|
package/dist/cli.cjs
CHANGED
|
@@ -3070,10 +3070,33 @@ function buildLineMap(emitted, printed, origins) {
|
|
|
3070
3070
|
}
|
|
3071
3071
|
return map;
|
|
3072
3072
|
}
|
|
3073
|
-
|
|
3073
|
+
var VLQ_DIGITS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
3074
|
+
function vlq(n) {
|
|
3075
|
+
let value = n < 0 ? -n * 2 + 1 : n * 2;
|
|
3076
|
+
let out2 = "";
|
|
3077
|
+
do {
|
|
3078
|
+
const digit = value % 32;
|
|
3079
|
+
value = Math.floor(value / 32);
|
|
3080
|
+
out2 += VLQ_DIGITS[value > 0 ? digit + 32 : digit];
|
|
3081
|
+
} while (value > 0);
|
|
3082
|
+
return out2;
|
|
3083
|
+
}
|
|
3084
|
+
function lineMapSource(map, unpack) {
|
|
3074
3085
|
const entries = [...map.entries()].sort((a, b) => a[0] - b[0]);
|
|
3075
|
-
const
|
|
3076
|
-
|
|
3086
|
+
const files = [];
|
|
3087
|
+
const indexes = /* @__PURE__ */ new Map();
|
|
3088
|
+
let data = "";
|
|
3089
|
+
let line = 0, file = 0, source = 0;
|
|
3090
|
+
for (const [at, origin] of entries) {
|
|
3091
|
+
const name = origin.file.replace(/\\/g, "/");
|
|
3092
|
+
if (!indexes.has(name)) indexes.set(name, files.push(name));
|
|
3093
|
+
const index2 = indexes.get(name);
|
|
3094
|
+
data += vlq(at - line) + vlq(index2 - file) + vlq(origin.line - source);
|
|
3095
|
+
line = at;
|
|
3096
|
+
file = index2;
|
|
3097
|
+
source = origin.line;
|
|
3098
|
+
}
|
|
3099
|
+
return `${unpack}({${files.map(import_parser6.luauString).join(",")}},${(0, import_parser6.luauString)(data)})`;
|
|
3077
3100
|
}
|
|
3078
3101
|
|
|
3079
3102
|
// src/lowering.ts
|
|
@@ -3148,6 +3171,7 @@ async function bundle(options) {
|
|
|
3148
3171
|
const origins = /* @__PURE__ */ new WeakMap();
|
|
3149
3172
|
const shared = new SharedRuntime(names);
|
|
3150
3173
|
const shaking = options.treeShaking ?? config2?.treeShaking ?? false;
|
|
3174
|
+
const mapping = options.lineMap ?? config2?.lineMap ?? true;
|
|
3151
3175
|
const resolveIn = (file) => (specifier) => {
|
|
3152
3176
|
const found = (0, import_parser7.resolveModulePath)(file, specifier, config2);
|
|
3153
3177
|
return found !== void 0 && sources.has(found) ? found : void 0;
|
|
@@ -3186,8 +3210,8 @@ async function bundle(options) {
|
|
|
3186
3210
|
import: importExpression,
|
|
3187
3211
|
// One file has one line map. Several have one each, and a
|
|
3188
3212
|
// module reads the one of the file it is in.
|
|
3189
|
-
lines: mode === "single" ? `${G}.lines` : `${G}.maps[${(0, import_parser7.luauString)(source.name)}]`,
|
|
3190
|
-
fail: `${G}.fail
|
|
3213
|
+
lines: !mapping ? void 0 : mode === "single" ? `${G}.lines` : `${G}.maps[${(0, import_parser7.luauString)(source.name)}]`,
|
|
3214
|
+
fail: mapping ? `${G}.fail` : void 0,
|
|
3191
3215
|
arrays: `${G}.arrays`,
|
|
3192
3216
|
resolve: (specifier, dynamic) => {
|
|
3193
3217
|
const found = (0, import_parser7.resolveModulePath)(file, specifier, config2);
|
|
@@ -3251,7 +3275,8 @@ async function bundle(options) {
|
|
|
3251
3275
|
several,
|
|
3252
3276
|
byPath,
|
|
3253
3277
|
files: elsewhere,
|
|
3254
|
-
imports: lowered.some((m) => m.dynamicImports.size > 0)
|
|
3278
|
+
imports: lowered.some((m) => m.dynamicImports.size > 0),
|
|
3279
|
+
mapping
|
|
3255
3280
|
}));
|
|
3256
3281
|
const assignment = program2.body.statements[1];
|
|
3257
3282
|
if (usesScriptArgs) {
|
|
@@ -3268,21 +3293,23 @@ async function bundle(options) {
|
|
|
3268
3293
|
program2.body.statements.unshift(...helpers.declare);
|
|
3269
3294
|
const ok = names.fresh("ok");
|
|
3270
3295
|
const result2 = names.fresh("result");
|
|
3271
|
-
const
|
|
3296
|
+
const entryName = (0, import_parser7.luauString)(sources.get(entry2).name);
|
|
3297
|
+
const returnsExports = modules.get(entry2).info.exports;
|
|
3298
|
+
const entryStatements = (0, import_luau_parser2.parse)(!mapping ? `${returnsExports ? "return " : ""}${G}.require(${entryName})` : `
|
|
3272
3299
|
local ${ok}, ${result2} = xpcall(function()
|
|
3273
|
-
return ${G}.require(${
|
|
3300
|
+
return ${G}.require(${entryName})
|
|
3274
3301
|
end, ${G}.fail)
|
|
3275
3302
|
if not ${ok} then
|
|
3276
3303
|
error(${result2}, 0)
|
|
3277
3304
|
end
|
|
3278
|
-
${
|
|
3305
|
+
${returnsExports ? `return ${result2}` : ""}
|
|
3279
3306
|
`).body.statements;
|
|
3280
3307
|
program2.body.statements.push(...entryStatements);
|
|
3281
|
-
const map = buildLineMap(program2, (0, import_luau_parser2.parse)((0, import_luau_parser2.print)(program2)), origins);
|
|
3282
|
-
if (map.size || several) {
|
|
3308
|
+
const map = mapping ? buildLineMap(program2, (0, import_luau_parser2.parse)((0, import_luau_parser2.print)(program2)), origins) : /* @__PURE__ */ new Map();
|
|
3309
|
+
if (mapping && (map.size || several)) {
|
|
3283
3310
|
const mapStatements = [assign(
|
|
3284
3311
|
[member(identifier(G), "lines")],
|
|
3285
|
-
[(0, import_luau_parser2.parseExpressionFromSource)(lineMapSource(map))]
|
|
3312
|
+
[(0, import_luau_parser2.parseExpressionFromSource)(lineMapSource(map, `${G}.lineMap`))]
|
|
3286
3313
|
)];
|
|
3287
3314
|
if (several) mapStatements.push(...mapRegistration(G, layout[0], `${G}.lines`));
|
|
3288
3315
|
program2.body.statements.splice(program2.body.statements.length - entryStatements.length, 0, ...mapStatements);
|
|
@@ -3300,8 +3327,11 @@ ${modules.get(entry2).info.exports ? `return ${result2}` : ""}
|
|
|
3300
3327
|
));
|
|
3301
3328
|
}
|
|
3302
3329
|
const chunk = program([returns([functionExpression(functionBody([G], body))])]);
|
|
3303
|
-
|
|
3304
|
-
|
|
3330
|
+
if (mapping) {
|
|
3331
|
+
const lines = buildLineMap(chunk, (0, import_luau_parser2.parse)((0, import_luau_parser2.print)(chunk)), origins);
|
|
3332
|
+
body.push(...mapRegistration(G, file, lineMapSource(lines, `${G}.lineMap`)));
|
|
3333
|
+
}
|
|
3334
|
+
body.push(...fileHelpers.define);
|
|
3305
3335
|
files.push({ path: file.path, code: (0, import_luau_parser2.print)(chunk) + "\n", modules: file.modules.map((m) => m.name) });
|
|
3306
3336
|
}
|
|
3307
3337
|
return { code: files[0].code, files, modules: moduleNames, diagnostics };
|
|
@@ -3399,7 +3429,7 @@ function loader(G, byPath) {
|
|
|
3399
3429
|
require(file)(${G})`;
|
|
3400
3430
|
}
|
|
3401
3431
|
function runtime(G, options) {
|
|
3402
|
-
const { several } = options;
|
|
3432
|
+
const { several, mapping } = options;
|
|
3403
3433
|
const files = [...options.files].map(([name, file]) => `[${(0, import_parser7.luauString)(name)}] = ${(0, import_parser7.luauString)(file)}`).join(", ");
|
|
3404
3434
|
return `
|
|
3405
3435
|
local ${G}
|
|
@@ -3407,7 +3437,7 @@ ${G} = {
|
|
|
3407
3437
|
modules = {},
|
|
3408
3438
|
-- Every array the program made, so \`typeof\` can tell one from an object.
|
|
3409
3439
|
-- The keys are held weakly: being written down keeps no array alive.
|
|
3410
|
-
arrays = setmetatable({}, { __mode = "k" })
|
|
3440
|
+
arrays = setmetatable({}, { __mode = "k" }),${mapping ? `
|
|
3411
3441
|
-- Filled in just before the entry runs: bundle line -> { file, line }.
|
|
3412
3442
|
lines = nil,
|
|
3413
3443
|
-- What an error nothing caught says, in the project's files: the bundle's
|
|
@@ -3575,13 +3605,49 @@ ${several ? `
|
|
|
3575
3605
|
end
|
|
3576
3606
|
return mapped .. "\\n" .. table.concat(frames, "\\n")
|
|
3577
3607
|
end,
|
|
3608
|
+
-- A line map as it is written: the files it names, and base-64 VLQ
|
|
3609
|
+
-- numbers, three to a line \u2014 how far down the bundle, which file, how far
|
|
3610
|
+
-- down that file, each counted from the line before. It is read out the
|
|
3611
|
+
-- first time a line is looked up, which is when something went wrong.
|
|
3612
|
+
lineMap = function(files, data)
|
|
3613
|
+
local map = {}
|
|
3614
|
+
return setmetatable(map, { __index = function(_, key)
|
|
3615
|
+
setmetatable(map, nil)
|
|
3616
|
+
local digits = {}
|
|
3617
|
+
for i = 1, 64 do
|
|
3618
|
+
digits[("${VLQ_DIGITS}"):byte(i)] = i - 1
|
|
3619
|
+
end
|
|
3620
|
+
local at = 1
|
|
3621
|
+
local function read()
|
|
3622
|
+
local value, scale = 0, 1
|
|
3623
|
+
repeat
|
|
3624
|
+
local digit = digits[data:byte(at)]
|
|
3625
|
+
at = at + 1
|
|
3626
|
+
value = value + digit % 32 * scale
|
|
3627
|
+
scale = scale * 32
|
|
3628
|
+
until digit < 32
|
|
3629
|
+
if value % 2 == 1 then
|
|
3630
|
+
return -math.floor(value / 2)
|
|
3631
|
+
end
|
|
3632
|
+
return math.floor(value / 2)
|
|
3633
|
+
end
|
|
3634
|
+
local line, file, source = 0, 0, 0
|
|
3635
|
+
while at <= #data do
|
|
3636
|
+
line = line + read()
|
|
3637
|
+
file = file + read()
|
|
3638
|
+
source = source + read()
|
|
3639
|
+
map[line] = { files[file], source }
|
|
3640
|
+
end
|
|
3641
|
+
return map[key]
|
|
3642
|
+
end })
|
|
3643
|
+
end,` : ""}
|
|
3578
3644
|
records = {},${several ? `
|
|
3579
3645
|
-- The file each module outside this one is in, as \`load\` is handed it.
|
|
3580
3646
|
files = { ${files} },
|
|
3581
|
-
loaded = {}
|
|
3647
|
+
loaded = {},${mapping ? `
|
|
3582
3648
|
-- Every file's line map: by the module, and by the file's name.
|
|
3583
3649
|
maps = {},
|
|
3584
|
-
sources = {}
|
|
3650
|
+
sources = {},` : ""}
|
|
3585
3651
|
-- Another of the bundle's files: a function that adds its modules here.
|
|
3586
3652
|
load = function(file)
|
|
3587
3653
|
if ${G}.loaded[file] then
|
|
@@ -3822,18 +3888,20 @@ function allStatements(statements) {
|
|
|
3822
3888
|
}
|
|
3823
3889
|
|
|
3824
3890
|
// src/cli.ts
|
|
3825
|
-
var usage = "usage: tilua <entry> [--out <file>] [--output single|chunks|modules] [--config <tilua.config.json>] [--noCheck]";
|
|
3891
|
+
var usage = "usage: tilua <entry> [--out <file>] [--output single|chunks|modules] [--config <tilua.config.json>] [--noCheck] [--noLineMap]";
|
|
3826
3892
|
var args = process.argv.slice(2);
|
|
3827
3893
|
var entry;
|
|
3828
3894
|
var out;
|
|
3829
3895
|
var config;
|
|
3830
3896
|
var typeCheck = true;
|
|
3897
|
+
var lineMap;
|
|
3831
3898
|
var output;
|
|
3832
3899
|
for (let i = 0; i < args.length; i++) {
|
|
3833
3900
|
const arg = args[i];
|
|
3834
3901
|
if (arg === "--out") out = args[++i];
|
|
3835
3902
|
else if (arg === "--config") config = args[++i];
|
|
3836
3903
|
else if (arg === "--noCheck") typeCheck = false;
|
|
3904
|
+
else if (arg === "--noLineMap") lineMap = false;
|
|
3837
3905
|
else if (arg === "--target") {
|
|
3838
3906
|
console.error(`--target is gone: the output runs on Lua 5.1 to 5.4, LuaJIT and Luau, and a library says what more its Lua has \u2014 add "luau" to the config's 'types'`);
|
|
3839
3907
|
process.exit(2);
|
|
@@ -3863,6 +3931,7 @@ async function main(from) {
|
|
|
3863
3931
|
config,
|
|
3864
3932
|
typeCheck,
|
|
3865
3933
|
output: mode,
|
|
3934
|
+
lineMap,
|
|
3866
3935
|
outFile: entryFile !== void 0 ? (0, import_node_path3.basename)(entryFile) : void 0
|
|
3867
3936
|
});
|
|
3868
3937
|
for (const d of result2.diagnostics) {
|
package/dist/cli.js
CHANGED
|
@@ -2,23 +2,25 @@
|
|
|
2
2
|
import {
|
|
3
3
|
bundle,
|
|
4
4
|
resolveConfig
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-WOBHMGGC.js";
|
|
6
6
|
|
|
7
7
|
// src/cli.ts
|
|
8
8
|
import { mkdirSync, writeFileSync } from "fs";
|
|
9
9
|
import { basename, dirname, join, relative, resolve } from "path";
|
|
10
|
-
var usage = "usage: tilua <entry> [--out <file>] [--output single|chunks|modules] [--config <tilua.config.json>] [--noCheck]";
|
|
10
|
+
var usage = "usage: tilua <entry> [--out <file>] [--output single|chunks|modules] [--config <tilua.config.json>] [--noCheck] [--noLineMap]";
|
|
11
11
|
var args = process.argv.slice(2);
|
|
12
12
|
var entry;
|
|
13
13
|
var out;
|
|
14
14
|
var config;
|
|
15
15
|
var typeCheck = true;
|
|
16
|
+
var lineMap;
|
|
16
17
|
var output;
|
|
17
18
|
for (let i = 0; i < args.length; i++) {
|
|
18
19
|
const arg = args[i];
|
|
19
20
|
if (arg === "--out") out = args[++i];
|
|
20
21
|
else if (arg === "--config") config = args[++i];
|
|
21
22
|
else if (arg === "--noCheck") typeCheck = false;
|
|
23
|
+
else if (arg === "--noLineMap") lineMap = false;
|
|
22
24
|
else if (arg === "--target") {
|
|
23
25
|
console.error(`--target is gone: the output runs on Lua 5.1 to 5.4, LuaJIT and Luau, and a library says what more its Lua has \u2014 add "luau" to the config's 'types'`);
|
|
24
26
|
process.exit(2);
|
|
@@ -48,6 +50,7 @@ async function main(from) {
|
|
|
48
50
|
config,
|
|
49
51
|
typeCheck,
|
|
50
52
|
output: mode,
|
|
53
|
+
lineMap,
|
|
51
54
|
outFile: entryFile !== void 0 ? basename(entryFile) : void 0
|
|
52
55
|
});
|
|
53
56
|
for (const d of result.diagnostics) {
|
package/dist/index.cjs
CHANGED
|
@@ -3093,10 +3093,33 @@ function buildLineMap(emitted, printed, origins) {
|
|
|
3093
3093
|
}
|
|
3094
3094
|
return map;
|
|
3095
3095
|
}
|
|
3096
|
-
|
|
3096
|
+
var VLQ_DIGITS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
3097
|
+
function vlq(n) {
|
|
3098
|
+
let value = n < 0 ? -n * 2 + 1 : n * 2;
|
|
3099
|
+
let out = "";
|
|
3100
|
+
do {
|
|
3101
|
+
const digit = value % 32;
|
|
3102
|
+
value = Math.floor(value / 32);
|
|
3103
|
+
out += VLQ_DIGITS[value > 0 ? digit + 32 : digit];
|
|
3104
|
+
} while (value > 0);
|
|
3105
|
+
return out;
|
|
3106
|
+
}
|
|
3107
|
+
function lineMapSource(map, unpack) {
|
|
3097
3108
|
const entries = [...map.entries()].sort((a, b) => a[0] - b[0]);
|
|
3098
|
-
const
|
|
3099
|
-
|
|
3109
|
+
const files = [];
|
|
3110
|
+
const indexes = /* @__PURE__ */ new Map();
|
|
3111
|
+
let data = "";
|
|
3112
|
+
let line = 0, file = 0, source = 0;
|
|
3113
|
+
for (const [at, origin] of entries) {
|
|
3114
|
+
const name = origin.file.replace(/\\/g, "/");
|
|
3115
|
+
if (!indexes.has(name)) indexes.set(name, files.push(name));
|
|
3116
|
+
const index2 = indexes.get(name);
|
|
3117
|
+
data += vlq(at - line) + vlq(index2 - file) + vlq(origin.line - source);
|
|
3118
|
+
line = at;
|
|
3119
|
+
file = index2;
|
|
3120
|
+
source = origin.line;
|
|
3121
|
+
}
|
|
3122
|
+
return `${unpack}({${files.map(import_parser6.luauString).join(",")}},${(0, import_parser6.luauString)(data)})`;
|
|
3100
3123
|
}
|
|
3101
3124
|
|
|
3102
3125
|
// src/lowering.ts
|
|
@@ -3171,6 +3194,7 @@ async function bundle(options) {
|
|
|
3171
3194
|
const origins = /* @__PURE__ */ new WeakMap();
|
|
3172
3195
|
const shared = new SharedRuntime(names);
|
|
3173
3196
|
const shaking = options.treeShaking ?? config?.treeShaking ?? false;
|
|
3197
|
+
const mapping = options.lineMap ?? config?.lineMap ?? true;
|
|
3174
3198
|
const resolveIn = (file) => (specifier) => {
|
|
3175
3199
|
const found = (0, import_parser7.resolveModulePath)(file, specifier, config);
|
|
3176
3200
|
return found !== void 0 && sources.has(found) ? found : void 0;
|
|
@@ -3209,8 +3233,8 @@ async function bundle(options) {
|
|
|
3209
3233
|
import: importExpression,
|
|
3210
3234
|
// One file has one line map. Several have one each, and a
|
|
3211
3235
|
// module reads the one of the file it is in.
|
|
3212
|
-
lines: mode === "single" ? `${G}.lines` : `${G}.maps[${(0, import_parser7.luauString)(source.name)}]`,
|
|
3213
|
-
fail: `${G}.fail
|
|
3236
|
+
lines: !mapping ? void 0 : mode === "single" ? `${G}.lines` : `${G}.maps[${(0, import_parser7.luauString)(source.name)}]`,
|
|
3237
|
+
fail: mapping ? `${G}.fail` : void 0,
|
|
3214
3238
|
arrays: `${G}.arrays`,
|
|
3215
3239
|
resolve: (specifier, dynamic) => {
|
|
3216
3240
|
const found = (0, import_parser7.resolveModulePath)(file, specifier, config);
|
|
@@ -3274,7 +3298,8 @@ async function bundle(options) {
|
|
|
3274
3298
|
several,
|
|
3275
3299
|
byPath,
|
|
3276
3300
|
files: elsewhere,
|
|
3277
|
-
imports: lowered.some((m) => m.dynamicImports.size > 0)
|
|
3301
|
+
imports: lowered.some((m) => m.dynamicImports.size > 0),
|
|
3302
|
+
mapping
|
|
3278
3303
|
}));
|
|
3279
3304
|
const assignment = program2.body.statements[1];
|
|
3280
3305
|
if (usesScriptArgs) {
|
|
@@ -3291,21 +3316,23 @@ async function bundle(options) {
|
|
|
3291
3316
|
program2.body.statements.unshift(...helpers.declare);
|
|
3292
3317
|
const ok = names.fresh("ok");
|
|
3293
3318
|
const result2 = names.fresh("result");
|
|
3294
|
-
const
|
|
3319
|
+
const entryName = (0, import_parser7.luauString)(sources.get(entry).name);
|
|
3320
|
+
const returnsExports = modules.get(entry).info.exports;
|
|
3321
|
+
const entryStatements = (0, import_luau_parser2.parse)(!mapping ? `${returnsExports ? "return " : ""}${G}.require(${entryName})` : `
|
|
3295
3322
|
local ${ok}, ${result2} = xpcall(function()
|
|
3296
|
-
return ${G}.require(${
|
|
3323
|
+
return ${G}.require(${entryName})
|
|
3297
3324
|
end, ${G}.fail)
|
|
3298
3325
|
if not ${ok} then
|
|
3299
3326
|
error(${result2}, 0)
|
|
3300
3327
|
end
|
|
3301
|
-
${
|
|
3328
|
+
${returnsExports ? `return ${result2}` : ""}
|
|
3302
3329
|
`).body.statements;
|
|
3303
3330
|
program2.body.statements.push(...entryStatements);
|
|
3304
|
-
const map = buildLineMap(program2, (0, import_luau_parser2.parse)((0, import_luau_parser2.print)(program2)), origins);
|
|
3305
|
-
if (map.size || several) {
|
|
3331
|
+
const map = mapping ? buildLineMap(program2, (0, import_luau_parser2.parse)((0, import_luau_parser2.print)(program2)), origins) : /* @__PURE__ */ new Map();
|
|
3332
|
+
if (mapping && (map.size || several)) {
|
|
3306
3333
|
const mapStatements = [assign(
|
|
3307
3334
|
[member(identifier(G), "lines")],
|
|
3308
|
-
[(0, import_luau_parser2.parseExpressionFromSource)(lineMapSource(map))]
|
|
3335
|
+
[(0, import_luau_parser2.parseExpressionFromSource)(lineMapSource(map, `${G}.lineMap`))]
|
|
3309
3336
|
)];
|
|
3310
3337
|
if (several) mapStatements.push(...mapRegistration(G, layout[0], `${G}.lines`));
|
|
3311
3338
|
program2.body.statements.splice(program2.body.statements.length - entryStatements.length, 0, ...mapStatements);
|
|
@@ -3323,8 +3350,11 @@ ${modules.get(entry).info.exports ? `return ${result2}` : ""}
|
|
|
3323
3350
|
));
|
|
3324
3351
|
}
|
|
3325
3352
|
const chunk = program([returns([functionExpression(functionBody([G], body))])]);
|
|
3326
|
-
|
|
3327
|
-
|
|
3353
|
+
if (mapping) {
|
|
3354
|
+
const lines = buildLineMap(chunk, (0, import_luau_parser2.parse)((0, import_luau_parser2.print)(chunk)), origins);
|
|
3355
|
+
body.push(...mapRegistration(G, file, lineMapSource(lines, `${G}.lineMap`)));
|
|
3356
|
+
}
|
|
3357
|
+
body.push(...fileHelpers.define);
|
|
3328
3358
|
files.push({ path: file.path, code: (0, import_luau_parser2.print)(chunk) + "\n", modules: file.modules.map((m) => m.name) });
|
|
3329
3359
|
}
|
|
3330
3360
|
return { code: files[0].code, files, modules: moduleNames, diagnostics };
|
|
@@ -3422,7 +3452,7 @@ function loader(G, byPath) {
|
|
|
3422
3452
|
require(file)(${G})`;
|
|
3423
3453
|
}
|
|
3424
3454
|
function runtime(G, options) {
|
|
3425
|
-
const { several } = options;
|
|
3455
|
+
const { several, mapping } = options;
|
|
3426
3456
|
const files = [...options.files].map(([name, file]) => `[${(0, import_parser7.luauString)(name)}] = ${(0, import_parser7.luauString)(file)}`).join(", ");
|
|
3427
3457
|
return `
|
|
3428
3458
|
local ${G}
|
|
@@ -3430,7 +3460,7 @@ ${G} = {
|
|
|
3430
3460
|
modules = {},
|
|
3431
3461
|
-- Every array the program made, so \`typeof\` can tell one from an object.
|
|
3432
3462
|
-- The keys are held weakly: being written down keeps no array alive.
|
|
3433
|
-
arrays = setmetatable({}, { __mode = "k" })
|
|
3463
|
+
arrays = setmetatable({}, { __mode = "k" }),${mapping ? `
|
|
3434
3464
|
-- Filled in just before the entry runs: bundle line -> { file, line }.
|
|
3435
3465
|
lines = nil,
|
|
3436
3466
|
-- What an error nothing caught says, in the project's files: the bundle's
|
|
@@ -3598,13 +3628,49 @@ ${several ? `
|
|
|
3598
3628
|
end
|
|
3599
3629
|
return mapped .. "\\n" .. table.concat(frames, "\\n")
|
|
3600
3630
|
end,
|
|
3631
|
+
-- A line map as it is written: the files it names, and base-64 VLQ
|
|
3632
|
+
-- numbers, three to a line \u2014 how far down the bundle, which file, how far
|
|
3633
|
+
-- down that file, each counted from the line before. It is read out the
|
|
3634
|
+
-- first time a line is looked up, which is when something went wrong.
|
|
3635
|
+
lineMap = function(files, data)
|
|
3636
|
+
local map = {}
|
|
3637
|
+
return setmetatable(map, { __index = function(_, key)
|
|
3638
|
+
setmetatable(map, nil)
|
|
3639
|
+
local digits = {}
|
|
3640
|
+
for i = 1, 64 do
|
|
3641
|
+
digits[("${VLQ_DIGITS}"):byte(i)] = i - 1
|
|
3642
|
+
end
|
|
3643
|
+
local at = 1
|
|
3644
|
+
local function read()
|
|
3645
|
+
local value, scale = 0, 1
|
|
3646
|
+
repeat
|
|
3647
|
+
local digit = digits[data:byte(at)]
|
|
3648
|
+
at = at + 1
|
|
3649
|
+
value = value + digit % 32 * scale
|
|
3650
|
+
scale = scale * 32
|
|
3651
|
+
until digit < 32
|
|
3652
|
+
if value % 2 == 1 then
|
|
3653
|
+
return -math.floor(value / 2)
|
|
3654
|
+
end
|
|
3655
|
+
return math.floor(value / 2)
|
|
3656
|
+
end
|
|
3657
|
+
local line, file, source = 0, 0, 0
|
|
3658
|
+
while at <= #data do
|
|
3659
|
+
line = line + read()
|
|
3660
|
+
file = file + read()
|
|
3661
|
+
source = source + read()
|
|
3662
|
+
map[line] = { files[file], source }
|
|
3663
|
+
end
|
|
3664
|
+
return map[key]
|
|
3665
|
+
end })
|
|
3666
|
+
end,` : ""}
|
|
3601
3667
|
records = {},${several ? `
|
|
3602
3668
|
-- The file each module outside this one is in, as \`load\` is handed it.
|
|
3603
3669
|
files = { ${files} },
|
|
3604
|
-
loaded = {}
|
|
3670
|
+
loaded = {},${mapping ? `
|
|
3605
3671
|
-- Every file's line map: by the module, and by the file's name.
|
|
3606
3672
|
maps = {},
|
|
3607
|
-
sources = {}
|
|
3673
|
+
sources = {},` : ""}
|
|
3608
3674
|
-- Another of the bundle's files: a function that adds its modules here.
|
|
3609
3675
|
load = function(file)
|
|
3610
3676
|
if ${G}.loaded[file] then
|
package/dist/index.d.cts
CHANGED
|
@@ -22,6 +22,9 @@ interface TiluaConfigJson {
|
|
|
22
22
|
noLib?: boolean;
|
|
23
23
|
/** Leave out of the bundle what the entry never reaches (`treeShake`). */
|
|
24
24
|
treeShaking?: boolean;
|
|
25
|
+
/** Write the map from the bundle's lines back to the project's, which
|
|
26
|
+
* error reports and `console` read. Default: true. */
|
|
27
|
+
lineMap?: boolean;
|
|
25
28
|
}
|
|
26
29
|
/** A config file's path, or the config itself. Relative paths — to a config
|
|
27
30
|
* file, and inside an inline config — resolve from `cwd`. */
|
|
@@ -51,6 +54,10 @@ interface BundleOptions {
|
|
|
51
54
|
/** Leave out what the entry never reaches. Overrides the config's
|
|
52
55
|
* `treeShaking`; off without either. */
|
|
53
56
|
readonly treeShaking?: boolean;
|
|
57
|
+
/** Write the map from the bundle's lines back to the project's. Overrides
|
|
58
|
+
* the config's `lineMap`; on without either. Without it an error names
|
|
59
|
+
* the bundle's lines, and the entry does not run under `xpcall`. */
|
|
60
|
+
readonly lineMap?: boolean;
|
|
54
61
|
/** What the entry's file is called: `main.luau`. The other files of
|
|
55
62
|
* `"chunks"` are named after it (`main_shop.luau`), and every file takes
|
|
56
63
|
* its extension. Default: the entry's own name, with `.luau`. */
|
package/dist/index.d.ts
CHANGED
|
@@ -22,6 +22,9 @@ interface TiluaConfigJson {
|
|
|
22
22
|
noLib?: boolean;
|
|
23
23
|
/** Leave out of the bundle what the entry never reaches (`treeShake`). */
|
|
24
24
|
treeShaking?: boolean;
|
|
25
|
+
/** Write the map from the bundle's lines back to the project's, which
|
|
26
|
+
* error reports and `console` read. Default: true. */
|
|
27
|
+
lineMap?: boolean;
|
|
25
28
|
}
|
|
26
29
|
/** A config file's path, or the config itself. Relative paths — to a config
|
|
27
30
|
* file, and inside an inline config — resolve from `cwd`. */
|
|
@@ -51,6 +54,10 @@ interface BundleOptions {
|
|
|
51
54
|
/** Leave out what the entry never reaches. Overrides the config's
|
|
52
55
|
* `treeShaking`; off without either. */
|
|
53
56
|
readonly treeShaking?: boolean;
|
|
57
|
+
/** Write the map from the bundle's lines back to the project's. Overrides
|
|
58
|
+
* the config's `lineMap`; on without either. Without it an error names
|
|
59
|
+
* the bundle's lines, and the entry does not run under `xpcall`. */
|
|
60
|
+
readonly lineMap?: boolean;
|
|
54
61
|
/** What the entry's file is called: `main.luau`. The other files of
|
|
55
62
|
* `"chunks"` are named after it (`main_shop.luau`), and every file takes
|
|
56
63
|
* its extension. Default: the entry's own name, with `.luau`. */
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tilua/compiler",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.1.0",
|
|
4
4
|
"description": "Compiles tilua to Luau: lowers the @tilua/parser AST to a luau-parser AST and prints it",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"type": "module",
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"luau-parser": "^1.0.3",
|
|
41
|
-
"@tilua/parser": "^8.
|
|
41
|
+
"@tilua/parser": "^8.1.0"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@types/node": "^22.20.2",
|