@markw65/monkeyc-optimizer 1.1.11 → 1.1.13
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 +12 -0
- package/build/api.cjs +522 -346
- package/build/optimizer.cjs +504 -341
- package/build/src/api.d.ts +1 -1
- package/build/src/optimizer-types.d.ts +1 -0
- package/build/src/type-flow/mimimize-modules.d.ts +3 -0
- package/build/src/type-flow/minimize-locals.d.ts +2 -0
- package/build/src/type-flow/minimize-modules.d.ts +3 -0
- package/build/src/type-flow/type-flow-util.d.ts +1 -1
- package/package.json +2 -2
package/build/api.cjs
CHANGED
|
@@ -1507,9 +1507,10 @@ function buildDataFlowGraph(state, func, wantsLiteral, trackInsertionPoints, wan
|
|
|
1507
1507
|
decl,
|
|
1508
1508
|
mayThrow,
|
|
1509
1509
|
};
|
|
1510
|
-
if (wantsAllRefs
|
|
1511
|
-
if (node.right.type === "Identifier" ||
|
|
1512
|
-
node.right.type === "MemberExpression")
|
|
1510
|
+
if (wantsAllRefs) {
|
|
1511
|
+
if ((node.right.type === "Identifier" ||
|
|
1512
|
+
node.right.type === "MemberExpression") &&
|
|
1513
|
+
node.operator === "=") {
|
|
1513
1514
|
const rhs = findDecl(node.right);
|
|
1514
1515
|
if (rhs)
|
|
1515
1516
|
def.rhs = rhs;
|
|
@@ -2757,13 +2758,15 @@ function fixNodeScope(state, lookupNode, nodeStack) {
|
|
|
2757
2758
|
/* harmony import */ var _type_flow__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(4859);
|
|
2758
2759
|
/* harmony import */ var _type_flow_could_be__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(4055);
|
|
2759
2760
|
/* harmony import */ var _type_flow_interp__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(7161);
|
|
2760
|
-
/* harmony import */ var
|
|
2761
|
-
/* harmony import */ var
|
|
2762
|
-
/* harmony import */ var
|
|
2763
|
-
/* harmony import */ var
|
|
2764
|
-
/* harmony import */ var
|
|
2765
|
-
/* harmony import */ var
|
|
2766
|
-
/* harmony import */ var
|
|
2761
|
+
/* harmony import */ var _type_flow_minimize_modules__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(4416);
|
|
2762
|
+
/* harmony import */ var _type_flow_optimize__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(3687);
|
|
2763
|
+
/* harmony import */ var _type_flow_sub_type__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(9234);
|
|
2764
|
+
/* harmony import */ var _type_flow_types__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(7255);
|
|
2765
|
+
/* harmony import */ var _unused_exprs__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(424);
|
|
2766
|
+
/* harmony import */ var _util__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(6906);
|
|
2767
|
+
/* harmony import */ var _util__WEBPACK_IMPORTED_MODULE_17___default = /*#__PURE__*/__webpack_require__.n(_util__WEBPACK_IMPORTED_MODULE_17__);
|
|
2768
|
+
/* harmony import */ var _variable_renamer__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(4405);
|
|
2769
|
+
|
|
2767
2770
|
|
|
2768
2771
|
|
|
2769
2772
|
|
|
@@ -3369,32 +3372,30 @@ async function optimizeMonkeyC(fnMap, resourcesMap, manifestXML, config) {
|
|
|
3369
3372
|
break;
|
|
3370
3373
|
case "Identifier": {
|
|
3371
3374
|
const map = topLocals().map;
|
|
3372
|
-
if (map) {
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
|
|
3379
|
-
if (results) {
|
|
3380
|
-
|
|
3381
|
-
|
|
3382
|
-
|
|
3383
|
-
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
return [];
|
|
3392
|
-
}
|
|
3393
|
-
if (parent.type !== "BlockStatement") {
|
|
3394
|
-
throw new Error(`Local ${node.name} was not declared at block scope(??)`);
|
|
3395
|
-
}
|
|
3396
|
-
decl.used = true;
|
|
3375
|
+
if (hasProperty(map, node.name)) {
|
|
3376
|
+
const name = map[node.name];
|
|
3377
|
+
if (typeof name === "string") {
|
|
3378
|
+
renameIdentifier(node, name);
|
|
3379
|
+
}
|
|
3380
|
+
const [, results] = state.lookupValue(node);
|
|
3381
|
+
if (results) {
|
|
3382
|
+
if (results.length !== 1 || results[0].results.length !== 1) {
|
|
3383
|
+
throw new Error(`Local ${node.name} had multiple lookup results`);
|
|
3384
|
+
}
|
|
3385
|
+
const parent = results[0].parent;
|
|
3386
|
+
if (!parent) {
|
|
3387
|
+
throw new Error(`Local ${node.name} had no parent`);
|
|
3388
|
+
}
|
|
3389
|
+
const decl = results[0].results[0];
|
|
3390
|
+
if (parent.type === "FunctionDeclaration" ||
|
|
3391
|
+
decl.type !== "VariableDeclarator") {
|
|
3392
|
+
// we can't optimize away function or catch parameters
|
|
3393
|
+
return [];
|
|
3397
3394
|
}
|
|
3395
|
+
if (parent.type !== "BlockStatement") {
|
|
3396
|
+
throw new Error(`Local ${node.name} was not declared at block scope(??)`);
|
|
3397
|
+
}
|
|
3398
|
+
decl.used = true;
|
|
3398
3399
|
}
|
|
3399
3400
|
}
|
|
3400
3401
|
return [];
|
|
@@ -3682,6 +3683,11 @@ async function optimizeMonkeyC(fnMap, resourcesMap, manifestXML, config) {
|
|
|
3682
3683
|
state.nextExposed = {};
|
|
3683
3684
|
delete state.pre;
|
|
3684
3685
|
delete state.post;
|
|
3686
|
+
if (state.config?.minimizeModules ?? true) {
|
|
3687
|
+
Object.values(fnMap).forEach((f) => {
|
|
3688
|
+
minimizeModules(f.ast, state);
|
|
3689
|
+
});
|
|
3690
|
+
}
|
|
3685
3691
|
Object.values(state.allFunctions).forEach((fns) => fns.forEach((fn) => sizeBasedPRE(state, fn)));
|
|
3686
3692
|
const cleanup = (node) => {
|
|
3687
3693
|
switch (node.type) {
|
|
@@ -4025,7 +4031,7 @@ function pragmaChecker(state, ast, diagnostics) {
|
|
|
4025
4031
|
if (kind === "match") {
|
|
4026
4032
|
const haystack = formatAst(node)
|
|
4027
4033
|
.replace(/([\r\n]|\s)+/g, " ")
|
|
4028
|
-
.replace(/\b\w+\s\/\*>(\w+)<\*\//g, "$1");
|
|
4034
|
+
.replace(/\b\w+\s\/\*>([\w.]+)<\*\//g, "$1");
|
|
4029
4035
|
if (!matcher(quote, needle, haystack)) {
|
|
4030
4036
|
matcher(quote, needle, haystack);
|
|
4031
4037
|
diagnostic(state, comment, `Didn't find '${needle}' in '${haystack}'`, "ERROR");
|
|
@@ -4950,79 +4956,42 @@ function buildConflictGraph(state, func) {
|
|
|
4950
4956
|
function addEquiv(ts, key, equiv) {
|
|
4951
4957
|
if (key === equiv)
|
|
4952
4958
|
return true;
|
|
4953
|
-
|
|
4954
|
-
|
|
4959
|
+
const keyVal = ts.get(key);
|
|
4960
|
+
const equivVal = ts.get(equiv);
|
|
4955
4961
|
if (!keyVal || !equivVal)
|
|
4956
4962
|
return false;
|
|
4957
4963
|
if (equivVal.equivSet) {
|
|
4958
|
-
if (
|
|
4959
|
-
|
|
4960
|
-
// equiv is part of it.
|
|
4961
|
-
let s = keyVal.equivSet.next;
|
|
4962
|
-
do {
|
|
4963
|
-
if (s === equiv) {
|
|
4964
|
-
// these two are already equivalent
|
|
4965
|
-
return true;
|
|
4966
|
-
}
|
|
4967
|
-
const next = ts.get(s);
|
|
4968
|
-
if (!next || !next.equivSet) {
|
|
4969
|
-
throw new Error(`Inconsistent equivSet for ${tsKey(key)}: missing value for ${tsKey(s)}`);
|
|
4970
|
-
}
|
|
4971
|
-
s = next.equivSet.next;
|
|
4972
|
-
} while (s !== key);
|
|
4964
|
+
if (equivVal.equivSet.has(key)) {
|
|
4965
|
+
return true;
|
|
4973
4966
|
}
|
|
4974
4967
|
// equiv is already a member of a set. remove it
|
|
4975
4968
|
removeEquiv(ts, equiv);
|
|
4976
4969
|
}
|
|
4977
4970
|
// equiv is not (or no longer) part of an equivSet
|
|
4978
|
-
keyVal = { ...keyVal };
|
|
4979
4971
|
if (!keyVal.equivSet) {
|
|
4980
|
-
keyVal.equivSet =
|
|
4972
|
+
keyVal.equivSet = new Set([key, equiv]);
|
|
4973
|
+
}
|
|
4974
|
+
else {
|
|
4975
|
+
keyVal.equivSet.add(equiv);
|
|
4981
4976
|
}
|
|
4982
|
-
equivVal =
|
|
4983
|
-
keyVal.equivSet = { next: equiv };
|
|
4984
|
-
ts.set(key, keyVal);
|
|
4985
|
-
ts.set(equiv, equivVal);
|
|
4977
|
+
equivVal.equivSet = keyVal.equivSet;
|
|
4986
4978
|
return false;
|
|
4987
4979
|
}
|
|
4988
4980
|
function removeEquiv(ts, equiv) {
|
|
4989
4981
|
const equivVal = ts.get(equiv);
|
|
4990
4982
|
if (!equivVal?.equivSet)
|
|
4991
4983
|
return;
|
|
4992
|
-
|
|
4993
|
-
|
|
4994
|
-
const
|
|
4995
|
-
|
|
4996
|
-
|
|
4997
|
-
|
|
4998
|
-
|
|
4999
|
-
const { equivSet: _e, ...rest } = next;
|
|
5000
|
-
if (equivVal.equivSet.next === s) {
|
|
5001
|
-
// this is a pair. just kill both
|
|
5002
|
-
ts.set(s, rest);
|
|
5003
|
-
}
|
|
5004
|
-
else {
|
|
5005
|
-
ts.set(s, { ...rest, equivSet: equivVal.equivSet });
|
|
5006
|
-
}
|
|
5007
|
-
break;
|
|
5008
|
-
}
|
|
5009
|
-
s = next.equivSet.next;
|
|
5010
|
-
} while (true);
|
|
5011
|
-
const newVal = { ...equivVal };
|
|
5012
|
-
delete newVal.equivSet;
|
|
5013
|
-
ts.set(equiv, newVal);
|
|
4984
|
+
equivVal.equivSet.delete(equiv);
|
|
4985
|
+
if (equivVal.equivSet.size === 1) {
|
|
4986
|
+
const other = Array.from(equivVal.equivSet)[0];
|
|
4987
|
+
const otherVal = ts.get(other);
|
|
4988
|
+
delete otherVal.equivSet;
|
|
4989
|
+
}
|
|
4990
|
+
delete equivVal.equivSet;
|
|
5014
4991
|
}
|
|
5015
4992
|
function getEquivSet(ts, k) {
|
|
5016
|
-
const keys =
|
|
5017
|
-
|
|
5018
|
-
do {
|
|
5019
|
-
const next = ts.get(s);
|
|
5020
|
-
if (!next || !next.equivSet) {
|
|
5021
|
-
throw new Error(`Inconsistent equivSet for ${tsKey(k)}: missing value for ${tsKey(s)}`);
|
|
5022
|
-
}
|
|
5023
|
-
keys.add(s);
|
|
5024
|
-
s = next.equivSet.next;
|
|
5025
|
-
} while (s !== k);
|
|
4993
|
+
const keys = ts.get(k)?.equivSet;
|
|
4994
|
+
assert(keys);
|
|
5026
4995
|
return keys;
|
|
5027
4996
|
}
|
|
5028
4997
|
function intersectEquiv(ts1, ts2, k) {
|
|
@@ -5034,21 +5003,26 @@ function intersectEquiv(ts1, ts2, k) {
|
|
|
5034
5003
|
removeEquiv(ts1, k);
|
|
5035
5004
|
return true;
|
|
5036
5005
|
}
|
|
5037
|
-
|
|
5038
|
-
|
|
5039
|
-
|
|
5040
|
-
|
|
5041
|
-
|
|
5042
|
-
|
|
5043
|
-
|
|
5044
|
-
|
|
5045
|
-
if (!keys.has(s)) {
|
|
5046
|
-
ret = true;
|
|
5047
|
-
removeEquiv(ts1, s);
|
|
5006
|
+
let removed = null;
|
|
5007
|
+
eq1.equivSet.forEach((key) => {
|
|
5008
|
+
if (!eq2.equivSet.has(key)) {
|
|
5009
|
+
eq1.equivSet.delete(key);
|
|
5010
|
+
if (!removed) {
|
|
5011
|
+
removed = new Set();
|
|
5012
|
+
}
|
|
5013
|
+
removed.add(key);
|
|
5048
5014
|
}
|
|
5049
|
-
|
|
5050
|
-
|
|
5051
|
-
|
|
5015
|
+
});
|
|
5016
|
+
if (eq1.equivSet.size === 1) {
|
|
5017
|
+
assert(eq1.equivSet.has(k));
|
|
5018
|
+
delete eq1.equivSet;
|
|
5019
|
+
}
|
|
5020
|
+
if (removed) {
|
|
5021
|
+
removed.forEach((k) => removed.size === 1
|
|
5022
|
+
? delete ts1.get(k).equivSet
|
|
5023
|
+
: (ts1.get(k).equivSet = removed));
|
|
5024
|
+
}
|
|
5025
|
+
return false;
|
|
5052
5026
|
}
|
|
5053
5027
|
function clearAssocPaths(blockState, decl, v) {
|
|
5054
5028
|
if (v.assocPaths?.size) {
|
|
@@ -5066,6 +5040,17 @@ function clearAssocPaths(blockState, decl, v) {
|
|
|
5066
5040
|
function cloneTypeState(blockState) {
|
|
5067
5041
|
const { map, trackedMemberDecls, liveCopyPropEvents, ...rest } = blockState;
|
|
5068
5042
|
const clone = { map: new Map(map), ...rest };
|
|
5043
|
+
clone.map.forEach((value, key) => {
|
|
5044
|
+
if (value.equivSet) {
|
|
5045
|
+
if (key === Array.from(value.equivSet)[0]) {
|
|
5046
|
+
const equivSet = new Set(value.equivSet);
|
|
5047
|
+
equivSet.forEach((k) => clone.map.set(k, { ...clone.map.get(k), equivSet }));
|
|
5048
|
+
}
|
|
5049
|
+
}
|
|
5050
|
+
else {
|
|
5051
|
+
clone.map.set(key, { ...value });
|
|
5052
|
+
}
|
|
5053
|
+
});
|
|
5069
5054
|
if (trackedMemberDecls) {
|
|
5070
5055
|
clone.trackedMemberDecls = new Map();
|
|
5071
5056
|
trackedMemberDecls.forEach((value, key) => {
|
|
@@ -5100,12 +5085,9 @@ function addCopyPropEvent(blockState, item) {
|
|
|
5100
5085
|
const liveCopyPropEvents = blockState.liveCopyPropEvents;
|
|
5101
5086
|
const decl = item.event.decl;
|
|
5102
5087
|
assert(declIsLocal(decl));
|
|
5103
|
-
|
|
5088
|
+
const tov = blockState.map.get(decl);
|
|
5104
5089
|
assert(tov);
|
|
5105
|
-
|
|
5106
|
-
tov = { ...tov, copyPropItem: item };
|
|
5107
|
-
blockState.map.set(decl, tov);
|
|
5108
|
-
}
|
|
5090
|
+
tov.copyPropItem = item;
|
|
5109
5091
|
item.contained.forEach((value, key) => {
|
|
5110
5092
|
const decls = liveCopyPropEvents.get(key);
|
|
5111
5093
|
if (!decls) {
|
|
@@ -5138,15 +5120,13 @@ function clearRelatedCopyPropEvents(blockState, decl, nodeCopyProp) {
|
|
|
5138
5120
|
blockState.liveCopyPropEvents
|
|
5139
5121
|
?.get(decl)
|
|
5140
5122
|
?.forEach((cpDecl) => {
|
|
5141
|
-
|
|
5123
|
+
const value = blockState.map.get(cpDecl);
|
|
5142
5124
|
assert(value && value.copyPropItem);
|
|
5143
5125
|
assert(Array.from(value.copyPropItem.contained).some(([key]) => {
|
|
5144
5126
|
return decl === key;
|
|
5145
5127
|
}));
|
|
5146
5128
|
copyPropFailed(blockState, value.copyPropItem, nodeCopyProp);
|
|
5147
|
-
value = { ...value };
|
|
5148
5129
|
delete value.copyPropItem;
|
|
5149
|
-
blockState.map.set(cpDecl, value);
|
|
5150
5130
|
});
|
|
5151
5131
|
}
|
|
5152
5132
|
function validateTypeState(curState) {
|
|
@@ -5189,11 +5169,9 @@ function mergeTypeState(blockStates, index, from, nodeCopyProp) {
|
|
|
5189
5169
|
if (tov.equivSet) {
|
|
5190
5170
|
if (intersectEquiv(to.map, from.map, k)) {
|
|
5191
5171
|
changes = true;
|
|
5192
|
-
tov = to.map.get(k);
|
|
5193
5172
|
}
|
|
5194
5173
|
}
|
|
5195
5174
|
if (tov.assocPaths) {
|
|
5196
|
-
tov = { ...tov };
|
|
5197
5175
|
if (!fromv.assocPaths) {
|
|
5198
5176
|
changes = true;
|
|
5199
5177
|
delete tov.assocPaths;
|
|
@@ -5216,7 +5194,6 @@ function mergeTypeState(blockStates, index, from, nodeCopyProp) {
|
|
|
5216
5194
|
delete tov.assocPaths;
|
|
5217
5195
|
}
|
|
5218
5196
|
}
|
|
5219
|
-
to.map.set(k, tov);
|
|
5220
5197
|
}
|
|
5221
5198
|
// if both from and to have copyPropEvents, we can only
|
|
5222
5199
|
// keep it if they're the same event.
|
|
@@ -5234,10 +5211,8 @@ function mergeTypeState(blockStates, index, from, nodeCopyProp) {
|
|
|
5234
5211
|
}
|
|
5235
5212
|
nodeCopyProp.set(fromv.copyPropItem.event.node, false);
|
|
5236
5213
|
}
|
|
5237
|
-
tov = { ...tov };
|
|
5238
5214
|
delete tov.copyPropItem;
|
|
5239
5215
|
changes = true;
|
|
5240
|
-
to.map.set(k, tov);
|
|
5241
5216
|
}
|
|
5242
5217
|
else {
|
|
5243
5218
|
assert(k === tov.copyPropItem.event.decl);
|
|
@@ -5248,7 +5223,7 @@ function mergeTypeState(blockStates, index, from, nodeCopyProp) {
|
|
|
5248
5223
|
if (subtypeOf(fromv.curType, tov.curType))
|
|
5249
5224
|
return;
|
|
5250
5225
|
if (subtypeOf(tov.curType, fromv.curType)) {
|
|
5251
|
-
|
|
5226
|
+
tov.curType = fromv.curType;
|
|
5252
5227
|
changes = true;
|
|
5253
5228
|
return;
|
|
5254
5229
|
}
|
|
@@ -5261,22 +5236,11 @@ function mergeTypeState(blockStates, index, from, nodeCopyProp) {
|
|
|
5261
5236
|
if (wide)
|
|
5262
5237
|
result = wide;
|
|
5263
5238
|
}
|
|
5264
|
-
|
|
5239
|
+
tov.curType = result;
|
|
5265
5240
|
changes = true;
|
|
5266
5241
|
});
|
|
5267
5242
|
return changes;
|
|
5268
5243
|
}
|
|
5269
|
-
function tsEquivs(state, key) {
|
|
5270
|
-
const result = [];
|
|
5271
|
-
let s = key;
|
|
5272
|
-
do {
|
|
5273
|
-
result.push(tsKey(s));
|
|
5274
|
-
const next = state.get(s);
|
|
5275
|
-
assert(next && next.equivSet);
|
|
5276
|
-
s = next.equivSet.next;
|
|
5277
|
-
} while (s !== key);
|
|
5278
|
-
return `[(${result.join(", ")})]`;
|
|
5279
|
-
}
|
|
5280
5244
|
function typeStateEntry(value, key) {
|
|
5281
5245
|
return `${tsKey(key)} = ${display(value.curType)}`;
|
|
5282
5246
|
}
|
|
@@ -5287,7 +5251,9 @@ function printBlockState(block, state, indent = "") {
|
|
|
5287
5251
|
return;
|
|
5288
5252
|
}
|
|
5289
5253
|
state.map.forEach((value, key) => {
|
|
5290
|
-
console.log(`${indent} - ${typeStateEntry(value, key)}${value.equivSet
|
|
5254
|
+
console.log(`${indent} - ${typeStateEntry(value, key)}${value.equivSet
|
|
5255
|
+
? " " + `[(${Array.from(value.equivSet).map(tsKey).join(", ")})]`
|
|
5256
|
+
: ""}`);
|
|
5291
5257
|
});
|
|
5292
5258
|
}
|
|
5293
5259
|
function updateAffected(blockState, objectType, baseDecl, assignedPath, affectedName, affected, assignedType) {
|
|
@@ -5295,7 +5261,6 @@ function updateAffected(blockState, objectType, baseDecl, assignedPath, affected
|
|
|
5295
5261
|
let droppedComponents = null;
|
|
5296
5262
|
const entry = blockState.map.get(key);
|
|
5297
5263
|
assert(entry && entry.assocPaths);
|
|
5298
|
-
let newEntry = entry;
|
|
5299
5264
|
entry.assocPaths.forEach((path) => {
|
|
5300
5265
|
if (key === baseDecl && path === assignedPath) {
|
|
5301
5266
|
return;
|
|
@@ -5314,12 +5279,9 @@ function updateAffected(blockState, objectType, baseDecl, assignedPath, affected
|
|
|
5314
5279
|
});
|
|
5315
5280
|
if (pathItem === affectedName && couldBeShallow(type, objectType)) {
|
|
5316
5281
|
const newAssocKey = assocPath.map((av) => av.name ?? "*").join(".");
|
|
5317
|
-
if (newEntry === entry) {
|
|
5318
|
-
newEntry = { ...entry };
|
|
5319
|
-
}
|
|
5320
5282
|
if (newAssocKey !== path) {
|
|
5321
|
-
|
|
5322
|
-
|
|
5283
|
+
entry.assocPaths = new Set(entry.assocPaths);
|
|
5284
|
+
entry.assocPaths.delete(path);
|
|
5323
5285
|
// the "extra" path components will also have entries
|
|
5324
5286
|
// in blockState.trackedMemberDecls. Since they're gone
|
|
5325
5287
|
// from here, we (may) need to remove them from there
|
|
@@ -5331,8 +5293,7 @@ function updateAffected(blockState, objectType, baseDecl, assignedPath, affected
|
|
|
5331
5293
|
}
|
|
5332
5294
|
break;
|
|
5333
5295
|
}
|
|
5334
|
-
|
|
5335
|
-
newEntry.curType = baseType;
|
|
5296
|
+
entry.curType = updateByAssocPath(assocPath, assignedType, true);
|
|
5336
5297
|
break;
|
|
5337
5298
|
}
|
|
5338
5299
|
if (pathItem === "*") {
|
|
@@ -5362,14 +5323,11 @@ function updateAffected(blockState, objectType, baseDecl, assignedPath, affected
|
|
|
5362
5323
|
}
|
|
5363
5324
|
}
|
|
5364
5325
|
});
|
|
5365
|
-
if (
|
|
5366
|
-
|
|
5367
|
-
|
|
5368
|
-
|
|
5369
|
-
|
|
5370
|
-
droppedComponents.forEach((pathComponent) => blockState.trackedMemberDecls.get(pathComponent).delete(key));
|
|
5371
|
-
}
|
|
5372
|
-
blockState.map.set(key, newEntry);
|
|
5326
|
+
if (droppedComponents) {
|
|
5327
|
+
entry.assocPaths.forEach((path) => path
|
|
5328
|
+
.split(".")
|
|
5329
|
+
.forEach((pathComponent) => droppedComponents.delete(pathComponent)));
|
|
5330
|
+
droppedComponents.forEach((pathComponent) => blockState.trackedMemberDecls.get(pathComponent).delete(key));
|
|
5373
5331
|
}
|
|
5374
5332
|
});
|
|
5375
5333
|
}
|
|
@@ -5476,10 +5434,9 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, copyPropStore
|
|
|
5476
5434
|
const assocKey = assocValue.map((av) => av.name ?? "*").join(".");
|
|
5477
5435
|
const newType = updateByAssocPath(assocValue, next, false);
|
|
5478
5436
|
setStateEvent(blockState, decl.base, newType, newValue ? 1 /* UpdateKind.Inner */ : 0 /* UpdateKind.None */);
|
|
5479
|
-
const tsv =
|
|
5437
|
+
const tsv = blockState.map.get(decl.base);
|
|
5480
5438
|
tsv.assocPaths = new Set(tsv.assocPaths);
|
|
5481
5439
|
tsv.assocPaths.add(assocKey);
|
|
5482
|
-
blockState.map.set(decl.base, tsv);
|
|
5483
5440
|
addTrackedMemberDecl(blockState, decl.base, assocKey);
|
|
5484
5441
|
if (newValue) {
|
|
5485
5442
|
const baseElem = assocValue[decl.path.length - 1];
|
|
@@ -5557,38 +5514,39 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, copyPropStore
|
|
|
5557
5514
|
// that foo is side-effect free, and accesses no globals.
|
|
5558
5515
|
clearRelatedCopyPropEvents(blockState, decl, nodeCopyProp);
|
|
5559
5516
|
}
|
|
5517
|
+
const v = blockState.map.get(decl);
|
|
5518
|
+
if (!v) {
|
|
5519
|
+
blockState.map.set(decl, { curType: value });
|
|
5520
|
+
return;
|
|
5521
|
+
}
|
|
5560
5522
|
if (updateKind !== 2 /* UpdateKind.Reassign */) {
|
|
5561
5523
|
/*
|
|
5562
5524
|
* If we're not re-assigning, the equivalencies don't
|
|
5563
5525
|
* change, so this update must be applied to every
|
|
5564
5526
|
* element of the set
|
|
5565
5527
|
*/
|
|
5566
|
-
|
|
5567
|
-
|
|
5568
|
-
let s = decl;
|
|
5569
|
-
do {
|
|
5528
|
+
if (v.equivSet) {
|
|
5529
|
+
v.equivSet.forEach((s) => {
|
|
5570
5530
|
const next = blockState.map.get(s);
|
|
5571
|
-
|
|
5572
|
-
|
|
5573
|
-
|
|
5574
|
-
blockState.map.set(s, { ...next, curType: value });
|
|
5575
|
-
s = next.equivSet.next;
|
|
5576
|
-
} while (s !== decl);
|
|
5531
|
+
assert(next && next.equivSet?.has(s));
|
|
5532
|
+
next.curType = value;
|
|
5533
|
+
});
|
|
5577
5534
|
}
|
|
5578
5535
|
else {
|
|
5579
|
-
|
|
5536
|
+
v.curType = value;
|
|
5580
5537
|
}
|
|
5581
5538
|
}
|
|
5582
5539
|
else {
|
|
5583
|
-
const v = blockState.map.get(decl);
|
|
5584
5540
|
removeEquiv(blockState.map, decl);
|
|
5585
|
-
if (v
|
|
5541
|
+
if (v.assocPaths?.size) {
|
|
5586
5542
|
clearAssocPaths(blockState, decl, v);
|
|
5543
|
+
delete v.assocPaths;
|
|
5587
5544
|
}
|
|
5588
|
-
if (v
|
|
5545
|
+
if (v.copyPropItem) {
|
|
5589
5546
|
copyPropFailed(blockState, v.copyPropItem, nodeCopyProp);
|
|
5547
|
+
delete v.copyPropItem;
|
|
5590
5548
|
}
|
|
5591
|
-
|
|
5549
|
+
v.curType = value;
|
|
5592
5550
|
}
|
|
5593
5551
|
return;
|
|
5594
5552
|
}
|
|
@@ -5922,7 +5880,7 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, copyPropStore
|
|
|
5922
5880
|
break;
|
|
5923
5881
|
}
|
|
5924
5882
|
case "ref": {
|
|
5925
|
-
|
|
5883
|
+
const curEntry = getStateEntry(curState, event.decl);
|
|
5926
5884
|
typeMap.set(event.node, curEntry.curType);
|
|
5927
5885
|
nodeEquivs.delete(event.node);
|
|
5928
5886
|
if (curEntry.equivSet) {
|
|
@@ -5946,9 +5904,7 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, copyPropStore
|
|
|
5946
5904
|
nodeCopyProp.set(curEntry.copyPropItem.event.node, event.node);
|
|
5947
5905
|
}
|
|
5948
5906
|
clearCopyProp(curState, curEntry.copyPropItem);
|
|
5949
|
-
curEntry = { ...curEntry };
|
|
5950
5907
|
delete curEntry.copyPropItem;
|
|
5951
|
-
curState.map.set(event.decl, curEntry);
|
|
5952
5908
|
}
|
|
5953
5909
|
else if (declIsNonLocal(event.decl)) {
|
|
5954
5910
|
clearRelatedCopyPropEvents(curState, null, nodeCopyProp);
|
|
@@ -5986,12 +5942,13 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, copyPropStore
|
|
|
5986
5942
|
}
|
|
5987
5943
|
});
|
|
5988
5944
|
}
|
|
5945
|
+
let calleeEffects;
|
|
5989
5946
|
curState.map.forEach((tsv, decl) => {
|
|
5990
5947
|
let type = tsv.curType;
|
|
5991
|
-
if (
|
|
5992
|
-
(
|
|
5993
|
-
|
|
5994
|
-
|
|
5948
|
+
if ((type.value == null ||
|
|
5949
|
+
!(type.type &
|
|
5950
|
+
(32768 /* TypeTag.Object */ | 512 /* TypeTag.Array */ | 1024 /* TypeTag.Dictionary */))) &&
|
|
5951
|
+
!some(decl, (d) => d.type === "VariableDeclarator" && !isLocal(d))) {
|
|
5995
5952
|
return;
|
|
5996
5953
|
}
|
|
5997
5954
|
if (modifiableDecl(decl, callees)) {
|
|
@@ -6007,9 +5964,14 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, copyPropStore
|
|
|
6007
5964
|
clearRelatedCopyPropEvents(curState, decl, nodeCopyProp);
|
|
6008
5965
|
curState.map.set(decl, { curType: typeConstraint(decl) });
|
|
6009
5966
|
}
|
|
6010
|
-
else if (type.
|
|
6011
|
-
(
|
|
6012
|
-
|
|
5967
|
+
else if (type.type &
|
|
5968
|
+
(32768 /* TypeTag.Object */ | 512 /* TypeTag.Array */ | 1024 /* TypeTag.Dictionary */) &&
|
|
5969
|
+
(calleeEffects == null
|
|
5970
|
+
? (calleeEffects =
|
|
5971
|
+
!callees ||
|
|
5972
|
+
!every(callees, (callee) => callee.info === false))
|
|
5973
|
+
: calleeEffects)) {
|
|
5974
|
+
if (type.value != null && type.type & 32768 /* TypeTag.Object */) {
|
|
6013
5975
|
const odata = getObjectValue(tsv.curType);
|
|
6014
5976
|
if (odata?.obj) {
|
|
6015
5977
|
type = cloneType(type);
|
|
@@ -6017,18 +5979,12 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, copyPropStore
|
|
|
6017
5979
|
setUnionComponent(type, 32768 /* TypeTag.Object */, newData);
|
|
6018
5980
|
if (tsv.assocPaths) {
|
|
6019
5981
|
clearAssocPaths(curState, decl, tsv);
|
|
6020
|
-
tsv = { ...tsv };
|
|
6021
5982
|
delete tsv.assocPaths;
|
|
6022
5983
|
}
|
|
6023
|
-
|
|
6024
|
-
copyPropFailed(curState, tsv.copyPropItem, nodeCopyProp);
|
|
6025
|
-
tsv = { ...tsv };
|
|
6026
|
-
delete tsv.copyPropItem;
|
|
6027
|
-
}
|
|
6028
|
-
clearRelatedCopyPropEvents(curState, decl, nodeCopyProp);
|
|
6029
|
-
curState.map.set(decl, { ...tsv, curType: type });
|
|
5984
|
+
tsv.curType = type;
|
|
6030
5985
|
}
|
|
6031
5986
|
}
|
|
5987
|
+
clearRelatedCopyPropEvents(curState, decl, nodeCopyProp);
|
|
6032
5988
|
}
|
|
6033
5989
|
});
|
|
6034
5990
|
return true;
|
|
@@ -6050,10 +6006,7 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, copyPropStore
|
|
|
6050
6006
|
(event.node.type !== "AssignmentExpression" ||
|
|
6051
6007
|
event.node.operator !== "=")) {
|
|
6052
6008
|
copyPropFailed(curState, before.copyPropItem, nodeCopyProp);
|
|
6053
|
-
|
|
6054
|
-
delete v.copyPropItem;
|
|
6055
|
-
assert(isTypeStateKey(event.decl));
|
|
6056
|
-
curState.map.set(event.decl, v);
|
|
6009
|
+
delete before.copyPropItem;
|
|
6057
6010
|
}
|
|
6058
6011
|
}
|
|
6059
6012
|
const expr = event.node.type === "VariableDeclarator"
|
|
@@ -6147,22 +6100,41 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, copyPropStore
|
|
|
6147
6100
|
decl.type === "BinaryExpression" ||
|
|
6148
6101
|
decl.type === "Identifier"))) {
|
|
6149
6102
|
const key = event.decl ?? null;
|
|
6150
|
-
if (key &&
|
|
6151
|
-
|
|
6152
|
-
|
|
6153
|
-
|
|
6154
|
-
|
|
6155
|
-
|
|
6156
|
-
|
|
6157
|
-
|
|
6158
|
-
|
|
6159
|
-
|
|
6160
|
-
|
|
6161
|
-
|
|
6162
|
-
|
|
6163
|
-
|
|
6164
|
-
|
|
6165
|
-
|
|
6103
|
+
if (key && declIsLocal(key)) {
|
|
6104
|
+
if (nodeCopyProp.has(event.node)) {
|
|
6105
|
+
// we might have
|
|
6106
|
+
//
|
|
6107
|
+
// var x = foo();
|
|
6108
|
+
// var y = x + 1;
|
|
6109
|
+
// bar();
|
|
6110
|
+
// return y;
|
|
6111
|
+
//
|
|
6112
|
+
// In that case, its ok to drop "x = foo()" and rewrite as y = foo() + 1"
|
|
6113
|
+
// OR its ok to drop "y = x + 1" and rewrite as "return x + 1".
|
|
6114
|
+
// But we can't do both, and rewrite as "bar(); return foo() + 1;"
|
|
6115
|
+
// So just disable copy prop for *this* node. We'll re-run and have a
|
|
6116
|
+
// second chance later.
|
|
6117
|
+
return false;
|
|
6118
|
+
}
|
|
6119
|
+
else if (event.node.type === "AssignmentExpression" &&
|
|
6120
|
+
event.node.operator !== "=" &&
|
|
6121
|
+
nodeCopyProp.has(event.node.left)) {
|
|
6122
|
+
// If we're copy proping into the lhs of an update
|
|
6123
|
+
// assignment, we're going to have to rewrite it.
|
|
6124
|
+
// similar to the above, don't also do forward copy
|
|
6125
|
+
// prop. eg
|
|
6126
|
+
//
|
|
6127
|
+
// var x = a + b;
|
|
6128
|
+
// x += c;
|
|
6129
|
+
// return x;
|
|
6130
|
+
//
|
|
6131
|
+
// becomes
|
|
6132
|
+
//
|
|
6133
|
+
// var x;
|
|
6134
|
+
// x = (a + b) + c;
|
|
6135
|
+
// return x; // <- dont propagate to here (yet), in case a+b has changed.
|
|
6136
|
+
return false;
|
|
6137
|
+
}
|
|
6166
6138
|
}
|
|
6167
6139
|
const item = contained.get(key);
|
|
6168
6140
|
if (!item) {
|
|
@@ -6351,7 +6323,22 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, copyPropStore
|
|
|
6351
6323
|
}
|
|
6352
6324
|
}
|
|
6353
6325
|
}));
|
|
6354
|
-
traverseAst(func.node.body,
|
|
6326
|
+
traverseAst(func.node.body, (node) => {
|
|
6327
|
+
if (node.type === "AssignmentExpression" &&
|
|
6328
|
+
node.operator !== "=" &&
|
|
6329
|
+
nodeCopyProp.has(node.left)) {
|
|
6330
|
+
const left = cloneDeep(node.left);
|
|
6331
|
+
const right = withLoc({
|
|
6332
|
+
type: "BinaryExpression",
|
|
6333
|
+
operator: node.operator.slice(0, -1),
|
|
6334
|
+
left: withLocDeep(node.left, node.right, false, true),
|
|
6335
|
+
right: node.right,
|
|
6336
|
+
}, node.left, node.right);
|
|
6337
|
+
node.operator = "=";
|
|
6338
|
+
node.left = left;
|
|
6339
|
+
node.right = right;
|
|
6340
|
+
}
|
|
6341
|
+
}, (node) => {
|
|
6355
6342
|
const copyNode = nodeCopyProp.get(node);
|
|
6356
6343
|
if (copyNode) {
|
|
6357
6344
|
if (node.type === "AssignmentExpression") {
|
|
@@ -6370,10 +6357,18 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, copyPropStore
|
|
|
6370
6357
|
return dup;
|
|
6371
6358
|
}
|
|
6372
6359
|
if (copyNode.type === "AssignmentExpression") {
|
|
6360
|
+
const replacement = copyNode.operator === "="
|
|
6361
|
+
? copyNode.right
|
|
6362
|
+
: {
|
|
6363
|
+
type: "BinaryExpression",
|
|
6364
|
+
operator: copyNode.operator.slice(0, -1),
|
|
6365
|
+
left: copyNode.left,
|
|
6366
|
+
right: copyNode.right,
|
|
6367
|
+
};
|
|
6373
6368
|
if (logThisRun) {
|
|
6374
|
-
console.log(`copy-prop ${formatAstLongLines(node)} => ${formatAstLongLines(
|
|
6369
|
+
console.log(`copy-prop ${formatAstLongLines(node)} => ${formatAstLongLines(replacement)}`);
|
|
6375
6370
|
}
|
|
6376
|
-
return withLocDeep(
|
|
6371
|
+
return withLocDeep(replacement, node, node, false);
|
|
6377
6372
|
}
|
|
6378
6373
|
else if (copyNode.type === "VariableDeclarator") {
|
|
6379
6374
|
assert(copyNode.init);
|
|
@@ -6706,7 +6701,9 @@ function couldBeObj(a, b) {
|
|
|
6706
6701
|
/* harmony import */ var _control_flow__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(5101);
|
|
6707
6702
|
/* harmony import */ var _data_flow__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(8180);
|
|
6708
6703
|
/* harmony import */ var _inliner__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(333);
|
|
6709
|
-
/* harmony import */ var
|
|
6704
|
+
/* harmony import */ var _minimize_locals__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(736);
|
|
6705
|
+
/* harmony import */ var _type_flow_util__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(1638);
|
|
6706
|
+
|
|
6710
6707
|
|
|
6711
6708
|
|
|
6712
6709
|
|
|
@@ -6715,18 +6712,18 @@ function couldBeObj(a, b) {
|
|
|
6715
6712
|
|
|
6716
6713
|
|
|
6717
6714
|
function cloneAnt(antMap) {
|
|
6718
|
-
|
|
6719
|
-
antMap.forEach((s, k) => ant.set(k, new Set(s)));
|
|
6720
|
-
return ant;
|
|
6715
|
+
return new Map(antMap);
|
|
6721
6716
|
}
|
|
6722
6717
|
function addAnt(antMap, decl, node) {
|
|
6723
6718
|
assert(node.type === "Identifier");
|
|
6724
6719
|
const ant = antMap.get(decl);
|
|
6725
|
-
if (
|
|
6726
|
-
|
|
6720
|
+
if (ant === false || ant === node)
|
|
6721
|
+
return;
|
|
6722
|
+
if (ant === undefined) {
|
|
6723
|
+
antMap.set(decl, node);
|
|
6727
6724
|
}
|
|
6728
6725
|
else {
|
|
6729
|
-
|
|
6726
|
+
antMap.set(decl, false);
|
|
6730
6727
|
}
|
|
6731
6728
|
}
|
|
6732
6729
|
function cloneState(blockState) {
|
|
@@ -6762,18 +6759,10 @@ function findDeadStores(func, graph, nodeEquivs, findCopyPropCandidates, logThis
|
|
|
6762
6759
|
else {
|
|
6763
6760
|
changed = Array.from(to.anticipated).reduce((changed, [decl, toant]) => {
|
|
6764
6761
|
const fromant = from.anticipated.get(decl);
|
|
6765
|
-
if (
|
|
6762
|
+
if (toant !== fromant) {
|
|
6766
6763
|
to.anticipated.delete(decl);
|
|
6767
6764
|
changed = true;
|
|
6768
6765
|
}
|
|
6769
|
-
else {
|
|
6770
|
-
toant.forEach((node) => {
|
|
6771
|
-
if (!fromant.has(node)) {
|
|
6772
|
-
toant.delete(node);
|
|
6773
|
-
changed = true;
|
|
6774
|
-
}
|
|
6775
|
-
});
|
|
6776
|
-
}
|
|
6777
6766
|
return changed;
|
|
6778
6767
|
}, changed);
|
|
6779
6768
|
}
|
|
@@ -6786,17 +6775,15 @@ function findDeadStores(func, graph, nodeEquivs, findCopyPropCandidates, logThis
|
|
|
6786
6775
|
else {
|
|
6787
6776
|
changed = Array.from(from.partiallyAnticipated).reduce((changed, [decl, fromant]) => {
|
|
6788
6777
|
const toant = to.partiallyAnticipated.get(decl);
|
|
6789
|
-
if (
|
|
6778
|
+
if (toant === undefined) {
|
|
6790
6779
|
to.partiallyAnticipated.set(decl, fromant);
|
|
6791
6780
|
changed = true;
|
|
6792
6781
|
}
|
|
6793
6782
|
else {
|
|
6794
|
-
fromant
|
|
6795
|
-
|
|
6796
|
-
|
|
6797
|
-
|
|
6798
|
-
}
|
|
6799
|
-
});
|
|
6783
|
+
if (toant !== fromant) {
|
|
6784
|
+
changed = true;
|
|
6785
|
+
to.partiallyAnticipated.set(decl, false);
|
|
6786
|
+
}
|
|
6800
6787
|
}
|
|
6801
6788
|
return changed;
|
|
6802
6789
|
}, changed);
|
|
@@ -6860,7 +6847,7 @@ function findDeadStores(func, graph, nodeEquivs, findCopyPropCandidates, logThis
|
|
|
6860
6847
|
}
|
|
6861
6848
|
addAnt(curState.partiallyAnticipated, event.decl, event.node);
|
|
6862
6849
|
if (logThisRun) {
|
|
6863
|
-
console.log(` antrefs: ${curState.partiallyAnticipated.get(event.decl)
|
|
6850
|
+
console.log(` antrefs: ${curState.partiallyAnticipated.get(event.decl) !== false} ${curState.anticipated.get(event.decl) !== false}`);
|
|
6864
6851
|
}
|
|
6865
6852
|
}
|
|
6866
6853
|
curState.dead.delete(event.decl);
|
|
@@ -6881,25 +6868,21 @@ function findDeadStores(func, graph, nodeEquivs, findCopyPropCandidates, logThis
|
|
|
6881
6868
|
}
|
|
6882
6869
|
else {
|
|
6883
6870
|
deadStores.delete(event.node);
|
|
6884
|
-
|
|
6885
|
-
|
|
6886
|
-
curState.partiallyAnticipated) {
|
|
6871
|
+
copyPropStores.delete(event.node);
|
|
6872
|
+
if (declIsLocal(event.decl) && curState.partiallyAnticipated) {
|
|
6887
6873
|
const pant = curState.partiallyAnticipated.get(event.decl);
|
|
6888
|
-
if (pant
|
|
6874
|
+
if (pant) {
|
|
6889
6875
|
if (logThisRun) {
|
|
6890
|
-
console.log(` is copy-prop-candidate ${curState.anticipated?.get(event.decl)
|
|
6876
|
+
console.log(` is copy-prop-candidate ${curState.anticipated?.get(event.decl) === pant}`);
|
|
6891
6877
|
}
|
|
6892
6878
|
copyPropStores.set(event.node, {
|
|
6893
|
-
ref:
|
|
6894
|
-
ant: curState.anticipated?.get(event.decl)
|
|
6879
|
+
ref: pant,
|
|
6880
|
+
ant: curState.anticipated?.get(event.decl) === pant,
|
|
6895
6881
|
});
|
|
6896
6882
|
}
|
|
6897
6883
|
curState.partiallyAnticipated.delete(event.decl);
|
|
6898
6884
|
curState.anticipated?.delete(event.decl);
|
|
6899
6885
|
}
|
|
6900
|
-
else {
|
|
6901
|
-
copyPropStores.delete(event.node);
|
|
6902
|
-
}
|
|
6903
6886
|
}
|
|
6904
6887
|
if (nodeConflicts) {
|
|
6905
6888
|
const conflicts = new Set(locals);
|
|
@@ -6988,7 +6971,10 @@ function eliminateDeadStores(state, func, graph, logThisRun) {
|
|
|
6988
6971
|
console.log(`${formatAst(dead)} (${sourceLocation(dead.loc)})`));
|
|
6989
6972
|
}
|
|
6990
6973
|
let changes = false;
|
|
6991
|
-
traverseAst(func.node.body, null, (node
|
|
6974
|
+
traverseAst(func.node.body, null, (node) => {
|
|
6975
|
+
const cleaned = variableCleanup(node);
|
|
6976
|
+
if (cleaned !== null)
|
|
6977
|
+
return cleaned;
|
|
6992
6978
|
if (node.type === "ExpressionStatement" &&
|
|
6993
6979
|
node.expression.type === "AssignmentExpression" &&
|
|
6994
6980
|
deadStores.has(node.expression)) {
|
|
@@ -7010,40 +6996,17 @@ function eliminateDeadStores(state, func, graph, logThisRun) {
|
|
|
7010
6996
|
changes = true;
|
|
7011
6997
|
return { type: "Literal", value: null, raw: "null" };
|
|
7012
6998
|
}
|
|
7013
|
-
if (node.type === "
|
|
7014
|
-
const
|
|
7015
|
-
|
|
7016
|
-
const
|
|
7017
|
-
|
|
7018
|
-
|
|
7019
|
-
|
|
7020
|
-
|
|
7021
|
-
(parent.type !== "BlockStatement" && parent.type !== "SwitchCase")) {
|
|
7022
|
-
// Must be the init in a for statement. Fixing
|
|
7023
|
-
// it would be complicated, so just punt for now.
|
|
7024
|
-
break;
|
|
7025
|
-
}
|
|
7026
|
-
const newDeclaration = withLoc({ ...node }, node, decl.id);
|
|
7027
|
-
if (i + 1 < node.declarations.length) {
|
|
7028
|
-
newDeclaration.declarations = node.declarations.splice(0, i + 1);
|
|
7029
|
-
result.push(newDeclaration);
|
|
7030
|
-
withLoc(node, node.declarations[0], node);
|
|
7031
|
-
i = -1;
|
|
7032
|
-
}
|
|
7033
|
-
else {
|
|
7034
|
-
result.push(node);
|
|
7035
|
-
}
|
|
7036
|
-
result.push(...body);
|
|
7037
|
-
}
|
|
7038
|
-
changes = true;
|
|
7039
|
-
delete decl.init;
|
|
7040
|
-
}
|
|
7041
|
-
}
|
|
7042
|
-
if (result.length) {
|
|
7043
|
-
if (!result.includes(node)) {
|
|
7044
|
-
result.push(node);
|
|
6999
|
+
if (node.type === "VariableDeclarator") {
|
|
7000
|
+
const decl = node;
|
|
7001
|
+
if (decl.init && deadStores.has(decl)) {
|
|
7002
|
+
const body = unused(state, decl.init);
|
|
7003
|
+
delete decl.init;
|
|
7004
|
+
changes = true;
|
|
7005
|
+
if (!body.length) {
|
|
7006
|
+
return null;
|
|
7045
7007
|
}
|
|
7046
|
-
|
|
7008
|
+
body.unshift(decl);
|
|
7009
|
+
return body;
|
|
7047
7010
|
}
|
|
7048
7011
|
}
|
|
7049
7012
|
return null;
|
|
@@ -9342,7 +9305,7 @@ function restrictByEquality(a, b) {
|
|
|
9342
9305
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
9343
9306
|
|
|
9344
9307
|
"use strict";
|
|
9345
|
-
/* unused harmony
|
|
9308
|
+
/* unused harmony exports minimizeLocals, variableCleanup */
|
|
9346
9309
|
/* harmony import */ var node_assert__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4143);
|
|
9347
9310
|
/* harmony import */ var node_assert__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(node_assert__WEBPACK_IMPORTED_MODULE_0__);
|
|
9348
9311
|
/* harmony import */ var _api__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6817);
|
|
@@ -9516,11 +9479,6 @@ function minimizeLocals(state, func) {
|
|
|
9516
9479
|
return null;
|
|
9517
9480
|
}
|
|
9518
9481
|
break;
|
|
9519
|
-
case "ExpressionStatement":
|
|
9520
|
-
if (node.expression.type === "Literal") {
|
|
9521
|
-
return false;
|
|
9522
|
-
}
|
|
9523
|
-
break;
|
|
9524
9482
|
case "UpdateExpression":
|
|
9525
9483
|
if (info) {
|
|
9526
9484
|
assert(node.argument.type === "Identifier");
|
|
@@ -9541,7 +9499,7 @@ function minimizeLocals(state, func) {
|
|
|
9541
9499
|
}
|
|
9542
9500
|
// VariableDeclarations aren't allowed to have
|
|
9543
9501
|
// AssignmentExpressions in them, but we'll fix that
|
|
9544
|
-
//
|
|
9502
|
+
// via variableCleanup
|
|
9545
9503
|
return withLoc({
|
|
9546
9504
|
type: "AssignmentExpression",
|
|
9547
9505
|
operator: "=",
|
|
@@ -9554,79 +9512,297 @@ function minimizeLocals(state, func) {
|
|
|
9554
9512
|
}, node, node);
|
|
9555
9513
|
}
|
|
9556
9514
|
break;
|
|
9557
|
-
|
|
9558
|
-
|
|
9559
|
-
|
|
9560
|
-
|
|
9561
|
-
|
|
9562
|
-
|
|
9563
|
-
|
|
9564
|
-
|
|
9565
|
-
|
|
9566
|
-
|
|
9567
|
-
|
|
9568
|
-
|
|
9569
|
-
|
|
9570
|
-
|
|
9571
|
-
|
|
9572
|
-
|
|
9573
|
-
|
|
9574
|
-
|
|
9575
|
-
|
|
9576
|
-
|
|
9577
|
-
|
|
9578
|
-
|
|
9579
|
-
|
|
9580
|
-
|
|
9581
|
-
|
|
9582
|
-
|
|
9583
|
-
|
|
9584
|
-
|
|
9585
|
-
|
|
9586
|
-
|
|
9587
|
-
|
|
9588
|
-
|
|
9515
|
+
}
|
|
9516
|
+
assert(!info);
|
|
9517
|
+
return variableCleanup(node);
|
|
9518
|
+
});
|
|
9519
|
+
return;
|
|
9520
|
+
}
|
|
9521
|
+
function variableCleanup(node) {
|
|
9522
|
+
switch (node.type) {
|
|
9523
|
+
case "ExpressionStatement":
|
|
9524
|
+
if (node.expression.type === "Literal") {
|
|
9525
|
+
return false;
|
|
9526
|
+
}
|
|
9527
|
+
break;
|
|
9528
|
+
case "VariableDeclaration":
|
|
9529
|
+
if (node.declarations.some((decl) => decl.type !== "VariableDeclarator")) {
|
|
9530
|
+
const results = [];
|
|
9531
|
+
node.declarations.forEach((decl) => {
|
|
9532
|
+
if (isStatement(decl)) {
|
|
9533
|
+
results.push(decl);
|
|
9534
|
+
}
|
|
9535
|
+
else if (isExpression(decl)) {
|
|
9536
|
+
results.push(withLoc({ type: "ExpressionStatement", expression: decl }, decl, decl));
|
|
9537
|
+
}
|
|
9538
|
+
else if (decl.init) {
|
|
9539
|
+
results.push(withLoc({
|
|
9540
|
+
type: "ExpressionStatement",
|
|
9541
|
+
expression: withLoc({
|
|
9542
|
+
type: "AssignmentExpression",
|
|
9543
|
+
operator: "=",
|
|
9544
|
+
left: withLoc({
|
|
9545
|
+
type: "Identifier",
|
|
9546
|
+
name: variableDeclarationName(decl.id),
|
|
9547
|
+
}, decl.id, decl.id),
|
|
9548
|
+
right: decl.init,
|
|
9549
|
+
}, decl, decl),
|
|
9550
|
+
}, decl, decl));
|
|
9589
9551
|
}
|
|
9590
|
-
|
|
9591
|
-
|
|
9592
|
-
|
|
9593
|
-
|
|
9552
|
+
});
|
|
9553
|
+
node.declarations = node.declarations.filter((decl) => {
|
|
9554
|
+
if (decl.type === "VariableDeclarator") {
|
|
9555
|
+
delete decl.init;
|
|
9556
|
+
return true;
|
|
9557
|
+
}
|
|
9558
|
+
return false;
|
|
9559
|
+
});
|
|
9560
|
+
if (node.declarations.length) {
|
|
9561
|
+
withLocDeep(node, node, false);
|
|
9562
|
+
results.unshift(node);
|
|
9594
9563
|
}
|
|
9595
|
-
|
|
9596
|
-
|
|
9597
|
-
|
|
9598
|
-
|
|
9599
|
-
|
|
9600
|
-
|
|
9601
|
-
|
|
9602
|
-
|
|
9603
|
-
|
|
9604
|
-
|
|
9605
|
-
|
|
9606
|
-
|
|
9607
|
-
|
|
9608
|
-
|
|
9609
|
-
|
|
9610
|
-
|
|
9611
|
-
|
|
9564
|
+
// if this was the init of a ForStatement, this will
|
|
9565
|
+
// replace its init with a BlockStatement, so we have to
|
|
9566
|
+
// fix that below.
|
|
9567
|
+
return results;
|
|
9568
|
+
}
|
|
9569
|
+
break;
|
|
9570
|
+
case "ForStatement":
|
|
9571
|
+
if (node.init) {
|
|
9572
|
+
if (node.init.type === "BlockStatement") {
|
|
9573
|
+
const result = node.init;
|
|
9574
|
+
delete node.init;
|
|
9575
|
+
result.body.push(node);
|
|
9576
|
+
if (node.loc && result.loc) {
|
|
9577
|
+
// result has the range of the original VariableDeclaration
|
|
9578
|
+
// but now we're moving that ahead of the 'for', so to keep
|
|
9579
|
+
// things straight, we need to set the for's start to be
|
|
9580
|
+
// where result ended, and result's end to be where the for
|
|
9581
|
+
// ends (since that block now encloses the for)
|
|
9582
|
+
node.start = result.end;
|
|
9583
|
+
node.loc.start = result.loc.end;
|
|
9584
|
+
result.end = node.end;
|
|
9585
|
+
result.loc.end = node.loc.end;
|
|
9586
|
+
}
|
|
9587
|
+
return result;
|
|
9588
|
+
}
|
|
9589
|
+
if (node.init.type === "Literal") {
|
|
9590
|
+
delete node.init;
|
|
9591
|
+
}
|
|
9592
|
+
}
|
|
9593
|
+
break;
|
|
9594
|
+
case "SequenceExpression":
|
|
9595
|
+
if (node.expressions.some((e) => e.type === "Literal")) {
|
|
9596
|
+
node.expressions = node.expressions.filter((e) => e.type !== "Literal");
|
|
9597
|
+
}
|
|
9598
|
+
break;
|
|
9599
|
+
}
|
|
9600
|
+
return null;
|
|
9601
|
+
}
|
|
9602
|
+
|
|
9603
|
+
|
|
9604
|
+
/***/ }),
|
|
9605
|
+
|
|
9606
|
+
/***/ 4416:
|
|
9607
|
+
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
9608
|
+
|
|
9609
|
+
"use strict";
|
|
9610
|
+
/* unused harmony export minimizeModules */
|
|
9611
|
+
/* harmony import */ var node_assert__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4143);
|
|
9612
|
+
/* harmony import */ var node_assert__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(node_assert__WEBPACK_IMPORTED_MODULE_0__);
|
|
9613
|
+
/* harmony import */ var _ast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6652);
|
|
9614
|
+
/* harmony import */ var _api__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(6817);
|
|
9615
|
+
/* harmony import */ var _api__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_api__WEBPACK_IMPORTED_MODULE_2__);
|
|
9616
|
+
|
|
9617
|
+
|
|
9618
|
+
|
|
9619
|
+
function minimizeModules(ast, state) {
|
|
9620
|
+
const { pre, post } = state;
|
|
9621
|
+
try {
|
|
9622
|
+
const replacementMap = new Map();
|
|
9623
|
+
const conflictingNames = new Set();
|
|
9624
|
+
state.pre = (node) => {
|
|
9625
|
+
if (state.inType)
|
|
9626
|
+
return null;
|
|
9627
|
+
switch (node.type) {
|
|
9628
|
+
case "ModuleDeclaration":
|
|
9629
|
+
case "ClassDeclaration":
|
|
9630
|
+
case "FunctionDeclaration":
|
|
9631
|
+
return ["body"];
|
|
9632
|
+
case "Using":
|
|
9633
|
+
conflictingNames.add(node.as?.name ??
|
|
9634
|
+
(node.id.type === "Identifier"
|
|
9635
|
+
? node.id.name
|
|
9636
|
+
: node.id.property.name));
|
|
9637
|
+
return [];
|
|
9638
|
+
case "ImportModule":
|
|
9639
|
+
conflictingNames.add(node.id.type === "Identifier" ? node.id.name : node.id.property.name);
|
|
9640
|
+
return [];
|
|
9641
|
+
case "Identifier":
|
|
9642
|
+
case "MemberExpression": {
|
|
9643
|
+
let current = node;
|
|
9644
|
+
const parts = [];
|
|
9645
|
+
while (current.type === "MemberExpression" && !current.computed) {
|
|
9646
|
+
parts.unshift(current);
|
|
9647
|
+
current = current.object;
|
|
9648
|
+
}
|
|
9649
|
+
if (current.type !== "Identifier" &&
|
|
9650
|
+
current.type !== "ThisExpression") {
|
|
9651
|
+
break;
|
|
9652
|
+
}
|
|
9653
|
+
let toReplace = null;
|
|
9654
|
+
let module = null;
|
|
9655
|
+
let addImport = false;
|
|
9656
|
+
let [, results] = state.lookupValue(current, null);
|
|
9657
|
+
let i = 0;
|
|
9658
|
+
for (; results &&
|
|
9659
|
+
results.length === 1 &&
|
|
9660
|
+
results[0].results.length === 1 &&
|
|
9661
|
+
(results[0].results[0].type === "Program" ||
|
|
9662
|
+
results[0].results[0].type === "ClassDeclaration" ||
|
|
9663
|
+
results[0].results[0].type === "ModuleDeclaration"); i++) {
|
|
9664
|
+
if (current.type === "Identifier" &&
|
|
9665
|
+
results[0].results[0].type === "ModuleDeclaration" &&
|
|
9666
|
+
isImportCandidate(results[0].results[0])) {
|
|
9667
|
+
const directResults = i
|
|
9668
|
+
? state.lookupValue(current, null)
|
|
9669
|
+
: results;
|
|
9670
|
+
if (directResults &&
|
|
9671
|
+
directResults.length === 1 &&
|
|
9672
|
+
directResults[0].results.length === 1 &&
|
|
9673
|
+
directResults[0].results[0] === results[0].results[0]) {
|
|
9674
|
+
// we would find the same thing if we just looked up
|
|
9675
|
+
// current directly.
|
|
9676
|
+
toReplace = (i ? parts[i - 1] : current);
|
|
9677
|
+
module = results[0].results[0];
|
|
9678
|
+
if (findUsingForNode(state, state.stack, state.stack.length - 1, current) === directResults[0].results[0]) {
|
|
9679
|
+
// we already find it via an import, so we don't need
|
|
9680
|
+
// a new import.
|
|
9681
|
+
addImport = false;
|
|
9682
|
+
}
|
|
9683
|
+
else {
|
|
9684
|
+
addImport = true;
|
|
9685
|
+
}
|
|
9686
|
+
}
|
|
9687
|
+
else {
|
|
9688
|
+
toReplace = parts[i - 1];
|
|
9689
|
+
module = results[0].results[0];
|
|
9690
|
+
addImport = true;
|
|
9691
|
+
}
|
|
9612
9692
|
}
|
|
9613
|
-
|
|
9693
|
+
if (i === parts.length)
|
|
9694
|
+
break;
|
|
9695
|
+
current = parts[i].property;
|
|
9696
|
+
results = lookupNext(state, results, "decls", current);
|
|
9614
9697
|
}
|
|
9615
|
-
if (
|
|
9616
|
-
|
|
9698
|
+
if (toReplace) {
|
|
9699
|
+
assert(module);
|
|
9700
|
+
replacementMap.set(toReplace, { module, addImport });
|
|
9617
9701
|
}
|
|
9702
|
+
else if (parts.length === 0) {
|
|
9703
|
+
assert(node.type === "Identifier");
|
|
9704
|
+
conflictingNames.add(node.name);
|
|
9705
|
+
}
|
|
9706
|
+
else if (parts[0].object.type === "Identifier") {
|
|
9707
|
+
conflictingNames.add(parts[0].object.name);
|
|
9708
|
+
}
|
|
9709
|
+
return [];
|
|
9618
9710
|
}
|
|
9619
|
-
|
|
9620
|
-
|
|
9621
|
-
|
|
9622
|
-
|
|
9711
|
+
}
|
|
9712
|
+
return null;
|
|
9713
|
+
};
|
|
9714
|
+
collectNamespaces(ast, state);
|
|
9715
|
+
const mappedNames = new Map();
|
|
9716
|
+
replacementMap.forEach((value, key) => {
|
|
9717
|
+
let name;
|
|
9718
|
+
if (value.addImport) {
|
|
9719
|
+
name = mappedNames.get(value.module);
|
|
9720
|
+
if (!name) {
|
|
9721
|
+
name = value.module.name;
|
|
9722
|
+
for (let i = 0; conflictingNames.has(name); i++) {
|
|
9723
|
+
name = `${value.module.name}_${i}`;
|
|
9724
|
+
}
|
|
9725
|
+
mappedNames.set(value.module, name);
|
|
9726
|
+
conflictingNames.add(name);
|
|
9623
9727
|
}
|
|
9624
|
-
|
|
9625
|
-
|
|
9626
|
-
|
|
9627
|
-
|
|
9728
|
+
}
|
|
9729
|
+
else {
|
|
9730
|
+
name = key.type === "Identifier" ? key.name : key.property.name;
|
|
9731
|
+
}
|
|
9732
|
+
const original = formatAstLongLines(key);
|
|
9733
|
+
const repl = key;
|
|
9734
|
+
repl.type = "Identifier";
|
|
9735
|
+
repl.name = name;
|
|
9736
|
+
if (name !== original) {
|
|
9737
|
+
repl.original = original;
|
|
9738
|
+
}
|
|
9739
|
+
delete repl.property;
|
|
9740
|
+
delete repl.object;
|
|
9741
|
+
delete repl.computed;
|
|
9742
|
+
});
|
|
9743
|
+
mappedNames.forEach((name, module) => {
|
|
9744
|
+
const id = makeScopedName(module.fullName.slice(2));
|
|
9745
|
+
const as = name !== (id.type === "Identifier" ? id : id.property).name &&
|
|
9746
|
+
makeIdentifier(name);
|
|
9747
|
+
const using = withLocDeep(as ? { type: "Using", id, as } : { type: "Using", id }, ast, false, true);
|
|
9748
|
+
ast.body.unshift(using);
|
|
9749
|
+
});
|
|
9750
|
+
}
|
|
9751
|
+
finally {
|
|
9752
|
+
state.pre = pre;
|
|
9753
|
+
state.post = post;
|
|
9754
|
+
}
|
|
9755
|
+
}
|
|
9756
|
+
/**
|
|
9757
|
+
* There's a bug in garmin's runtime (although the compiler could
|
|
9758
|
+
* work around it). See
|
|
9759
|
+
*
|
|
9760
|
+
* https://forums.garmin.com/developer/connect-iq/i/bug-reports/referencing-an-imported-module-doesn-t-run-its-parent-s-init
|
|
9761
|
+
*
|
|
9762
|
+
* What this means is that if a module's parent isn't `globals`
|
|
9763
|
+
* and it needs to be initialized, then we can't risk
|
|
9764
|
+
* importing it, because the parent module might not get initialized
|
|
9765
|
+
* in time.
|
|
9766
|
+
*/
|
|
9767
|
+
function isImportCandidate(module) {
|
|
9768
|
+
if (module.fullName.startsWith("$.Toybox."))
|
|
9769
|
+
return true;
|
|
9770
|
+
if (module.fullName.startsWith("$.Rez."))
|
|
9771
|
+
return false;
|
|
9772
|
+
assert(module.stack);
|
|
9773
|
+
if (module.stack.length === 1)
|
|
9774
|
+
return true;
|
|
9775
|
+
return module.stack.every((elem) => {
|
|
9776
|
+
if (!elem.sn.decls)
|
|
9777
|
+
return false;
|
|
9778
|
+
if (elem.sn.type === "Program")
|
|
9779
|
+
return true;
|
|
9780
|
+
if (elem.sn.type !== "ModuleDeclaration")
|
|
9781
|
+
return false;
|
|
9782
|
+
return Object.values(elem.sn.decls).every((decls) => decls.every((decl) => {
|
|
9783
|
+
if (decl.type !== "VariableDeclarator")
|
|
9784
|
+
return true;
|
|
9785
|
+
if (!decl.node.init)
|
|
9786
|
+
return true;
|
|
9787
|
+
if (decl.node.init.type === "UnaryExpression" &&
|
|
9788
|
+
decl.node.init.operator === ":") {
|
|
9789
|
+
return true;
|
|
9790
|
+
}
|
|
9791
|
+
if (decl.node.init.type !== "Literal")
|
|
9792
|
+
return false;
|
|
9793
|
+
switch (typeof decl.node.init.value) {
|
|
9794
|
+
case "boolean":
|
|
9795
|
+
return true;
|
|
9796
|
+
case "bigint":
|
|
9797
|
+
return false;
|
|
9798
|
+
case "number":
|
|
9799
|
+
return !/[dl]$/i.test(decl.node.init.raw);
|
|
9800
|
+
case "object":
|
|
9801
|
+
return decl.node.init.value === null;
|
|
9802
|
+
}
|
|
9803
|
+
return false;
|
|
9804
|
+
}));
|
|
9628
9805
|
});
|
|
9629
|
-
return;
|
|
9630
9806
|
}
|
|
9631
9807
|
|
|
9632
9808
|
|