storm-lua-minify 0.3.0 → 0.9.1
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 +119 -41
- package/dist/aggregateSpecialization.js +406 -0
- package/dist/ast2lua.js +156 -68
- package/dist/astWalk.js +162 -0
- package/dist/callGraph.js +372 -0
- package/dist/cli.js +53 -58
- package/dist/cliOptions.js +36 -0
- package/dist/cliProgress.js +87 -0
- package/dist/config.js +73 -0
- package/dist/constantFold.js +798 -0
- package/dist/controlFlow.js +266 -0
- package/dist/functionRewrites.js +580 -0
- package/dist/generatedAst.js +108 -0
- package/dist/generatedNode.js +23 -0
- package/dist/globalRename.js +17 -4
- package/dist/interproceduralAnalysis.js +842 -0
- package/dist/interproceduralConstants.js +120 -0
- package/dist/luaString.js +157 -0
- package/dist/minifier.js +1219 -49
- package/dist/optimizerAnalysis.js +43 -0
- package/dist/optimizerDiagnostics.js +65 -0
- package/dist/optimizerFacts.js +529 -0
- package/dist/optimizerPass.js +96 -0
- package/dist/optimizerTransaction.js +56 -0
- package/dist/optimizerValueDomain.js +200 -0
- package/dist/options.js +233 -0
- package/dist/progress.js +2 -0
- package/dist/removeUnused.js +145 -0
- package/dist/renamer.js +280 -54
- package/dist/resolver.js +35 -11
- package/dist/runtimeEnvironment.js +105 -0
- package/dist/sourceMetadata.js +314 -0
- package/dist/statementDataflow.js +259 -0
- package/dist/statementScheduler.js +598 -0
- package/dist/symbolLiveness.js +92 -0
- package/dist/tableEffects.js +356 -0
- package/dist/transform.js +10 -371
- package/dist/valueFlow.js +409 -0
- package/dist/wholeProgramExports.js +646 -0
- package/dist/wholeProgramFieldRenames.js +583 -0
- package/dist/wholeProgramFields.js +672 -0
- package/dist/wholeProgramObjects.js +783 -0
- package/package.json +11 -2
- package/dist/index.js +0 -27
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.UNCHANGED = exports.PassOrchestrator = void 0;
|
|
4
|
+
const resolver_1 = require("./resolver");
|
|
5
|
+
/**
|
|
6
|
+
* AST変換と解析世代を結び付ける最小のpass orchestrator。
|
|
7
|
+
*
|
|
8
|
+
* 構造変更後の古いResolveResultやoptimizer factを後続passへ渡さないことが
|
|
9
|
+
* 第一の不変条件である。AST世代はあらゆる変更で進み、Resolve世代は束縛を
|
|
10
|
+
* 変える変更だけで進む。この区別により、安価な解析を不必要に再Resolveせず、
|
|
11
|
+
* ASTを参照するcacheだけは確実に失効させる。
|
|
12
|
+
*/
|
|
13
|
+
class PassOrchestrator {
|
|
14
|
+
chunk;
|
|
15
|
+
resolvedValue;
|
|
16
|
+
astGenerationValue = 0;
|
|
17
|
+
resolveGenerationValue = 0;
|
|
18
|
+
recordsValue = [];
|
|
19
|
+
analysisCache = new Map();
|
|
20
|
+
constructor(chunk, initialResolve) {
|
|
21
|
+
this.chunk = chunk;
|
|
22
|
+
this.resolvedValue = initialResolve;
|
|
23
|
+
}
|
|
24
|
+
get resolved() {
|
|
25
|
+
return this.resolvedValue;
|
|
26
|
+
}
|
|
27
|
+
get resolveGeneration() {
|
|
28
|
+
return this.resolveGenerationValue;
|
|
29
|
+
}
|
|
30
|
+
get astGeneration() {
|
|
31
|
+
return this.astGenerationValue;
|
|
32
|
+
}
|
|
33
|
+
get records() {
|
|
34
|
+
return this.recordsValue;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* 現在のAST世代に束縛された解析を遅延生成する。
|
|
38
|
+
*
|
|
39
|
+
* cache keyは解析種別とpolicyの組を表す安定したobjectにする。ASTを変更したpassが
|
|
40
|
+
* 一つでも走れば、Resolveの再計算要否にかかわらずcacheは破棄される。
|
|
41
|
+
*/
|
|
42
|
+
analysis(key, analyze) {
|
|
43
|
+
const cached = this.analysisCache.get(key);
|
|
44
|
+
if (cached?.generation === this.astGenerationValue) {
|
|
45
|
+
return cached.value;
|
|
46
|
+
}
|
|
47
|
+
const value = analyze(this.chunk, this.resolvedValue, this.astGenerationValue);
|
|
48
|
+
if (value.generation !== this.astGenerationValue) {
|
|
49
|
+
throw new Error("Analysis was built for a stale AST generation");
|
|
50
|
+
}
|
|
51
|
+
this.analysisCache.set(key, {
|
|
52
|
+
generation: this.astGenerationValue,
|
|
53
|
+
value,
|
|
54
|
+
});
|
|
55
|
+
return value;
|
|
56
|
+
}
|
|
57
|
+
run(name, transform) {
|
|
58
|
+
const astBefore = this.astGenerationValue;
|
|
59
|
+
const resolveBefore = this.resolveGenerationValue;
|
|
60
|
+
const result = transform(this.resolvedValue);
|
|
61
|
+
if (!result.changed && result.invalidatesResolve) {
|
|
62
|
+
throw new Error(`Pass ${name} cannot invalidate Resolve without changing the AST`);
|
|
63
|
+
}
|
|
64
|
+
if (result.changed) {
|
|
65
|
+
this.astGenerationValue++;
|
|
66
|
+
this.analysisCache.clear();
|
|
67
|
+
}
|
|
68
|
+
if (result.invalidatesResolve) {
|
|
69
|
+
this.resolvedValue = (0, resolver_1.resolveScopes)(this.chunk);
|
|
70
|
+
this.resolveGenerationValue++;
|
|
71
|
+
}
|
|
72
|
+
this.recordsValue.push({
|
|
73
|
+
name,
|
|
74
|
+
...result,
|
|
75
|
+
astGenerationBefore: astBefore,
|
|
76
|
+
astGenerationAfter: this.astGenerationValue,
|
|
77
|
+
resolveGenerationBefore: resolveBefore,
|
|
78
|
+
resolveGenerationAfter: this.resolveGenerationValue,
|
|
79
|
+
});
|
|
80
|
+
return result;
|
|
81
|
+
}
|
|
82
|
+
runUntilStable(name, transform) {
|
|
83
|
+
const results = [];
|
|
84
|
+
for (let iteration = 0;; iteration++) {
|
|
85
|
+
const result = this.run(`${name}:${String(iteration)}`, (resolved) => transform(resolved, iteration));
|
|
86
|
+
results.push(result);
|
|
87
|
+
if (!result.changed)
|
|
88
|
+
return results;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
exports.PassOrchestrator = PassOrchestrator;
|
|
93
|
+
exports.UNCHANGED = {
|
|
94
|
+
changed: false,
|
|
95
|
+
invalidatesResolve: false,
|
|
96
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.selectTransactionalMinifierVariant = selectTransactionalMinifierVariant;
|
|
4
|
+
const minifier_1 = require("./minifier");
|
|
5
|
+
function renderVariant(request, mode) {
|
|
6
|
+
// Minifier instanceを共有しないことがrollbackの不変条件。ASTだけでなく
|
|
7
|
+
// Resolve、SourceMetadata、annotation、rename cache、module予約名も分離する。
|
|
8
|
+
const output = new minifier_1.Minifier(request.entryFilePath, request.luaParseSettings, mode)
|
|
9
|
+
.parse()
|
|
10
|
+
.toStringWithSourceMap({
|
|
11
|
+
file: request.outputFile ?? "main.min.lua",
|
|
12
|
+
});
|
|
13
|
+
return {
|
|
14
|
+
code: output.code,
|
|
15
|
+
sourceMap: output.map.toString(),
|
|
16
|
+
byteLength: new TextEncoder().encode(output.code).length,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* baselineとtrialを最終Rename/Printまで同条件で評価し、厳密に短いtrialだけを選ぶ。
|
|
21
|
+
* trialは隔離されたMinifier上で動くため、失敗・同長・増加時に復元操作は不要。
|
|
22
|
+
*/
|
|
23
|
+
function selectTransactionalMinifierVariant(request) {
|
|
24
|
+
const baseline = renderVariant(request, request.baselineMode);
|
|
25
|
+
let trial;
|
|
26
|
+
try {
|
|
27
|
+
trial = renderVariant(request, request.trialMode);
|
|
28
|
+
}
|
|
29
|
+
catch (trialError) {
|
|
30
|
+
return {
|
|
31
|
+
accepted: false,
|
|
32
|
+
reason: "trial-failed",
|
|
33
|
+
selected: baseline,
|
|
34
|
+
baseline,
|
|
35
|
+
trialError,
|
|
36
|
+
byteSavings: 0,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
if (trial.byteLength >= baseline.byteLength) {
|
|
40
|
+
return {
|
|
41
|
+
accepted: false,
|
|
42
|
+
reason: "not-shorter",
|
|
43
|
+
selected: baseline,
|
|
44
|
+
baseline,
|
|
45
|
+
trial,
|
|
46
|
+
byteSavings: 0,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
accepted: true,
|
|
51
|
+
selected: trial,
|
|
52
|
+
baseline,
|
|
53
|
+
trial,
|
|
54
|
+
byteSavings: baseline.byteLength - trial.byteLength,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EMPTY_OPTIMIZER_TUPLE = exports.EMPTY_OPTIMIZER_VALUE = exports.NIL_ATOM = exports.DEFAULT_OPTIMIZER_VALUE_DOMAIN_LIMITS = void 0;
|
|
4
|
+
exports.finiteOptimizerValue = finiteOptimizerValue;
|
|
5
|
+
exports.unknownOptimizerValue = unknownOptimizerValue;
|
|
6
|
+
exports.joinOptimizerValues = joinOptimizerValues;
|
|
7
|
+
exports.finiteOptimizerTuple = finiteOptimizerTuple;
|
|
8
|
+
exports.valueAtOptimizerTupleSlot = valueAtOptimizerTupleSlot;
|
|
9
|
+
exports.joinOptimizerTuples = joinOptimizerTuples;
|
|
10
|
+
exports.DEFAULT_OPTIMIZER_VALUE_DOMAIN_LIMITS = Object.freeze({
|
|
11
|
+
maxAtoms: 16,
|
|
12
|
+
maxUnknownReasons: 8,
|
|
13
|
+
maxTuplePrefix: 16,
|
|
14
|
+
});
|
|
15
|
+
exports.NIL_ATOM = Object.freeze({ kind: "nil" });
|
|
16
|
+
exports.EMPTY_OPTIMIZER_VALUE = Object.freeze({
|
|
17
|
+
atoms: Object.freeze([]),
|
|
18
|
+
unknownReasons: Object.freeze([]),
|
|
19
|
+
});
|
|
20
|
+
exports.EMPTY_OPTIMIZER_TUPLE = Object.freeze({
|
|
21
|
+
prefix: Object.freeze([]),
|
|
22
|
+
tail: Object.freeze({ kind: "none" }),
|
|
23
|
+
});
|
|
24
|
+
function finiteOptimizerValue(atoms = [], unknownReasons = [], limits = exports.DEFAULT_OPTIMIZER_VALUE_DOMAIN_LIMITS) {
|
|
25
|
+
validateCustomLimits(limits);
|
|
26
|
+
const normalizedAtoms = uniqueSorted(atoms, atomKey);
|
|
27
|
+
const normalizedReasons = uniqueSorted(unknownReasons, (reason) => reason);
|
|
28
|
+
const atomOverflow = normalizedAtoms.length > limits.maxAtoms;
|
|
29
|
+
const reasons = atomOverflow
|
|
30
|
+
? capReasons([...normalizedReasons, "atom-cap-exceeded"], limits.maxUnknownReasons)
|
|
31
|
+
: capNormalizedReasons(normalizedReasons, limits.maxUnknownReasons);
|
|
32
|
+
return Object.freeze({
|
|
33
|
+
atoms: Object.freeze(normalizedAtoms.slice(0, limits.maxAtoms)),
|
|
34
|
+
unknownReasons: Object.freeze(reasons),
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
function unknownOptimizerValue(reason, limits = exports.DEFAULT_OPTIMIZER_VALUE_DOMAIN_LIMITS) {
|
|
38
|
+
return finiteOptimizerValue([], [reason], limits);
|
|
39
|
+
}
|
|
40
|
+
function joinOptimizerValues(values, limits = exports.DEFAULT_OPTIMIZER_VALUE_DOMAIN_LIMITS) {
|
|
41
|
+
return finiteOptimizerValue(values.flatMap((value) => value.atoms), values.flatMap((value) => value.unknownReasons), limits);
|
|
42
|
+
}
|
|
43
|
+
function finiteOptimizerTuple(prefix, tail = { kind: "none" }, limits = exports.DEFAULT_OPTIMIZER_VALUE_DOMAIN_LIMITS) {
|
|
44
|
+
validateCustomLimits(limits);
|
|
45
|
+
const normalizedPrefix = prefix
|
|
46
|
+
.slice(0, limits.maxTuplePrefix)
|
|
47
|
+
.map((value) => finiteOptimizerValue(value.atoms, value.unknownReasons, limits));
|
|
48
|
+
const normalizedTail = prefix.length > limits.maxTuplePrefix
|
|
49
|
+
? joinTupleTails([
|
|
50
|
+
tail,
|
|
51
|
+
{
|
|
52
|
+
kind: "unknown",
|
|
53
|
+
reasons: ["tuple-prefix-cap-exceeded"],
|
|
54
|
+
},
|
|
55
|
+
], limits)
|
|
56
|
+
: normalizeTail(tail, limits);
|
|
57
|
+
return Object.freeze({
|
|
58
|
+
prefix: Object.freeze(normalizedPrefix),
|
|
59
|
+
tail: normalizedTail,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
function valueAtOptimizerTupleSlot(tuple, index, limits = exports.DEFAULT_OPTIMIZER_VALUE_DOMAIN_LIMITS) {
|
|
63
|
+
if (!Number.isInteger(index) || index < 0)
|
|
64
|
+
throw new RangeError("Tuple slot index must be a non-negative integer");
|
|
65
|
+
if (index < tuple.prefix.length)
|
|
66
|
+
return tuple.prefix[index];
|
|
67
|
+
switch (tuple.tail.kind) {
|
|
68
|
+
case "none":
|
|
69
|
+
return finiteOptimizerValue([exports.NIL_ATOM], [], limits);
|
|
70
|
+
case "vararg":
|
|
71
|
+
// A vararg may contain fewer values than the requested slot.
|
|
72
|
+
return joinOptimizerValues([tuple.tail.value, finiteOptimizerValue([exports.NIL_ATOM], [], limits)], limits);
|
|
73
|
+
case "unknown":
|
|
74
|
+
return finiteOptimizerValue([], tuple.tail.reasons, limits);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function joinOptimizerTuples(tuples, limits = exports.DEFAULT_OPTIMIZER_VALUE_DOMAIN_LIMITS) {
|
|
78
|
+
validateCustomLimits(limits);
|
|
79
|
+
if (tuples.length === 0)
|
|
80
|
+
return exports.EMPTY_OPTIMIZER_TUPLE;
|
|
81
|
+
const prefixLength = Math.min(Math.max(...tuples.map((tuple) => tuple.prefix.length)), limits.maxTuplePrefix);
|
|
82
|
+
const prefix = Array.from({ length: prefixLength }, (_, index) => joinOptimizerValues(tuples.map((tuple) => valueAtOptimizerTupleSlot(tuple, index, limits)), limits));
|
|
83
|
+
const overflow = tuples.some((tuple) => tuple.prefix.length > limits.maxTuplePrefix);
|
|
84
|
+
const tail = joinTupleTails([
|
|
85
|
+
...tuples.map((tuple) => tuple.tail),
|
|
86
|
+
...(overflow
|
|
87
|
+
? [
|
|
88
|
+
{
|
|
89
|
+
kind: "unknown",
|
|
90
|
+
reasons: ["tuple-prefix-cap-exceeded"],
|
|
91
|
+
},
|
|
92
|
+
]
|
|
93
|
+
: []),
|
|
94
|
+
], limits);
|
|
95
|
+
return finiteOptimizerTuple(prefix, tail, limits);
|
|
96
|
+
}
|
|
97
|
+
function joinTupleTails(tails, limits) {
|
|
98
|
+
const unknownReasons = tails.flatMap((tail) => tail.kind === "unknown" ? tail.reasons : []);
|
|
99
|
+
if (unknownReasons.length > 0) {
|
|
100
|
+
return Object.freeze({
|
|
101
|
+
kind: "unknown",
|
|
102
|
+
reasons: Object.freeze(capReasons(unknownReasons, limits.maxUnknownReasons)),
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
const varargs = tails.filter((tail) => tail.kind === "vararg");
|
|
106
|
+
if (varargs.length === 0)
|
|
107
|
+
return Object.freeze({ kind: "none" });
|
|
108
|
+
const values = varargs.map((tail) => tail.value);
|
|
109
|
+
if (tails.some((tail) => tail.kind === "none")) {
|
|
110
|
+
values.push(finiteOptimizerValue([exports.NIL_ATOM], [], limits));
|
|
111
|
+
}
|
|
112
|
+
return Object.freeze({
|
|
113
|
+
kind: "vararg",
|
|
114
|
+
value: joinOptimizerValues(values, limits),
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
function normalizeTail(tail, limits) {
|
|
118
|
+
switch (tail.kind) {
|
|
119
|
+
case "none":
|
|
120
|
+
return Object.freeze({ kind: "none" });
|
|
121
|
+
case "vararg":
|
|
122
|
+
return Object.freeze({
|
|
123
|
+
kind: "vararg",
|
|
124
|
+
value: finiteOptimizerValue(tail.value.atoms, tail.value.unknownReasons, limits),
|
|
125
|
+
});
|
|
126
|
+
case "unknown":
|
|
127
|
+
return Object.freeze({
|
|
128
|
+
kind: "unknown",
|
|
129
|
+
reasons: Object.freeze(capReasons(tail.reasons, limits.maxUnknownReasons)),
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
function atomKey(atom) {
|
|
134
|
+
switch (atom.kind) {
|
|
135
|
+
case "nil":
|
|
136
|
+
return "0:nil";
|
|
137
|
+
case "boolean":
|
|
138
|
+
return `1:boolean:${atom.value ? "1" : "0"}`;
|
|
139
|
+
case "number":
|
|
140
|
+
return `2:number:${atom.raw}`;
|
|
141
|
+
case "string":
|
|
142
|
+
return `3:string:${JSON.stringify(atom.value)}`;
|
|
143
|
+
case "function":
|
|
144
|
+
return `4:function:${atom.id}`;
|
|
145
|
+
case "allocation":
|
|
146
|
+
return `5:allocation:${atom.allocationKind}:${atom.id}`;
|
|
147
|
+
case "parameter":
|
|
148
|
+
return `6:parameter:${String(atom.index).padStart(12, "0")}`;
|
|
149
|
+
case "external":
|
|
150
|
+
return `7:external:${atom.id}`;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
function uniqueSorted(values, keyOf) {
|
|
154
|
+
if (values.length === 0)
|
|
155
|
+
return [];
|
|
156
|
+
if (values.length === 1)
|
|
157
|
+
return [values[0]];
|
|
158
|
+
if (values.length === 2) {
|
|
159
|
+
const firstKey = keyOf(values[0]);
|
|
160
|
+
const lastKey = keyOf(values[1]);
|
|
161
|
+
if (firstKey === lastKey)
|
|
162
|
+
return [values[1]];
|
|
163
|
+
return firstKey < lastKey ? [values[0], values[1]] : [values[1], values[0]];
|
|
164
|
+
}
|
|
165
|
+
const byKey = new Map();
|
|
166
|
+
values.forEach((value) => byKey.set(keyOf(value), value));
|
|
167
|
+
return [...byKey.entries()]
|
|
168
|
+
.sort(([left], [right]) => (left < right ? -1 : left > right ? 1 : 0))
|
|
169
|
+
.map(([, value]) => value);
|
|
170
|
+
}
|
|
171
|
+
function capReasons(reasons, maximum) {
|
|
172
|
+
const normalized = uniqueSorted(reasons, (reason) => reason);
|
|
173
|
+
return capNormalizedReasons(normalized, maximum);
|
|
174
|
+
}
|
|
175
|
+
function capNormalizedReasons(normalized, maximum) {
|
|
176
|
+
if (normalized.length <= maximum)
|
|
177
|
+
return normalized;
|
|
178
|
+
if (maximum === 0)
|
|
179
|
+
return [];
|
|
180
|
+
return [
|
|
181
|
+
...normalized.slice(0, Math.max(0, maximum - 1)),
|
|
182
|
+
"reason-cap-exceeded",
|
|
183
|
+
];
|
|
184
|
+
}
|
|
185
|
+
function validateCustomLimits(limits) {
|
|
186
|
+
// The default is a module-owned frozen literal that satisfies the invariants.
|
|
187
|
+
// Nearly every optimizer value uses it, so do not enumerate its fields again.
|
|
188
|
+
if (limits !== exports.DEFAULT_OPTIMIZER_VALUE_DOMAIN_LIMITS)
|
|
189
|
+
validateLimits(limits);
|
|
190
|
+
}
|
|
191
|
+
function validateLimits(limits) {
|
|
192
|
+
Object.entries(limits).forEach(([name, value]) => {
|
|
193
|
+
if (!Number.isInteger(value) || value < 0)
|
|
194
|
+
throw new RangeError(`${name} must be a non-negative integer`);
|
|
195
|
+
});
|
|
196
|
+
// At least one slot is necessary to preserve the fact that a cap discarded
|
|
197
|
+
// information. An empty reason set means the atom set is exhaustive.
|
|
198
|
+
if (limits.maxUnknownReasons === 0)
|
|
199
|
+
throw new RangeError("maxUnknownReasons must be at least one");
|
|
200
|
+
}
|
package/dist/options.js
ADDED
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.optimizationLeafDefinitions = exports.optimizationOptionDefinitions = void 0;
|
|
4
|
+
exports.resolveMinifierMode = resolveMinifierMode;
|
|
5
|
+
exports.isOptimizationOptionKey = isOptimizationOptionKey;
|
|
6
|
+
exports.optimizationOptionDefinitions = [
|
|
7
|
+
{ key: "optimizations", name: "optimizations", defaultValue: undefined },
|
|
8
|
+
{
|
|
9
|
+
key: "identifierOptimizations",
|
|
10
|
+
name: "identifier-optimizations",
|
|
11
|
+
parent: "optimizations",
|
|
12
|
+
defaultValue: undefined,
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
key: "localRenaming",
|
|
16
|
+
name: "local-renaming",
|
|
17
|
+
parent: "identifierOptimizations",
|
|
18
|
+
defaultValue: true,
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
key: "localNameReuse",
|
|
22
|
+
name: "local-name-reuse",
|
|
23
|
+
parent: "identifierOptimizations",
|
|
24
|
+
defaultValue: true,
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
key: "globalRenaming",
|
|
28
|
+
name: "global-renaming",
|
|
29
|
+
parent: "identifierOptimizations",
|
|
30
|
+
defaultValue: false,
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
key: "fieldRenaming",
|
|
34
|
+
name: "field-renaming",
|
|
35
|
+
parent: "identifierOptimizations",
|
|
36
|
+
defaultValue: true,
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
key: "globalAliasing",
|
|
40
|
+
name: "global-aliasing",
|
|
41
|
+
parent: "identifierOptimizations",
|
|
42
|
+
defaultValue: true,
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
key: "statementOptimizations",
|
|
46
|
+
name: "statement-optimizations",
|
|
47
|
+
parent: "optimizations",
|
|
48
|
+
defaultValue: undefined,
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
key: "localDeclarationMerging",
|
|
52
|
+
name: "local-declaration-merging",
|
|
53
|
+
parent: "statementOptimizations",
|
|
54
|
+
defaultValue: true,
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
key: "localDeclarationHoisting",
|
|
58
|
+
name: "local-declaration-hoisting",
|
|
59
|
+
parent: "statementOptimizations",
|
|
60
|
+
defaultValue: true,
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
key: "tableReadMerging",
|
|
64
|
+
name: "table-read-merging",
|
|
65
|
+
parent: "statementOptimizations",
|
|
66
|
+
defaultValue: true,
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
key: "fieldSensitiveTableEffects",
|
|
70
|
+
name: "field-sensitive-table-effects",
|
|
71
|
+
parent: "statementOptimizations",
|
|
72
|
+
defaultValue: true,
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
key: "constantOptimizations",
|
|
76
|
+
name: "constant-optimizations",
|
|
77
|
+
parent: "optimizations",
|
|
78
|
+
defaultValue: undefined,
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
key: "constantExpressionEvaluation",
|
|
82
|
+
name: "constant-expression-evaluation",
|
|
83
|
+
parent: "constantOptimizations",
|
|
84
|
+
defaultValue: false,
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
key: "localConstantPropagation",
|
|
88
|
+
name: "local-constant-propagation",
|
|
89
|
+
parent: "constantOptimizations",
|
|
90
|
+
defaultValue: false,
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
key: "interproceduralConstantPropagation",
|
|
94
|
+
name: "interprocedural-constant-propagation",
|
|
95
|
+
parent: "constantOptimizations",
|
|
96
|
+
defaultValue: false,
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
key: "functionOptimizations",
|
|
100
|
+
name: "function-optimizations",
|
|
101
|
+
parent: "optimizations",
|
|
102
|
+
defaultValue: undefined,
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
key: "parameterPruning",
|
|
106
|
+
name: "parameter-pruning",
|
|
107
|
+
parent: "functionOptimizations",
|
|
108
|
+
defaultValue: true,
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
key: "functionInlining",
|
|
112
|
+
name: "function-inlining",
|
|
113
|
+
parent: "functionOptimizations",
|
|
114
|
+
defaultValue: true,
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
key: "functionSpecialization",
|
|
118
|
+
name: "function-specialization",
|
|
119
|
+
parent: "functionOptimizations",
|
|
120
|
+
defaultValue: true,
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
key: "objectOptimizations",
|
|
124
|
+
name: "object-optimizations",
|
|
125
|
+
parent: "optimizations",
|
|
126
|
+
defaultValue: undefined,
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
key: "fieldValuePropagation",
|
|
130
|
+
name: "field-value-propagation",
|
|
131
|
+
parent: "objectOptimizations",
|
|
132
|
+
defaultValue: true,
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
key: "deadCodeOptimizations",
|
|
136
|
+
name: "dead-code-optimizations",
|
|
137
|
+
parent: "optimizations",
|
|
138
|
+
defaultValue: undefined,
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
key: "unusedCodeRemoval",
|
|
142
|
+
name: "unused-code-removal",
|
|
143
|
+
parent: "deadCodeOptimizations",
|
|
144
|
+
defaultValue: undefined,
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
key: "unusedLocalRemoval",
|
|
148
|
+
name: "unused-local-removal",
|
|
149
|
+
parent: "unusedCodeRemoval",
|
|
150
|
+
defaultValue: true,
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
key: "unusedFunctionRemoval",
|
|
154
|
+
name: "unused-function-removal",
|
|
155
|
+
parent: "unusedCodeRemoval",
|
|
156
|
+
defaultValue: true,
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
key: "unusedFieldInitializerRemoval",
|
|
160
|
+
name: "unused-field-initializer-removal",
|
|
161
|
+
parent: "unusedCodeRemoval",
|
|
162
|
+
defaultValue: true,
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
key: "unusedExportRemoval",
|
|
166
|
+
name: "unused-export-removal",
|
|
167
|
+
parent: "deadCodeOptimizations",
|
|
168
|
+
defaultValue: true,
|
|
169
|
+
},
|
|
170
|
+
];
|
|
171
|
+
const definitionsByKey = new Map(exports.optimizationOptionDefinitions.map((definition) => [
|
|
172
|
+
definition.key,
|
|
173
|
+
definition,
|
|
174
|
+
]));
|
|
175
|
+
exports.optimizationLeafDefinitions = exports.optimizationOptionDefinitions.filter((definition) => definition.defaultValue !== undefined);
|
|
176
|
+
function isOptionLayers(value) {
|
|
177
|
+
return "config" in value || "cli" in value || "defaults" in value;
|
|
178
|
+
}
|
|
179
|
+
function valueFromLayer(key, layer) {
|
|
180
|
+
let current = key;
|
|
181
|
+
while (current !== undefined) {
|
|
182
|
+
const value = layer[current];
|
|
183
|
+
if (value !== undefined)
|
|
184
|
+
return value;
|
|
185
|
+
const definition = definitionsByKey.get(current);
|
|
186
|
+
current =
|
|
187
|
+
definition && "parent" in definition ? definition.parent : undefined;
|
|
188
|
+
}
|
|
189
|
+
return undefined;
|
|
190
|
+
}
|
|
191
|
+
function resolveMinifierMode(layers) {
|
|
192
|
+
const normalized = isOptionLayers(layers)
|
|
193
|
+
? layers
|
|
194
|
+
: { cli: layers };
|
|
195
|
+
const defaults = normalized.defaults ?? {};
|
|
196
|
+
const config = normalized.config ?? {};
|
|
197
|
+
const cli = normalized.cli ?? {};
|
|
198
|
+
const runtimeProfile = cli.runtimeProfile ??
|
|
199
|
+
config.runtimeProfile ??
|
|
200
|
+
defaults.runtimeProfile ??
|
|
201
|
+
"lua53";
|
|
202
|
+
const requireWrapper = cli.requireWrapper ??
|
|
203
|
+
config.requireWrapper ??
|
|
204
|
+
defaults.requireWrapper ??
|
|
205
|
+
false;
|
|
206
|
+
const resolved = {
|
|
207
|
+
...defaults,
|
|
208
|
+
...config,
|
|
209
|
+
...cli,
|
|
210
|
+
requireWrapper,
|
|
211
|
+
runtimeProfile,
|
|
212
|
+
};
|
|
213
|
+
exports.optimizationLeafDefinitions.forEach((definition) => {
|
|
214
|
+
resolved[definition.key] =
|
|
215
|
+
valueFromLayer(definition.key, cli) ??
|
|
216
|
+
valueFromLayer(definition.key, config) ??
|
|
217
|
+
valueFromLayer(definition.key, defaults) ??
|
|
218
|
+
definition.defaultValue;
|
|
219
|
+
});
|
|
220
|
+
exports.optimizationOptionDefinitions
|
|
221
|
+
.filter((definition) => definition.defaultValue === undefined)
|
|
222
|
+
.forEach((definition) => {
|
|
223
|
+
resolved[definition.key] =
|
|
224
|
+
valueFromLayer(definition.key, cli) ??
|
|
225
|
+
valueFromLayer(definition.key, config) ??
|
|
226
|
+
valueFromLayer(definition.key, defaults) ??
|
|
227
|
+
false;
|
|
228
|
+
});
|
|
229
|
+
return resolved;
|
|
230
|
+
}
|
|
231
|
+
function isOptimizationOptionKey(value) {
|
|
232
|
+
return definitionsByKey.has(value);
|
|
233
|
+
}
|
package/dist/progress.js
ADDED