@tilua/compiler 6.1.0 → 7.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 +69 -22
- package/dist/{chunk-574KDV5W.js → chunk-NM3EVX2J.js} +566 -82
- package/dist/cli.cjs +569 -91
- package/dist/cli.js +4 -10
- package/dist/index.cjs +566 -83
- package/dist/index.d.cts +165 -115
- package/dist/index.d.ts +165 -115
- package/dist/index.js +1 -2
- package/package.json +2 -2
- package/runtime/json.luau +255 -0
package/dist/cli.cjs
CHANGED
|
@@ -44,7 +44,7 @@ var index = (object2, key) => ({ type: "IndexExpression", object: object2, index
|
|
|
44
44
|
var call = (callee, args2) => ({ type: "CallExpression", callee, arguments: args2, ...span() });
|
|
45
45
|
var methodCall = (object2, method, args2) => ({ type: "MethodCallExpression", object: object2, method: identifier(method), arguments: args2, ...span() });
|
|
46
46
|
var functionExpression = (func) => ({ type: "FunctionExpression", func, ...span() });
|
|
47
|
-
var binary = (operator, left, right) => ({ type: "BinaryExpression", operator, left, right, ...span() });
|
|
47
|
+
var binary = (operator, left, right) => ({ type: "BinaryExpression", operator, left: operator === "^" && left.type === "UnaryExpression" ? parenthesized(left) : left, right, ...span() });
|
|
48
48
|
var unary = (operator, argument) => ({ type: "UnaryExpression", operator, argument, ...span() });
|
|
49
49
|
var parenthesized = (expression) => ({ type: "ParenthesizedExpression", expression, ...span() });
|
|
50
50
|
var table = (fields) => ({ type: "TableExpression", fields, ...span() });
|
|
@@ -103,19 +103,19 @@ var Names = class _Names {
|
|
|
103
103
|
* a name shared across modules (the module table) collides with none. */
|
|
104
104
|
static from(...programs) {
|
|
105
105
|
const taken = /* @__PURE__ */ new Set(["select", "pairs", "table", "tostring", "setmetatable", "error"]);
|
|
106
|
-
const
|
|
106
|
+
const walk2 = (value) => {
|
|
107
107
|
if (!value || typeof value !== "object") return;
|
|
108
108
|
if (Array.isArray(value)) {
|
|
109
|
-
for (const item of value)
|
|
109
|
+
for (const item of value) walk2(item);
|
|
110
110
|
return;
|
|
111
111
|
}
|
|
112
112
|
const node = value;
|
|
113
113
|
if (typeof node.name === "string" && node.name) taken.add(node.name);
|
|
114
114
|
for (const [key, child] of Object.entries(value)) {
|
|
115
|
-
if (key !== "line" && key !== "column")
|
|
115
|
+
if (key !== "line" && key !== "column") walk2(child);
|
|
116
116
|
}
|
|
117
117
|
};
|
|
118
|
-
for (const program2 of programs)
|
|
118
|
+
for (const program2 of programs) walk2(program2);
|
|
119
119
|
return new _Names(taken);
|
|
120
120
|
}
|
|
121
121
|
/** A copy that goes on to take names independently — one per module, each
|
|
@@ -123,6 +123,10 @@ var Names = class _Names {
|
|
|
123
123
|
fork() {
|
|
124
124
|
return new _Names(new Set(this.taken));
|
|
125
125
|
}
|
|
126
|
+
/** `name`, chosen elsewhere, is not to be chosen again here. */
|
|
127
|
+
take(name) {
|
|
128
|
+
this.taken.add(name);
|
|
129
|
+
}
|
|
126
130
|
/** `base`, or `base2`, `base3`, ... — whichever is free first. */
|
|
127
131
|
fresh(base) {
|
|
128
132
|
let name = base;
|
|
@@ -140,6 +144,7 @@ var implemented = (source) => new Set([...source.matchAll(/function __NAME__\.(\
|
|
|
140
144
|
var array = read("array.luau");
|
|
141
145
|
var string2 = read("string.luau");
|
|
142
146
|
var object = read("object.luau");
|
|
147
|
+
var json = read("json.luau");
|
|
143
148
|
var arrayMethods = implemented(array);
|
|
144
149
|
var stringMethods = implemented(string2);
|
|
145
150
|
var objectMethods = implemented(object);
|
|
@@ -172,7 +177,7 @@ function objectKeys(type) {
|
|
|
172
177
|
return { known, open: String(open) };
|
|
173
178
|
}
|
|
174
179
|
var plugin = {
|
|
175
|
-
runtime: { array, string: string2, object },
|
|
180
|
+
runtime: { array, string: string2, object, json },
|
|
176
181
|
methodCall({ method, receiver, use }) {
|
|
177
182
|
if (isString(receiver)) {
|
|
178
183
|
return stringMethods.has(method) ? { callee: `${use("string")}.${method}` } : void 0;
|
|
@@ -261,6 +266,141 @@ var plugin2 = {
|
|
|
261
266
|
var standardLowering = { plugin: plugin2, from: "tilua (standard library)" };
|
|
262
267
|
|
|
263
268
|
// src/lower.ts
|
|
269
|
+
function syntaxOf(lowerings) {
|
|
270
|
+
return new Set((lowerings ?? []).flatMap((l) => l.plugin.syntax ?? []));
|
|
271
|
+
}
|
|
272
|
+
var SharedRuntime = class {
|
|
273
|
+
constructor(names) {
|
|
274
|
+
this.names = names;
|
|
275
|
+
}
|
|
276
|
+
names;
|
|
277
|
+
byKey = /* @__PURE__ */ new Map();
|
|
278
|
+
/** Each group of names and the statements that declare them as locals,
|
|
279
|
+
* in the order they were first defined: each after what it uses. */
|
|
280
|
+
definitions = [];
|
|
281
|
+
defined = /* @__PURE__ */ new Set();
|
|
282
|
+
/** The name the helper `key` goes by, in every module. */
|
|
283
|
+
name(key, base) {
|
|
284
|
+
let name = this.byKey.get(key);
|
|
285
|
+
if (!name) {
|
|
286
|
+
name = this.names.fresh(base);
|
|
287
|
+
this.byKey.set(key, name);
|
|
288
|
+
}
|
|
289
|
+
return name;
|
|
290
|
+
}
|
|
291
|
+
/** `statements` declare `names`. Only the first module to say so is heard:
|
|
292
|
+
* the others' are the same. */
|
|
293
|
+
define(names, statements) {
|
|
294
|
+
if (names.every((name) => this.defined.has(name))) return;
|
|
295
|
+
for (const name of names) this.defined.add(name);
|
|
296
|
+
this.definitions.push({ names, statements });
|
|
297
|
+
}
|
|
298
|
+
/** Tree shaking: leave out of each runtime table the members nothing
|
|
299
|
+
* reads. `code` is everything else the output holds — the modules —
|
|
300
|
+
* and a member is read when it, or a member read already, names it:
|
|
301
|
+
* `tilua_array.filter(xs, f)` keeps `filter`, and whatever `filter`
|
|
302
|
+
* itself calls. A table used as anything but `table.member` — handed
|
|
303
|
+
* on, walked, indexed by what only the running program knows — keeps
|
|
304
|
+
* every member. */
|
|
305
|
+
shake(code) {
|
|
306
|
+
const names = new Set(this.definitions.flatMap((group) => group.names));
|
|
307
|
+
const read3 = /* @__PURE__ */ new Map();
|
|
308
|
+
const use = (name, key) => {
|
|
309
|
+
const now = read3.get(name);
|
|
310
|
+
if (now === "all") return;
|
|
311
|
+
if (key === void 0) {
|
|
312
|
+
read3.set(name, "all");
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
read3.set(name, (now ?? /* @__PURE__ */ new Set()).add(key));
|
|
316
|
+
};
|
|
317
|
+
const isRead = (name, key) => {
|
|
318
|
+
const now = read3.get(name);
|
|
319
|
+
return now === "all" || (now?.has(key) ?? false);
|
|
320
|
+
};
|
|
321
|
+
const scan = (value) => {
|
|
322
|
+
if (!value || typeof value !== "object") return;
|
|
323
|
+
if (Array.isArray(value)) return void value.forEach(scan);
|
|
324
|
+
const node = value;
|
|
325
|
+
const object2 = node.object;
|
|
326
|
+
if (object2?.type === "Identifier" && names.has(object2.name)) {
|
|
327
|
+
if (node.type === "MemberExpression") return use(object2.name, node.property.name);
|
|
328
|
+
if (node.type === "MethodCallExpression") {
|
|
329
|
+
use(object2.name, node.method.name);
|
|
330
|
+
return scan(node.arguments);
|
|
331
|
+
}
|
|
332
|
+
if (node.type === "IndexExpression") {
|
|
333
|
+
const index2 = node.index;
|
|
334
|
+
if (index2.type === "StringLiteral") return use(object2.name, String(index2.value));
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
if (node.type === "Identifier" && names.has(node.name)) return use(node.name);
|
|
338
|
+
if (node.type === "LocalFunctionStatement") return scan(node.func);
|
|
339
|
+
for (const [key, child] of Object.entries(node)) {
|
|
340
|
+
if (key !== "line" && key !== "column") scan(child);
|
|
341
|
+
}
|
|
342
|
+
};
|
|
343
|
+
const defines = (statement, own) => {
|
|
344
|
+
if (statement.type === "FunctionDeclarationStatement") {
|
|
345
|
+
const target = statement.target;
|
|
346
|
+
if (own.includes(target.base.name) && target.path.length === 1 && !target.method) {
|
|
347
|
+
return { name: target.base.name, key: target.path[0].name, value: statement.func };
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
if (statement.type === "AssignmentStatement" && statement.targets.length === 1 && statement.values.length === 1) {
|
|
351
|
+
const target = statement.targets[0];
|
|
352
|
+
if (target.object?.type === "Identifier" && own.includes(target.object.name)) {
|
|
353
|
+
if (target.type === "MemberExpression") return { name: target.object.name, key: target.property.name, value: statement.values[0] };
|
|
354
|
+
if (target.type === "IndexExpression" && target.index?.type === "StringLiteral") {
|
|
355
|
+
return { name: target.object.name, key: String(target.index.value), value: statement.values[0] };
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
return void 0;
|
|
360
|
+
};
|
|
361
|
+
scan(code);
|
|
362
|
+
const scanned = /* @__PURE__ */ new Set();
|
|
363
|
+
let more = true;
|
|
364
|
+
while (more) {
|
|
365
|
+
more = false;
|
|
366
|
+
for (const group of this.definitions) {
|
|
367
|
+
for (const statement of group.statements) {
|
|
368
|
+
if (scanned.has(statement)) continue;
|
|
369
|
+
const definition = defines(statement, group.names);
|
|
370
|
+
if (definition && !isRead(definition.name, definition.key)) continue;
|
|
371
|
+
scanned.add(statement);
|
|
372
|
+
more = true;
|
|
373
|
+
scan(definition ? definition.value : statement);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
for (const group of this.definitions) {
|
|
378
|
+
group.statements = group.statements.filter((statement) => {
|
|
379
|
+
const definition = defines(statement, group.names);
|
|
380
|
+
return !definition || isRead(definition.name, definition.key);
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
/** Luau setting up the helpers `used` for a chunk whose code names them:
|
|
385
|
+
* `declare` goes before that code, which reads each as an upvalue, and
|
|
386
|
+
* `define` after it — before any of it runs, and after what a helper
|
|
387
|
+
* reads as it is set up (the line map). Each definition runs in a
|
|
388
|
+
* function of its own, so what it keeps to itself stays there. */
|
|
389
|
+
chunk(used) {
|
|
390
|
+
const groups = this.definitions.filter((group) => group.names.some((name) => used.has(name)));
|
|
391
|
+
const all = groups.flatMap((group) => group.names);
|
|
392
|
+
const declare = [];
|
|
393
|
+
for (let i = 0; i < all.length; i += 100) declare.push(local(all.slice(i, i + 100), []));
|
|
394
|
+
const define = groups.map((group) => assign(
|
|
395
|
+
group.names.map((name) => identifier(name)),
|
|
396
|
+
[call(parenthesized(functionExpression(functionBody([], [
|
|
397
|
+
...group.statements,
|
|
398
|
+
returns(group.names.map((name) => identifier(name)))
|
|
399
|
+
]))), [])]
|
|
400
|
+
));
|
|
401
|
+
return { declare, define };
|
|
402
|
+
}
|
|
403
|
+
};
|
|
264
404
|
function lower(program2, scopes, options = {}) {
|
|
265
405
|
const result2 = new Lowerer(program2, scopes, options).run();
|
|
266
406
|
dropUnreachable(result2.statements);
|
|
@@ -291,7 +431,7 @@ var Lowerer = class {
|
|
|
291
431
|
this.source = source;
|
|
292
432
|
this.scopes = scopes;
|
|
293
433
|
this.options = options;
|
|
294
|
-
this.
|
|
434
|
+
this.syntax = syntaxOf(options.lowerings);
|
|
295
435
|
this.names = options.names ? options.names.fork() : Names.from(source);
|
|
296
436
|
this.exportsName = this.names.fresh("exports");
|
|
297
437
|
for (const binding of scopes.bindings.values()) {
|
|
@@ -316,6 +456,11 @@ var Lowerer = class {
|
|
|
316
456
|
names;
|
|
317
457
|
diagnostics = [];
|
|
318
458
|
helpers = /* @__PURE__ */ new Map();
|
|
459
|
+
/** The shared helpers this file names. */
|
|
460
|
+
sharedUsed = /* @__PURE__ */ new Set();
|
|
461
|
+
/** While a shared helper is written: it is defined outside every module,
|
|
462
|
+
* where none of a module's own names shadows a global. */
|
|
463
|
+
rawGlobals = false;
|
|
319
464
|
/** The binding each declaration node creates. */
|
|
320
465
|
bindingByDeclaration = /* @__PURE__ */ new Map();
|
|
321
466
|
/** tilua names that are Luau keywords, and what they are called instead. */
|
|
@@ -331,8 +476,8 @@ var Lowerer = class {
|
|
|
331
476
|
tryFrames = [];
|
|
332
477
|
/** The loops being lowered in the current function, innermost last. */
|
|
333
478
|
loops = [];
|
|
334
|
-
/**
|
|
335
|
-
|
|
479
|
+
/** What the output's Lua can write beyond Lua 5.1 (`syntaxOf`). */
|
|
480
|
+
syntax;
|
|
336
481
|
/** The source line each emitted statement came from. */
|
|
337
482
|
origins = /* @__PURE__ */ new WeakMap();
|
|
338
483
|
/** The name each class written as a value is known by. */
|
|
@@ -340,15 +485,19 @@ var Lowerer = class {
|
|
|
340
485
|
run() {
|
|
341
486
|
const body = this.options.module ? this.module(this.options.module) : this.topLevel(this.source.body.statements);
|
|
342
487
|
const scriptArgs = this.usesScriptArgs && !this.options.module ? [local(["scriptArgs"], [this.array(table([{ type: "TableFieldPositional", value: vararg() }]))])] : [];
|
|
488
|
+
this.rawGlobals = this.options.shared !== void 0;
|
|
343
489
|
const helpers = this.helperDefinitions();
|
|
490
|
+
const classes = this.classRuntimeStatements();
|
|
491
|
+
this.rawGlobals = false;
|
|
344
492
|
const captured = [...this.builtins].map(([global, local2]) => local([local2], [identifier(global)]));
|
|
345
493
|
return {
|
|
346
|
-
statements: [...captured, ...helpers, ...scriptArgs, ...
|
|
494
|
+
statements: [...captured, ...helpers, ...scriptArgs, ...classes, ...body],
|
|
347
495
|
exportsName: this.exportsName,
|
|
348
496
|
module: this.info,
|
|
349
497
|
diagnostics: this.diagnostics,
|
|
350
498
|
origins: this.origins,
|
|
351
|
-
usesScriptArgs: this.usesScriptArgs
|
|
499
|
+
usesScriptArgs: this.usesScriptArgs,
|
|
500
|
+
shared: [...this.sharedUsed]
|
|
352
501
|
};
|
|
353
502
|
}
|
|
354
503
|
/** Whether the file reads `scriptArgs`, the language's own global. */
|
|
@@ -381,6 +530,7 @@ var Lowerer = class {
|
|
|
381
530
|
/** A global the generated code calls — `pairs`, `table`, ... — under a name
|
|
382
531
|
* the source cannot have shadowed. */
|
|
383
532
|
builtin(global) {
|
|
533
|
+
if (this.rawGlobals) return identifier(global);
|
|
384
534
|
let local2 = this.builtins.get(global);
|
|
385
535
|
if (!local2) {
|
|
386
536
|
const shadowed = [...this.scopes.bindings.values()].some((b) => b.name === global && b.kind !== "global");
|
|
@@ -392,16 +542,31 @@ var Lowerer = class {
|
|
|
392
542
|
}
|
|
393
543
|
/** `table.move`. Lua 5.1 has none, and gets a function that does the same. */
|
|
394
544
|
move() {
|
|
395
|
-
return this.
|
|
545
|
+
return this.helper("move");
|
|
396
546
|
}
|
|
397
547
|
helper(kind) {
|
|
398
548
|
let name = this.helpers.get(kind);
|
|
399
549
|
if (!name) {
|
|
400
|
-
name = this.
|
|
550
|
+
name = this.sharedName(`helper:${kind}`, `tilua_${kind === "array" ? "asArray" : kind}`);
|
|
401
551
|
this.helpers.set(kind, name);
|
|
402
552
|
}
|
|
403
553
|
return identifier(name);
|
|
404
554
|
}
|
|
555
|
+
/** A fresh name for a helper — in a bundle, the one every module calls
|
|
556
|
+
* that helper by. */
|
|
557
|
+
sharedName(key, base) {
|
|
558
|
+
const shared = this.options.shared;
|
|
559
|
+
if (!shared) return this.names.fresh(base);
|
|
560
|
+
const name = shared.name(key, base);
|
|
561
|
+
this.names.take(name);
|
|
562
|
+
this.sharedUsed.add(name);
|
|
563
|
+
return name;
|
|
564
|
+
}
|
|
565
|
+
/** `statements` declare `names`: in this file, or once for the bundle. */
|
|
566
|
+
define(names, statements, out2) {
|
|
567
|
+
if (this.options.shared) this.options.shared.define(names, statements);
|
|
568
|
+
else out2.push(...statements);
|
|
569
|
+
}
|
|
405
570
|
// `typeof v` tells an array from an object, which Luau cannot: both are
|
|
406
571
|
// tables. So every array the program makes — `[a, b]`, a rest parameter,
|
|
407
572
|
// what `:map` answers — is written down as one, in a table that holds its
|
|
@@ -434,7 +599,8 @@ var Lowerer = class {
|
|
|
434
599
|
const key = `${index2}:${runtime2}`;
|
|
435
600
|
let name = this.loweringNames.get(key);
|
|
436
601
|
if (!name) {
|
|
437
|
-
|
|
602
|
+
const lines = this.lowerings[index2].plugin.runtime?.[runtime2]?.includes("__LINES__") ? this.options.module?.lines : "";
|
|
603
|
+
name = this.sharedName(`lowering:${key}:${lines}`, `tilua_${runtime2.replace(/[^A-Za-z0-9_]/g, "_")}`);
|
|
438
604
|
this.loweringNames.set(key, name);
|
|
439
605
|
this.loweringUsed.push({ index: index2, runtime: runtime2, name });
|
|
440
606
|
}
|
|
@@ -634,19 +800,25 @@ var Lowerer = class {
|
|
|
634
800
|
const runtimes = this.runtimeDefinitions();
|
|
635
801
|
if (this.helpers.has("concat")) this.helper("array");
|
|
636
802
|
if (this.helpers.has("concat")) this.move();
|
|
803
|
+
const unpack = this.helpers.get("unpack");
|
|
804
|
+
if (unpack) {
|
|
805
|
+
this.define([unpack], (0, import_luau_parser.parse)(
|
|
806
|
+
`local ${unpack} = ${this.builtin("table").name}.unpack or ${this.builtin("unpack").name}`
|
|
807
|
+
).body.statements, out2);
|
|
808
|
+
}
|
|
637
809
|
const move = this.helpers.get("move");
|
|
638
810
|
if (move) {
|
|
639
|
-
|
|
640
|
-
local
|
|
811
|
+
this.define([move], (0, import_luau_parser.parse)(`
|
|
812
|
+
local ${move} = ${this.builtin("table").name}.move or function(from, first, last, at, to)
|
|
641
813
|
for i = first, last do
|
|
642
814
|
to[at + i - first] = from[i]
|
|
643
815
|
end
|
|
644
816
|
return to
|
|
645
|
-
end`).body.statements);
|
|
817
|
+
end`).body.statements, out2);
|
|
646
818
|
}
|
|
647
819
|
const each = this.helpers.get("each");
|
|
648
820
|
if (each) {
|
|
649
|
-
|
|
821
|
+
this.define([each], (0, import_luau_parser.parse)(`
|
|
650
822
|
local function ${each}(source, ...)
|
|
651
823
|
if ${this.builtin("type").name}(source) == "function" then
|
|
652
824
|
return source, ...
|
|
@@ -656,7 +828,7 @@ local function ${each}(source, ...)
|
|
|
656
828
|
return meta.__iter(source)
|
|
657
829
|
end
|
|
658
830
|
return ${this.builtin("next").name}, source
|
|
659
|
-
end`).body.statements);
|
|
831
|
+
end`).body.statements, out2);
|
|
660
832
|
}
|
|
661
833
|
const marker = this.helpers.get("array");
|
|
662
834
|
const typeOf = this.helpers.get("typeof");
|
|
@@ -664,19 +836,19 @@ end`).body.statements);
|
|
|
664
836
|
const arrays = this.arrays();
|
|
665
837
|
const own = this.helpers.get("arrays");
|
|
666
838
|
if (own) {
|
|
667
|
-
|
|
839
|
+
this.define([own], (0, import_luau_parser.parse)(`local ${own} = ${this.builtin("setmetatable").name}({}, { __mode = "k" })`).body.statements, out2);
|
|
668
840
|
}
|
|
669
841
|
if (marker) {
|
|
670
|
-
|
|
842
|
+
this.define([marker], (0, import_luau_parser.parse)(`
|
|
671
843
|
local function ${marker}(t)
|
|
672
844
|
${arrays}[t] = true
|
|
673
845
|
return t
|
|
674
|
-
end`).body.statements);
|
|
846
|
+
end`).body.statements, out2);
|
|
675
847
|
}
|
|
676
848
|
if (typeOf) {
|
|
677
|
-
|
|
849
|
+
this.define([typeOf], (0, import_luau_parser.parse)(`
|
|
678
850
|
local function ${typeOf}(value, known)
|
|
679
|
-
local name = ${this.builtin(
|
|
851
|
+
local name = (${this.builtin("typeof").name} or ${this.builtin("type").name})(value)
|
|
680
852
|
if name ~= "table" then
|
|
681
853
|
return name
|
|
682
854
|
end
|
|
@@ -693,22 +865,22 @@ local function ${typeOf}(value, known)
|
|
|
693
865
|
return "array"
|
|
694
866
|
end
|
|
695
867
|
return "object"
|
|
696
|
-
end`).body.statements);
|
|
868
|
+
end`).body.statements, out2);
|
|
697
869
|
}
|
|
698
870
|
}
|
|
699
871
|
const add = this.helpers.get("add");
|
|
700
872
|
if (add) {
|
|
701
|
-
|
|
873
|
+
this.define([add], (0, import_luau_parser.parse)(`
|
|
702
874
|
local function ${add}(a, b)
|
|
703
875
|
if ${this.builtin("type").name}(a) == "string" or ${this.builtin("type").name}(b) == "string" then
|
|
704
876
|
return ${this.builtin("tostring").name}(a) .. ${this.builtin("tostring").name}(b)
|
|
705
877
|
end
|
|
706
878
|
return a + b
|
|
707
|
-
end`).body.statements);
|
|
879
|
+
end`).body.statements, out2);
|
|
708
880
|
}
|
|
709
881
|
const instanceOf = this.helpers.get("instanceof");
|
|
710
882
|
if (instanceOf) {
|
|
711
|
-
|
|
883
|
+
this.define([instanceOf], (0, import_luau_parser.parse)(`
|
|
712
884
|
local function ${instanceOf}(value, class)
|
|
713
885
|
if ${this.builtin("type").name}(value) ~= "table" then
|
|
714
886
|
return false
|
|
@@ -721,11 +893,11 @@ local function ${instanceOf}(value, class)
|
|
|
721
893
|
current = current.ParentClass
|
|
722
894
|
end
|
|
723
895
|
return false
|
|
724
|
-
end`).body.statements);
|
|
896
|
+
end`).body.statements, out2);
|
|
725
897
|
}
|
|
726
898
|
const accessors = this.helpers.get("accessors");
|
|
727
899
|
if (accessors) {
|
|
728
|
-
|
|
900
|
+
this.define([accessors], (0, import_luau_parser.parse)(`
|
|
729
901
|
local function ${accessors}(target, getters, setters)
|
|
730
902
|
return ${this.builtin("setmetatable").name}(target, {
|
|
731
903
|
-- Read by a spread, which copies what the getters give.
|
|
@@ -749,11 +921,11 @@ local function ${accessors}(target, getters, setters)
|
|
|
749
921
|
${this.builtin("rawset").name}(self, key, value)
|
|
750
922
|
end,
|
|
751
923
|
})
|
|
752
|
-
end`).body.statements);
|
|
924
|
+
end`).body.statements, out2);
|
|
753
925
|
}
|
|
754
926
|
const assign2 = this.helpers.get("assign");
|
|
755
927
|
if (assign2) {
|
|
756
|
-
|
|
928
|
+
this.define([assign2], (0, import_luau_parser.parse)(`
|
|
757
929
|
local function ${assign2}(target, ...)
|
|
758
930
|
for i = 1, ${this.builtin("select").name}("#", ...) do
|
|
759
931
|
local source = (${this.builtin("select").name}(i, ...))
|
|
@@ -771,12 +943,12 @@ local function ${assign2}(target, ...)
|
|
|
771
943
|
end
|
|
772
944
|
end
|
|
773
945
|
return target
|
|
774
|
-
end`).body.statements);
|
|
946
|
+
end`).body.statements, out2);
|
|
775
947
|
}
|
|
776
|
-
|
|
948
|
+
for (const { names, statements } of runtimes) this.define(names, statements, out2);
|
|
777
949
|
const concat = this.helpers.get("concat");
|
|
778
950
|
if (concat) {
|
|
779
|
-
|
|
951
|
+
this.define([concat], [localFunction(concat, functionBody([], [
|
|
780
952
|
local(["result"], [this.array(table([]))]),
|
|
781
953
|
numericFor("i", number(1), selectCount(this.builtin("select")), [
|
|
782
954
|
local(["part"], [call(this.builtin("select"), [identifier("i"), vararg()])]),
|
|
@@ -789,7 +961,7 @@ end`).body.statements);
|
|
|
789
961
|
]))
|
|
790
962
|
]),
|
|
791
963
|
returns([identifier("result")])
|
|
792
|
-
], true)));
|
|
964
|
+
], true))], out2);
|
|
793
965
|
}
|
|
794
966
|
return out2;
|
|
795
967
|
}
|
|
@@ -809,7 +981,12 @@ end`).body.statements);
|
|
|
809
981
|
}
|
|
810
982
|
const lines = this.options.module?.lines ?? "nil";
|
|
811
983
|
const fail = this.options.module?.fail ?? "nil";
|
|
812
|
-
|
|
984
|
+
const group = {
|
|
985
|
+
names: [name],
|
|
986
|
+
statements: (0, import_luau_parser.parse)(source.replace(/__NAME__/g, name).replace(/__LINES__/g, lines).replace(/__FAIL__/g, fail).replace(/__ARRAYS__/g, () => this.arrays()).replace(/__ARRAY__/g, () => this.helper("array").name).replace(/__JSON__/g, () => this.loweringRuntime(0, "json"))).body.statements
|
|
987
|
+
};
|
|
988
|
+
if (index2 === 0 && runtime2 === "json") out2.unshift(group);
|
|
989
|
+
else out2.push(group);
|
|
813
990
|
}
|
|
814
991
|
return out2;
|
|
815
992
|
}
|
|
@@ -824,7 +1001,8 @@ end`).body.statements);
|
|
|
824
1001
|
* util = require("util") -- the imports
|
|
825
1002
|
* ... -- the rest, in source order */
|
|
826
1003
|
module(context) {
|
|
827
|
-
const
|
|
1004
|
+
const shaken = this.options.shaken;
|
|
1005
|
+
const statements = shaken ? this.source.body.statements.filter((s) => !shaken.removed.has(s)) : this.source.body.statements;
|
|
828
1006
|
const exportsTable = () => identifier(this.exportsName);
|
|
829
1007
|
const { names, links, stars } = this.info;
|
|
830
1008
|
const locals = [];
|
|
@@ -863,13 +1041,24 @@ end`).body.statements);
|
|
|
863
1041
|
};
|
|
864
1042
|
for (const statement of statements) {
|
|
865
1043
|
if (statement.type !== "ImportStatement" || statement.isTypeOnly) continue;
|
|
1044
|
+
if (!statement.defaultImport && !statement.namespaceImport && !statement.specifiers.length) {
|
|
1045
|
+
const key2 = resolve4(statement.source);
|
|
1046
|
+
if (key2 !== void 0) load(key2);
|
|
1047
|
+
continue;
|
|
1048
|
+
}
|
|
866
1049
|
const specifiers = [
|
|
867
1050
|
...statement.defaultImport ? [{ local: statement.defaultImport, imported: "default" }] : [],
|
|
868
1051
|
...statement.namespaceImport ? [{ local: statement.namespaceImport, imported: void 0 }] : [],
|
|
869
1052
|
...statement.specifiers.map((s) => ({ local: s.local, imported: s.imported.name }))
|
|
870
1053
|
];
|
|
871
|
-
const used = specifiers.filter((s) => (this.bindingByDeclaration.get(s.local)?.references
|
|
872
|
-
if (!used.length)
|
|
1054
|
+
const used = specifiers.filter((s) => (this.bindingByDeclaration.get(s.local)?.references ?? []).some((reference) => !shaken?.dead.has(reference)));
|
|
1055
|
+
if (!used.length) {
|
|
1056
|
+
if (shaken?.runs(statement.source.value)) {
|
|
1057
|
+
const key2 = resolve4(statement.source);
|
|
1058
|
+
if (key2 !== void 0) load(key2);
|
|
1059
|
+
}
|
|
1060
|
+
continue;
|
|
1061
|
+
}
|
|
873
1062
|
const key = resolve4(statement.source);
|
|
874
1063
|
if (key === void 0) continue;
|
|
875
1064
|
const local2 = moduleLocal(key);
|
|
@@ -911,6 +1100,7 @@ end`).body.statements);
|
|
|
911
1100
|
break;
|
|
912
1101
|
}
|
|
913
1102
|
case "ExportAllStatement": {
|
|
1103
|
+
if (shaken && !shaken.needed(statement.source.value)) break;
|
|
914
1104
|
const key = resolve4(statement.source);
|
|
915
1105
|
if (key === void 0) break;
|
|
916
1106
|
load(key);
|
|
@@ -1185,7 +1375,7 @@ end`).body.statements);
|
|
|
1185
1375
|
case "VariableDeclaration":
|
|
1186
1376
|
return this.variableDeclaration(node, "declare");
|
|
1187
1377
|
case "FunctionDeclaration":
|
|
1188
|
-
return [{ ...localFunction(this.name(node.name.name), this.functionBody(node.func)), attributes: this.
|
|
1378
|
+
return [{ ...localFunction(this.name(node.name.name), this.functionBody(node.func)), attributes: this.syntax.has("attributes") ? node.attributes : void 0 }];
|
|
1189
1379
|
case "FunctionDeclarationStatement":
|
|
1190
1380
|
return [this.functionDeclarationStatement(node)];
|
|
1191
1381
|
case "ClassDeclaration":
|
|
@@ -1197,7 +1387,7 @@ end`).body.statements);
|
|
|
1197
1387
|
const join2 = node.operator === "+=" ? this.options.types?.joins.get(node) : void 0;
|
|
1198
1388
|
if (join2 === "dynamic") return this.dynamicAddition(node);
|
|
1199
1389
|
const operator = join2 === "concat" ? "..=" : node.operator;
|
|
1200
|
-
if (this.
|
|
1390
|
+
if (!this.syntax.has("compoundAssignment")) return this.compoundAssignment51(node, operator);
|
|
1201
1391
|
return [{
|
|
1202
1392
|
type: "CompoundAssignmentStatement",
|
|
1203
1393
|
operator,
|
|
@@ -1235,10 +1425,10 @@ end`).body.statements);
|
|
|
1235
1425
|
case "RepeatStatement": {
|
|
1236
1426
|
const body = this.block(node.body);
|
|
1237
1427
|
const condition = this.expression(node.condition);
|
|
1238
|
-
if (this.
|
|
1428
|
+
if (!this.syntax.has("continue") && hasOwnJump(body.statements, "ContinueStatement")) {
|
|
1239
1429
|
const hidden = declaredNames(body.statements).filter((name) => mentions(condition, name));
|
|
1240
1430
|
if (hidden.length) {
|
|
1241
|
-
this.report(node, `'continue' in a 'repeat' whose 'until' reads ${hidden.map((n) => `'${n}'`).join(", ")} cannot be compiled
|
|
1431
|
+
this.report(node, `'continue' in a 'repeat' whose 'until' reads ${hidden.map((n) => `'${n}'`).join(", ")} cannot be compiled to Lua, which has no 'continue' to lower it to. Move what the condition reads out of the loop body, or use a 'while' loop \u2014 or load a library whose Lua has 'continue' ("luau").`);
|
|
1242
1432
|
}
|
|
1243
1433
|
}
|
|
1244
1434
|
return [{ type: "RepeatStatement", body: this.loopBody51(body), condition, ...spanOf(node) }];
|
|
@@ -1279,8 +1469,8 @@ end`).body.statements);
|
|
|
1279
1469
|
let source = this.expression(node.iterator);
|
|
1280
1470
|
if (form.viaIter) source = methodCall(source, "__iter", []);
|
|
1281
1471
|
const variables = form.walks === "values" ? [this.names.fresh("_"), item] : [item];
|
|
1282
|
-
let iterators = form.walks === "iteration" ? [call(this.
|
|
1283
|
-
if (this.
|
|
1472
|
+
let iterators = form.walks === "iteration" ? [call(this.helper("unpack"), [source, number(1), number(3)])] : [source];
|
|
1473
|
+
if (!this.syntax.has("iteration") && form.walks === "values") {
|
|
1284
1474
|
const kind = form.viaIter ? void 0 : this.options.types?.typeOf.get(node.iterator)?.kind;
|
|
1285
1475
|
iterators = [call(kind === "array" || kind === "tuple" ? this.builtin("ipairs") : this.helper("each"), [source])];
|
|
1286
1476
|
}
|
|
@@ -1436,8 +1626,8 @@ end`).body.statements);
|
|
|
1436
1626
|
classHelpers;
|
|
1437
1627
|
classRuntime() {
|
|
1438
1628
|
return this.classHelpers ??= {
|
|
1439
|
-
build: this.
|
|
1440
|
-
accessors: this.
|
|
1629
|
+
build: this.sharedName("class:build", "tilua_class"),
|
|
1630
|
+
accessors: this.sharedName("class:accessors", "tilua_accessors")
|
|
1441
1631
|
};
|
|
1442
1632
|
}
|
|
1443
1633
|
/** The helpers, as Luau — emitted only in a file that declares a class.
|
|
@@ -1455,7 +1645,8 @@ end`).body.statements);
|
|
|
1455
1645
|
if (!this.classHelpers) return [];
|
|
1456
1646
|
const { build, accessors } = this.classHelpers;
|
|
1457
1647
|
const metamethods = `{ ${CLASS_METAMETHODS.map((name) => `"${name}"`).join(", ")} }`;
|
|
1458
|
-
|
|
1648
|
+
const out2 = [];
|
|
1649
|
+
this.define([build, accessors], (0, import_luau_parser.parse)(`
|
|
1459
1650
|
local function ${build}(base, name)
|
|
1460
1651
|
local class = { __getters = {}, __setters = {} }
|
|
1461
1652
|
class.__index = class
|
|
@@ -1493,7 +1684,8 @@ local function ${accessors}(class)
|
|
|
1493
1684
|
rawset(this, key, value)
|
|
1494
1685
|
end
|
|
1495
1686
|
end
|
|
1496
|
-
`).body.statements;
|
|
1687
|
+
`).body.statements, out2);
|
|
1688
|
+
return out2;
|
|
1497
1689
|
}
|
|
1498
1690
|
/** The class being lowered, so `super` knows what to name. */
|
|
1499
1691
|
classContext;
|
|
@@ -1637,7 +1829,7 @@ end
|
|
|
1637
1829
|
isMethod,
|
|
1638
1830
|
func,
|
|
1639
1831
|
// `@native` and the like are Luau's.
|
|
1640
|
-
attributes: this.
|
|
1832
|
+
attributes: this.syntax.has("attributes") ? node.attributes : void 0,
|
|
1641
1833
|
...spanOf(node)
|
|
1642
1834
|
};
|
|
1643
1835
|
}
|
|
@@ -1877,7 +2069,7 @@ end
|
|
|
1877
2069
|
if (join2 === "concat") return binary("..", left, right);
|
|
1878
2070
|
if (join2 === "dynamic") return call(this.helper("add"), [this.keptToOne(left), this.keptToOne(right)]);
|
|
1879
2071
|
}
|
|
1880
|
-
if (this.
|
|
2072
|
+
if (!this.syntax.has("floorDivision") && node.operator === "//") return this.floorDivide(left, right);
|
|
1881
2073
|
return binary(node.operator, left, right);
|
|
1882
2074
|
}
|
|
1883
2075
|
case "UnaryExpression":
|
|
@@ -1911,7 +2103,7 @@ end
|
|
|
1911
2103
|
case "AsConstExpression":
|
|
1912
2104
|
return this.expression(node.expression);
|
|
1913
2105
|
case "IfElseExpression":
|
|
1914
|
-
if (this.
|
|
2106
|
+
if (!this.syntax.has("ifExpression")) return this.ifElse51(node);
|
|
1915
2107
|
return {
|
|
1916
2108
|
type: "IfElseExpression",
|
|
1917
2109
|
clauses: node.clauses.map((c) => ({ condition: this.expression(c.condition), body: this.expression(c.body) })),
|
|
@@ -1958,7 +2150,7 @@ end
|
|
|
1958
2150
|
const last2 = list.length - 1;
|
|
1959
2151
|
return lowered.length && !many.has(list[last2]) ? [...lowered.slice(0, -1), this.keptToOne(lowered[last2])] : lowered;
|
|
1960
2152
|
}
|
|
1961
|
-
const unpack = (value) => call(this.
|
|
2153
|
+
const unpack = (value) => call(this.helper("unpack"), [value]);
|
|
1962
2154
|
const last = list[list.length - 1];
|
|
1963
2155
|
if (spreads.length === 1 && last.type === "SpreadElement") {
|
|
1964
2156
|
return [...list.slice(0, -1).map((a) => this.expression(a)), unpack(this.expression(last.argument))];
|
|
@@ -2072,7 +2264,7 @@ end
|
|
|
2072
2264
|
const segments = this.segments(chain);
|
|
2073
2265
|
const base = this.expression(chain.base);
|
|
2074
2266
|
const last = chain.links[chain.links.length - 1];
|
|
2075
|
-
if (
|
|
2267
|
+
if (this.syntax.has("ifExpression") && base.type === "Identifier" && segments.length === 1 && last.type !== "CallExpression" && last.type !== "MethodCallExpression") {
|
|
2076
2268
|
return {
|
|
2077
2269
|
type: "IfElseExpression",
|
|
2078
2270
|
clauses: [{ condition: binary("==", base, nil()), body: nil() }],
|
|
@@ -2099,7 +2291,7 @@ end
|
|
|
2099
2291
|
nullish(node) {
|
|
2100
2292
|
const left = this.keptToOne(this.expression(node.left));
|
|
2101
2293
|
const right = this.keptToOne(this.expression(node.right));
|
|
2102
|
-
if (
|
|
2294
|
+
if (this.syntax.has("ifExpression") && left.type === "Identifier") {
|
|
2103
2295
|
return {
|
|
2104
2296
|
type: "IfElseExpression",
|
|
2105
2297
|
clauses: [{ condition: binary("~=", left, nil()), body: left }],
|
|
@@ -2186,14 +2378,19 @@ end
|
|
|
2186
2378
|
let target;
|
|
2187
2379
|
if (node.target.type === "MemberExpression" || node.target.type === "IndexExpression") {
|
|
2188
2380
|
const object2 = this.expression(node.target.object);
|
|
2189
|
-
const
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
target = member(identifier(objectName), node.target.property.name);
|
|
2381
|
+
const key = node.target.type === "IndexExpression" ? node.target.index : void 0;
|
|
2382
|
+
if (object2.type === "Identifier" && (key === void 0 || key.type === "StringLiteral" || key.type === "NumberLiteral")) {
|
|
2383
|
+
target = key === void 0 ? member(object2, node.target.property.name) : index(object2, this.expression(key));
|
|
2193
2384
|
} else {
|
|
2194
|
-
const
|
|
2195
|
-
before.push(local([
|
|
2196
|
-
target
|
|
2385
|
+
const objectName = this.names.fresh("target");
|
|
2386
|
+
before.push(local([objectName], [object2]));
|
|
2387
|
+
if (node.target.type === "MemberExpression") {
|
|
2388
|
+
target = member(identifier(objectName), node.target.property.name);
|
|
2389
|
+
} else {
|
|
2390
|
+
const keyName = this.names.fresh("key");
|
|
2391
|
+
before.push(local([keyName], [this.expression(node.target.index)]));
|
|
2392
|
+
target = index(identifier(objectName), identifier(keyName));
|
|
2393
|
+
}
|
|
2197
2394
|
}
|
|
2198
2395
|
} else {
|
|
2199
2396
|
target = this.expression(node.target);
|
|
@@ -2214,7 +2411,7 @@ end
|
|
|
2214
2411
|
* done, and breaks for real there. A body with no `continue` is left
|
|
2215
2412
|
* exactly as it was. */
|
|
2216
2413
|
loopBody51(body) {
|
|
2217
|
-
if (
|
|
2414
|
+
if (this.syntax.has("continue") || !hasOwnJump(body.statements, "ContinueStatement")) return body;
|
|
2218
2415
|
const flag = hasOwnJump(body.statements, "BreakStatement") ? this.names.fresh("broke") : void 0;
|
|
2219
2416
|
const once = repeatUntil(rewriteOwnJumps(body.statements, flag), boolean(true));
|
|
2220
2417
|
if (!flag) return block([once]);
|
|
@@ -2266,7 +2463,7 @@ end
|
|
|
2266
2463
|
* underscores and `0b1010` becomes the decimal it means. A hex literal
|
|
2267
2464
|
* keeps its base — 5.1 reads those. */
|
|
2268
2465
|
numberRaw(node) {
|
|
2269
|
-
if (
|
|
2466
|
+
if (this.syntax.has("numberLiterals")) return node.raw;
|
|
2270
2467
|
if (/^0[bB]/.test(node.raw)) return String(node.value);
|
|
2271
2468
|
return node.raw.replace(/_/g, "");
|
|
2272
2469
|
}
|
|
@@ -2519,10 +2716,10 @@ function declaredNames(statements) {
|
|
|
2519
2716
|
}
|
|
2520
2717
|
function mentions(expression, name) {
|
|
2521
2718
|
let found = false;
|
|
2522
|
-
const
|
|
2719
|
+
const walk2 = (value) => {
|
|
2523
2720
|
if (found || !value || typeof value !== "object") return;
|
|
2524
2721
|
if (Array.isArray(value)) {
|
|
2525
|
-
for (const item of value)
|
|
2722
|
+
for (const item of value) walk2(item);
|
|
2526
2723
|
return;
|
|
2527
2724
|
}
|
|
2528
2725
|
const node = value;
|
|
@@ -2531,10 +2728,10 @@ function mentions(expression, name) {
|
|
|
2531
2728
|
return;
|
|
2532
2729
|
}
|
|
2533
2730
|
for (const [key, child] of Object.entries(value)) {
|
|
2534
|
-
if (key !== "line" && key !== "column")
|
|
2731
|
+
if (key !== "line" && key !== "column") walk2(child);
|
|
2535
2732
|
}
|
|
2536
2733
|
};
|
|
2537
|
-
|
|
2734
|
+
walk2(expression);
|
|
2538
2735
|
return found;
|
|
2539
2736
|
}
|
|
2540
2737
|
function allNodes(root) {
|
|
@@ -2570,6 +2767,269 @@ var CLASS_METAMETHODS = [
|
|
|
2570
2767
|
"__iter"
|
|
2571
2768
|
];
|
|
2572
2769
|
|
|
2770
|
+
// src/treeshake.ts
|
|
2771
|
+
function walk(node, visit, parent) {
|
|
2772
|
+
if (!node || typeof node !== "object") return;
|
|
2773
|
+
if (Array.isArray(node)) {
|
|
2774
|
+
for (const item of node) walk(item, visit, parent);
|
|
2775
|
+
return;
|
|
2776
|
+
}
|
|
2777
|
+
const n = node;
|
|
2778
|
+
if (typeof n.type === "string" && visit(n, parent) === false) return;
|
|
2779
|
+
for (const [key, child] of Object.entries(n)) {
|
|
2780
|
+
if (key === "line" || key === "column") continue;
|
|
2781
|
+
walk(child, visit, typeof n.type === "string" ? n : parent);
|
|
2782
|
+
}
|
|
2783
|
+
}
|
|
2784
|
+
function pure(expression) {
|
|
2785
|
+
let ok = true;
|
|
2786
|
+
walk(expression, (node) => {
|
|
2787
|
+
if (!ok) return false;
|
|
2788
|
+
switch (node.type) {
|
|
2789
|
+
case "CallExpression":
|
|
2790
|
+
case "MethodCallExpression":
|
|
2791
|
+
case "ImportExpression":
|
|
2792
|
+
case "SuperExpression":
|
|
2793
|
+
ok = false;
|
|
2794
|
+
return false;
|
|
2795
|
+
case "FunctionExpression":
|
|
2796
|
+
case "FunctionBody":
|
|
2797
|
+
case "ClassMethod":
|
|
2798
|
+
case "ClassAccessor":
|
|
2799
|
+
case "ClassConstructor":
|
|
2800
|
+
return false;
|
|
2801
|
+
case "ClassField":
|
|
2802
|
+
if (!node.isStatic) return false;
|
|
2803
|
+
}
|
|
2804
|
+
});
|
|
2805
|
+
return ok;
|
|
2806
|
+
}
|
|
2807
|
+
function declarationOf(statement) {
|
|
2808
|
+
return statement.type === "ExportStatement" ? statement.declaration : statement;
|
|
2809
|
+
}
|
|
2810
|
+
function removable(statement) {
|
|
2811
|
+
const declaration = declarationOf(statement);
|
|
2812
|
+
switch (declaration.type) {
|
|
2813
|
+
case "FunctionDeclaration":
|
|
2814
|
+
return true;
|
|
2815
|
+
case "ClassDeclaration":
|
|
2816
|
+
return pure(declaration);
|
|
2817
|
+
case "VariableDeclaration":
|
|
2818
|
+
return declaration.init === void 0 || pure(declaration.init);
|
|
2819
|
+
case "ExportDefaultStatement":
|
|
2820
|
+
return pure(declaration.declaration);
|
|
2821
|
+
default:
|
|
2822
|
+
return false;
|
|
2823
|
+
}
|
|
2824
|
+
}
|
|
2825
|
+
function structural(statement) {
|
|
2826
|
+
switch (statement.type) {
|
|
2827
|
+
case "TypeAliasStatement":
|
|
2828
|
+
case "ExportTypeAliasStatement":
|
|
2829
|
+
case "DeclareStatement":
|
|
2830
|
+
case "DeclareClassStatement":
|
|
2831
|
+
case "DeclareMetatableStatement":
|
|
2832
|
+
case "ImportStatement":
|
|
2833
|
+
case "ExportNamedStatement":
|
|
2834
|
+
case "ExportAllStatement":
|
|
2835
|
+
return true;
|
|
2836
|
+
default:
|
|
2837
|
+
return false;
|
|
2838
|
+
}
|
|
2839
|
+
}
|
|
2840
|
+
function exportedNames(statement) {
|
|
2841
|
+
switch (statement.type) {
|
|
2842
|
+
case "ExportStatement": {
|
|
2843
|
+
const declaration = statement.declaration;
|
|
2844
|
+
if (declaration.type === "FunctionDeclaration" || declaration.type === "ClassDeclaration") return [declaration.name.name];
|
|
2845
|
+
const names = [];
|
|
2846
|
+
walk(declaration.name, (node) => {
|
|
2847
|
+
if (node.type === "IdentifierPattern") names.push(node.name);
|
|
2848
|
+
});
|
|
2849
|
+
return names;
|
|
2850
|
+
}
|
|
2851
|
+
case "ExportDefaultStatement":
|
|
2852
|
+
return ["default"];
|
|
2853
|
+
default:
|
|
2854
|
+
return [];
|
|
2855
|
+
}
|
|
2856
|
+
}
|
|
2857
|
+
function factsOf(module2) {
|
|
2858
|
+
const tops = module2.program.body.statements;
|
|
2859
|
+
const byNode = /* @__PURE__ */ new Map();
|
|
2860
|
+
for (const binding of module2.scopes.bindings.values()) {
|
|
2861
|
+
if (binding.declarationNode) byNode.set(binding.declarationNode, binding.id);
|
|
2862
|
+
}
|
|
2863
|
+
const declaredBy = /* @__PURE__ */ new Map();
|
|
2864
|
+
const imported = /* @__PURE__ */ new Map();
|
|
2865
|
+
for (const statement of tops) {
|
|
2866
|
+
const declaration = declarationOf(statement);
|
|
2867
|
+
const declare = (node) => {
|
|
2868
|
+
const id = node && byNode.get(node);
|
|
2869
|
+
if (id !== void 0) declaredBy.set(id, statement);
|
|
2870
|
+
};
|
|
2871
|
+
if (declaration.type === "FunctionDeclaration" || declaration.type === "ClassDeclaration") declare(declaration.name);
|
|
2872
|
+
else if (declaration.type === "VariableDeclaration") {
|
|
2873
|
+
walk(declaration.name, (node) => {
|
|
2874
|
+
if (node.type === "IdentifierPattern") declare(node);
|
|
2875
|
+
});
|
|
2876
|
+
} else if (declaration.type === "ImportStatement" && !declaration.isTypeOnly) {
|
|
2877
|
+
const target = module2.resolve(declaration.source.value);
|
|
2878
|
+
if (target === void 0) continue;
|
|
2879
|
+
const add = (node, name) => {
|
|
2880
|
+
const id = node && byNode.get(node);
|
|
2881
|
+
if (id !== void 0) imported.set(id, { target, name });
|
|
2882
|
+
};
|
|
2883
|
+
if (declaration.defaultImport) add(declaration.defaultImport, "default");
|
|
2884
|
+
if (declaration.namespaceImport) add(declaration.namespaceImport, "*");
|
|
2885
|
+
for (const s of declaration.specifiers) add(s.local, s.imported.name);
|
|
2886
|
+
}
|
|
2887
|
+
}
|
|
2888
|
+
const parents = /* @__PURE__ */ new WeakMap();
|
|
2889
|
+
walk(module2.program.body, (node, parent) => {
|
|
2890
|
+
if (parent) parents.set(node, parent);
|
|
2891
|
+
});
|
|
2892
|
+
const sideEffects = tops.some((s) => !structural(s) && !removable(s));
|
|
2893
|
+
return { module: module2, tops, declaredBy, imported, parents, sideEffects };
|
|
2894
|
+
}
|
|
2895
|
+
function treeShake(modules, entry2) {
|
|
2896
|
+
const facts = new Map(modules.map((m) => [m.file, factsOf(m)]));
|
|
2897
|
+
const used = /* @__PURE__ */ new Map();
|
|
2898
|
+
const live = /* @__PURE__ */ new Map();
|
|
2899
|
+
const required = /* @__PURE__ */ new Set();
|
|
2900
|
+
let changed = true;
|
|
2901
|
+
const require2 = (file) => {
|
|
2902
|
+
if (required.has(file) || !facts.has(file)) return;
|
|
2903
|
+
required.add(file);
|
|
2904
|
+
changed = true;
|
|
2905
|
+
};
|
|
2906
|
+
const read3 = (file, name) => {
|
|
2907
|
+
if (!facts.has(file)) return;
|
|
2908
|
+
require2(file);
|
|
2909
|
+
const now = used.get(file);
|
|
2910
|
+
if (now === "all") return;
|
|
2911
|
+
if (name === "*") {
|
|
2912
|
+
used.set(file, "all");
|
|
2913
|
+
changed = true;
|
|
2914
|
+
return;
|
|
2915
|
+
}
|
|
2916
|
+
const names = now ?? /* @__PURE__ */ new Set();
|
|
2917
|
+
if (!names.has(name)) {
|
|
2918
|
+
names.add(name);
|
|
2919
|
+
used.set(file, names);
|
|
2920
|
+
changed = true;
|
|
2921
|
+
}
|
|
2922
|
+
};
|
|
2923
|
+
const isRead = (file, name) => {
|
|
2924
|
+
const now = used.get(file);
|
|
2925
|
+
return now === "all" || (now?.has(name) ?? false);
|
|
2926
|
+
};
|
|
2927
|
+
require2(entry2);
|
|
2928
|
+
used.set(entry2, "all");
|
|
2929
|
+
while (changed) {
|
|
2930
|
+
changed = false;
|
|
2931
|
+
for (const file of [...required]) {
|
|
2932
|
+
const f = facts.get(file);
|
|
2933
|
+
const kept = live.get(file) ?? /* @__PURE__ */ new Set();
|
|
2934
|
+
live.set(file, kept);
|
|
2935
|
+
const queue = [];
|
|
2936
|
+
const keep = (statement) => {
|
|
2937
|
+
if (!statement || kept.has(statement)) return;
|
|
2938
|
+
kept.add(statement);
|
|
2939
|
+
queue.push(statement);
|
|
2940
|
+
changed = true;
|
|
2941
|
+
};
|
|
2942
|
+
for (const statement of f.tops) {
|
|
2943
|
+
if (!structural(statement) && !removable(statement)) keep(statement);
|
|
2944
|
+
if (exportedNames(statement).some((name) => isRead(file, name))) keep(statement);
|
|
2945
|
+
const declaration = declarationOf(statement);
|
|
2946
|
+
if (declaration.type === "ImportStatement" && !declaration.isTypeOnly && !declaration.defaultImport && !declaration.namespaceImport && !declaration.specifiers.length) {
|
|
2947
|
+
const target = f.module.resolve(declaration.source.value);
|
|
2948
|
+
if (target !== void 0) require2(target);
|
|
2949
|
+
}
|
|
2950
|
+
if (declaration.type === "ExportNamedStatement" && !declaration.typeOnly) {
|
|
2951
|
+
const target = declaration.source ? f.module.resolve(declaration.source.value) : void 0;
|
|
2952
|
+
for (const s of declaration.specifiers) {
|
|
2953
|
+
if (!isRead(file, s.exported.name)) continue;
|
|
2954
|
+
if (declaration.source) {
|
|
2955
|
+
if (target !== void 0) read3(target, s.local.name);
|
|
2956
|
+
continue;
|
|
2957
|
+
}
|
|
2958
|
+
const id = f.module.scopes.bindingOf.get(s.local);
|
|
2959
|
+
const own = [...f.declaredBy].find(([bid, st]) => (id !== void 0 ? bid === id : false) || exportedLocal(st, s.local.name));
|
|
2960
|
+
if (own) keep(own[1]);
|
|
2961
|
+
const from = id !== void 0 ? f.imported.get(id) : void 0;
|
|
2962
|
+
if (from) read3(from.target, from.name);
|
|
2963
|
+
}
|
|
2964
|
+
}
|
|
2965
|
+
if (declaration.type === "ExportAllStatement") {
|
|
2966
|
+
const target = f.module.resolve(declaration.source.value);
|
|
2967
|
+
if (target === void 0) continue;
|
|
2968
|
+
const mine = used.get(file);
|
|
2969
|
+
if (mine === "all") read3(target, "*");
|
|
2970
|
+
else for (const name of mine ?? []) if (!ownExport(f, name)) read3(target, name);
|
|
2971
|
+
}
|
|
2972
|
+
}
|
|
2973
|
+
for (const statement of [...kept]) queue.push(statement);
|
|
2974
|
+
while (queue.length) {
|
|
2975
|
+
const statement = queue.pop();
|
|
2976
|
+
walk(statement, (node) => {
|
|
2977
|
+
if (node.type === "ImportExpression") {
|
|
2978
|
+
const source = node.source;
|
|
2979
|
+
const target = source?.type === "StringLiteral" ? f.module.resolve(source.value) : void 0;
|
|
2980
|
+
if (target !== void 0) read3(target, "*");
|
|
2981
|
+
return;
|
|
2982
|
+
}
|
|
2983
|
+
if (node.type !== "Identifier") return;
|
|
2984
|
+
const id = f.module.scopes.bindingOf.get(node);
|
|
2985
|
+
if (id === void 0) return;
|
|
2986
|
+
const declaring = f.declaredBy.get(id);
|
|
2987
|
+
if (declaring && declaring !== statement) keep(declaring);
|
|
2988
|
+
const from = f.imported.get(id);
|
|
2989
|
+
if (!from) return;
|
|
2990
|
+
if (from.name !== "*") return read3(from.target, from.name);
|
|
2991
|
+
const parent = f.parents.get(node);
|
|
2992
|
+
if (parent?.type === "MemberExpression" && parent.object === node) read3(from.target, parent.property.name);
|
|
2993
|
+
else read3(from.target, "*");
|
|
2994
|
+
});
|
|
2995
|
+
}
|
|
2996
|
+
for (const statement of f.tops) {
|
|
2997
|
+
if (statement.type !== "ImportStatement" || statement.isTypeOnly) continue;
|
|
2998
|
+
const target = f.module.resolve(statement.source.value);
|
|
2999
|
+
if (target !== void 0 && facts.get(target)?.sideEffects) require2(target);
|
|
3000
|
+
}
|
|
3001
|
+
}
|
|
3002
|
+
}
|
|
3003
|
+
const shaken = /* @__PURE__ */ new Map();
|
|
3004
|
+
for (const [file, f] of facts) {
|
|
3005
|
+
const kept = live.get(file) ?? /* @__PURE__ */ new Set();
|
|
3006
|
+
const removed = new Set(f.tops.filter((s) => !kept.has(s) && removable(s)));
|
|
3007
|
+
const dead = /* @__PURE__ */ new Set();
|
|
3008
|
+
for (const statement of removed) walk(statement, (node) => {
|
|
3009
|
+
if (node.type === "Identifier") dead.add(node);
|
|
3010
|
+
});
|
|
3011
|
+
shaken.set(file, { removed, dead });
|
|
3012
|
+
}
|
|
3013
|
+
return {
|
|
3014
|
+
modules: shaken,
|
|
3015
|
+
sideEffects: new Set([...facts].filter(([, f]) => f.sideEffects).map(([file]) => file)),
|
|
3016
|
+
required
|
|
3017
|
+
};
|
|
3018
|
+
}
|
|
3019
|
+
function exportedLocal(statement, name) {
|
|
3020
|
+
const declaration = declarationOf(statement);
|
|
3021
|
+
if (declaration.type === "FunctionDeclaration" || declaration.type === "ClassDeclaration") return declaration.name.name === name;
|
|
3022
|
+
if (declaration.type !== "VariableDeclaration") return false;
|
|
3023
|
+
let found = false;
|
|
3024
|
+
walk(declaration.name, (node) => {
|
|
3025
|
+
if (node.type === "IdentifierPattern" && node.name === name) found = true;
|
|
3026
|
+
});
|
|
3027
|
+
return found;
|
|
3028
|
+
}
|
|
3029
|
+
function ownExport(f, name) {
|
|
3030
|
+
return f.tops.some((statement) => exportedNames(statement).includes(name) || statement.type === "ExportNamedStatement" && statement.specifiers.some((s) => s.exported.name === name));
|
|
3031
|
+
}
|
|
3032
|
+
|
|
2573
3033
|
// src/linemap.ts
|
|
2574
3034
|
var import_parser6 = require("@tilua/parser");
|
|
2575
3035
|
function statementsOf(node) {
|
|
@@ -2660,8 +3120,8 @@ async function bundle(options) {
|
|
|
2660
3120
|
sources.set(file, { file, name: nameOf(file), text, program: program3, scopes });
|
|
2661
3121
|
const dynamic = (0, import_parser7.importExpressions)(program3).flatMap((node) => node.source.type === "StringLiteral" ? [node.source.value] : []);
|
|
2662
3122
|
for (const specifier of [...importedSpecifiers(program3), ...dynamic]) {
|
|
2663
|
-
const
|
|
2664
|
-
if (
|
|
3123
|
+
const target = (0, import_parser7.resolveModulePath)(file, specifier, config2);
|
|
3124
|
+
if (target && !target.endsWith(".d.tilua")) queue.push(target);
|
|
2665
3125
|
}
|
|
2666
3126
|
}
|
|
2667
3127
|
const analysis = analyzeModules([...sources.values()], config2);
|
|
@@ -2675,9 +3135,16 @@ async function bundle(options) {
|
|
|
2675
3135
|
const requireExpression = member(identifier(G), "require");
|
|
2676
3136
|
const importExpression = member(identifier(G), "import");
|
|
2677
3137
|
const mode = options.output ?? config2?.output ?? "single";
|
|
2678
|
-
const
|
|
3138
|
+
const byPath = syntaxOf(lowerings).has("requireByPath");
|
|
2679
3139
|
const modules = /* @__PURE__ */ new Map();
|
|
2680
3140
|
const origins = /* @__PURE__ */ new WeakMap();
|
|
3141
|
+
const shared = new SharedRuntime(names);
|
|
3142
|
+
const shaking = options.treeShaking ?? config2?.treeShaking ?? false;
|
|
3143
|
+
const resolveIn = (file) => (specifier) => {
|
|
3144
|
+
const found = (0, import_parser7.resolveModulePath)(file, specifier, config2);
|
|
3145
|
+
return found !== void 0 && sources.has(found) ? found : void 0;
|
|
3146
|
+
};
|
|
3147
|
+
const shaken = shaking ? treeShake([...sources.values()].map((s) => ({ file: s.file, program: s.program, scopes: s.scopes, resolve: resolveIn(s.file) })), entry2) : void 0;
|
|
2681
3148
|
const pending = [entry2];
|
|
2682
3149
|
while (pending.length) {
|
|
2683
3150
|
const file = pending.shift();
|
|
@@ -2690,10 +3157,21 @@ async function bundle(options) {
|
|
|
2690
3157
|
names,
|
|
2691
3158
|
types: analysis.types.get(file),
|
|
2692
3159
|
lowerings,
|
|
2693
|
-
target,
|
|
2694
3160
|
noLib: config2?.noLib,
|
|
2695
3161
|
source: source.text,
|
|
2696
3162
|
file: shown,
|
|
3163
|
+
shared,
|
|
3164
|
+
shaken: shaken && {
|
|
3165
|
+
...shaken.modules.get(file),
|
|
3166
|
+
runs: (specifier) => {
|
|
3167
|
+
const target = resolveIn(file)(specifier);
|
|
3168
|
+
return target !== void 0 && shaken.sideEffects.has(target);
|
|
3169
|
+
},
|
|
3170
|
+
needed: (specifier) => {
|
|
3171
|
+
const target = resolveIn(file)(specifier);
|
|
3172
|
+
return target !== void 0 && shaken.required.has(target);
|
|
3173
|
+
}
|
|
3174
|
+
},
|
|
2697
3175
|
module: {
|
|
2698
3176
|
name: source.name,
|
|
2699
3177
|
require: requireExpression,
|
|
@@ -2724,6 +3202,7 @@ async function bundle(options) {
|
|
|
2724
3202
|
exportsName: lowered2.exportsName,
|
|
2725
3203
|
info: lowered2.module,
|
|
2726
3204
|
usesScriptArgs: lowered2.usesScriptArgs,
|
|
3205
|
+
shared: lowered2.shared,
|
|
2727
3206
|
imports,
|
|
2728
3207
|
dynamicImports
|
|
2729
3208
|
});
|
|
@@ -2749,16 +3228,17 @@ async function bundle(options) {
|
|
|
2749
3228
|
if (diagnostics.some((d) => d.category === "syntax" || d.category === "scope" || d.category === "module")) {
|
|
2750
3229
|
return { files: [], modules: moduleNames, diagnostics };
|
|
2751
3230
|
}
|
|
3231
|
+
if (shaking) shared.shake(lowered.flatMap((m) => m.statements));
|
|
2752
3232
|
const several = mode !== "single";
|
|
2753
3233
|
const layout = layoutOf(mode, modules.get(entry2), lowered, options.outFile);
|
|
2754
3234
|
const usesScriptArgs = lowered.some((m) => m.usesScriptArgs);
|
|
2755
3235
|
const elsewhere = /* @__PURE__ */ new Map();
|
|
2756
3236
|
for (const file of layout.slice(1)) {
|
|
2757
|
-
for (const module2 of file.modules) elsewhere.set(module2.name, loadPath(layout[0].path, file.path,
|
|
3237
|
+
for (const module2 of file.modules) elsewhere.set(module2.name, loadPath(layout[0].path, file.path, byPath));
|
|
2758
3238
|
}
|
|
2759
3239
|
const program2 = (0, import_luau_parser2.parse)(runtime(G, {
|
|
2760
3240
|
several,
|
|
2761
|
-
|
|
3241
|
+
byPath,
|
|
2762
3242
|
files: elsewhere,
|
|
2763
3243
|
imports: lowered.some((m) => m.dynamicImports.size > 0)
|
|
2764
3244
|
}));
|
|
@@ -2773,6 +3253,8 @@ async function bundle(options) {
|
|
|
2773
3253
|
for (const module2 of layout[0].modules) {
|
|
2774
3254
|
modulesTable.fields.push({ type: "TableFieldComputed", key: string(module2.name), value: moduleTable(module2) });
|
|
2775
3255
|
}
|
|
3256
|
+
const helpers = shared.chunk(new Set(layout[0].modules.flatMap((m) => m.shared)));
|
|
3257
|
+
program2.body.statements.unshift(...helpers.declare);
|
|
2776
3258
|
const ok = names.fresh("ok");
|
|
2777
3259
|
const result2 = names.fresh("result");
|
|
2778
3260
|
const entryStatements = (0, import_luau_parser2.parse)(`
|
|
@@ -2794,9 +3276,11 @@ ${modules.get(entry2).info.exports ? `return ${result2}` : ""}
|
|
|
2794
3276
|
if (several) mapStatements.push(...mapRegistration(G, layout[0], `${G}.lines`));
|
|
2795
3277
|
program2.body.statements.splice(program2.body.statements.length - entryStatements.length, 0, ...mapStatements);
|
|
2796
3278
|
}
|
|
3279
|
+
program2.body.statements.splice(program2.body.statements.length - entryStatements.length, 0, ...helpers.define);
|
|
2797
3280
|
const files = [{ path: layout[0].path, code: (0, import_luau_parser2.print)(program2) + "\n", modules: layout[0].modules.map((m) => m.name) }];
|
|
2798
3281
|
for (const file of layout.slice(1)) {
|
|
2799
|
-
const
|
|
3282
|
+
const fileHelpers = shared.chunk(new Set(file.modules.flatMap((m) => m.shared)));
|
|
3283
|
+
const body = [...fileHelpers.declare];
|
|
2800
3284
|
if (file.modules.some((m) => m.usesScriptArgs)) body.push(...(0, import_luau_parser2.parse)(`local scriptArgs = ${G}.scriptArgs`).body.statements);
|
|
2801
3285
|
for (const module2 of file.modules) {
|
|
2802
3286
|
body.push(assign(
|
|
@@ -2806,7 +3290,7 @@ ${modules.get(entry2).info.exports ? `return ${result2}` : ""}
|
|
|
2806
3290
|
}
|
|
2807
3291
|
const chunk = program([returns([functionExpression(functionBody([G], body))])]);
|
|
2808
3292
|
const lines = buildLineMap(chunk, (0, import_luau_parser2.parse)((0, import_luau_parser2.print)(chunk)), origins);
|
|
2809
|
-
body.push(...mapRegistration(G, file, lineMapSource(lines)));
|
|
3293
|
+
body.push(...mapRegistration(G, file, lineMapSource(lines)), ...fileHelpers.define);
|
|
2810
3294
|
files.push({ path: file.path, code: (0, import_luau_parser2.print)(chunk) + "\n", modules: file.modules.map((m) => m.name) });
|
|
2811
3295
|
}
|
|
2812
3296
|
return { code: files[0].code, files, modules: moduleNames, diagnostics };
|
|
@@ -2868,9 +3352,9 @@ function layoutOf(mode, entry2, modules, outFile) {
|
|
|
2868
3352
|
}
|
|
2869
3353
|
return files;
|
|
2870
3354
|
}
|
|
2871
|
-
function loadPath(entryPath, file,
|
|
3355
|
+
function loadPath(entryPath, file, byPath) {
|
|
2872
3356
|
const path = import_node_path2.posix.relative(import_node_path2.posix.dirname(entryPath), file);
|
|
2873
|
-
if (
|
|
3357
|
+
if (!byPath) return path;
|
|
2874
3358
|
const bare = path.slice(0, path.length - import_node_path2.posix.extname(path).length);
|
|
2875
3359
|
return bare.startsWith("../") ? bare : `./${bare}`;
|
|
2876
3360
|
}
|
|
@@ -2883,8 +3367,8 @@ function mapRegistration(G, file, map) {
|
|
|
2883
3367
|
...file.modules.map((module2) => `${G}.maps[${(0, import_parser7.luauString)(module2.name)}] = ${G}.sources[#${G}.sources][2]`)
|
|
2884
3368
|
].join("\n")).body.statements;
|
|
2885
3369
|
}
|
|
2886
|
-
function loader(G,
|
|
2887
|
-
if (
|
|
3370
|
+
function loader(G, byPath) {
|
|
3371
|
+
if (!byPath) {
|
|
2888
3372
|
return `
|
|
2889
3373
|
-- From beside this file, wherever that is: its own path says where.
|
|
2890
3374
|
local folder = ""
|
|
@@ -3092,7 +3576,7 @@ ${several ? `
|
|
|
3092
3576
|
if ${G}.loaded[file] then
|
|
3093
3577
|
return
|
|
3094
3578
|
end
|
|
3095
|
-
${G}.loaded[file] = true${loader(G, options.
|
|
3579
|
+
${G}.loaded[file] = true${loader(G, options.byPath)}
|
|
3096
3580
|
end,` : ""}${options.imports ? `
|
|
3097
3581
|
-- \`import("./x")\`: the module's exports, asked for where the code runs
|
|
3098
3582
|
-- rather than before its module does. \`require\` does the rest \u2014 and
|
|
@@ -3327,13 +3811,12 @@ function allStatements(statements) {
|
|
|
3327
3811
|
}
|
|
3328
3812
|
|
|
3329
3813
|
// src/cli.ts
|
|
3330
|
-
var usage = "usage: tilua <entry> [--out <file>] [--output single|chunks|modules] [--config <tilua.config.json>] [--noCheck]
|
|
3814
|
+
var usage = "usage: tilua <entry> [--out <file>] [--output single|chunks|modules] [--config <tilua.config.json>] [--noCheck]";
|
|
3331
3815
|
var args = process.argv.slice(2);
|
|
3332
3816
|
var entry;
|
|
3333
3817
|
var out;
|
|
3334
3818
|
var config;
|
|
3335
3819
|
var typeCheck = true;
|
|
3336
|
-
var buildTarget;
|
|
3337
3820
|
var output;
|
|
3338
3821
|
for (let i = 0; i < args.length; i++) {
|
|
3339
3822
|
const arg = args[i];
|
|
@@ -3341,12 +3824,8 @@ for (let i = 0; i < args.length; i++) {
|
|
|
3341
3824
|
else if (arg === "--config") config = args[++i];
|
|
3342
3825
|
else if (arg === "--noCheck") typeCheck = false;
|
|
3343
3826
|
else if (arg === "--target") {
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
console.error(`--target must be 'luau' or 'lua51', not '${value}'`);
|
|
3347
|
-
process.exit(2);
|
|
3348
|
-
}
|
|
3349
|
-
buildTarget = value;
|
|
3827
|
+
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'`);
|
|
3828
|
+
process.exit(2);
|
|
3350
3829
|
} else if (arg === "--output") {
|
|
3351
3830
|
const value = args[++i];
|
|
3352
3831
|
if (value !== "single" && value !== "chunks" && value !== "modules") {
|
|
@@ -3372,7 +3851,6 @@ async function main(from) {
|
|
|
3372
3851
|
entry: from,
|
|
3373
3852
|
config,
|
|
3374
3853
|
typeCheck,
|
|
3375
|
-
target: buildTarget,
|
|
3376
3854
|
output: mode,
|
|
3377
3855
|
outFile: entryFile !== void 0 ? (0, import_node_path3.basename)(entryFile) : void 0
|
|
3378
3856
|
});
|