@markw65/monkeyc-optimizer 1.1.12 → 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 +4 -0
- package/build/api.cjs +383 -204
- package/build/optimizer.cjs +365 -199
- 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/types.d.ts +1 -1
- package/package.json +1 -1
package/build/optimizer.cjs
CHANGED
|
@@ -6029,7 +6029,7 @@ function pragmaChecker(state, ast, diagnostics) {
|
|
|
6029
6029
|
if (kind === "match") {
|
|
6030
6030
|
const haystack = (0,external_api_cjs_namespaceObject.formatAst)(node)
|
|
6031
6031
|
.replace(/([\r\n]|\s)+/g, " ")
|
|
6032
|
-
.replace(/\b\w+\s\/\*>(\w+)<\*\//g, "$1");
|
|
6032
|
+
.replace(/\b\w+\s\/\*>([\w.]+)<\*\//g, "$1");
|
|
6033
6033
|
if (!matcher(quote, needle, haystack)) {
|
|
6034
6034
|
matcher(quote, needle, haystack);
|
|
6035
6035
|
(0,external_api_cjs_namespaceObject.diagnostic)(state, comment, `Didn't find '${needle}' in '${haystack}'`, "ERROR");
|
|
@@ -11183,6 +11183,7 @@ const external_node_assert_namespaceObject = require("node:assert");
|
|
|
11183
11183
|
|
|
11184
11184
|
|
|
11185
11185
|
|
|
11186
|
+
|
|
11186
11187
|
function cloneAnt(antMap) {
|
|
11187
11188
|
return new Map(antMap);
|
|
11188
11189
|
}
|
|
@@ -11443,7 +11444,10 @@ function eliminateDeadStores(state, func, graph, logThisRun) {
|
|
|
11443
11444
|
console.log(`${(0,external_api_cjs_namespaceObject.formatAst)(dead)} (${sourceLocation(dead.loc)})`));
|
|
11444
11445
|
}
|
|
11445
11446
|
let changes = false;
|
|
11446
|
-
(0,external_api_cjs_namespaceObject.traverseAst)(func.node.body, null, (node
|
|
11447
|
+
(0,external_api_cjs_namespaceObject.traverseAst)(func.node.body, null, (node) => {
|
|
11448
|
+
const cleaned = variableCleanup(node);
|
|
11449
|
+
if (cleaned !== null)
|
|
11450
|
+
return cleaned;
|
|
11447
11451
|
if (node.type === "ExpressionStatement" &&
|
|
11448
11452
|
node.expression.type === "AssignmentExpression" &&
|
|
11449
11453
|
deadStores.has(node.expression)) {
|
|
@@ -11465,40 +11469,17 @@ function eliminateDeadStores(state, func, graph, logThisRun) {
|
|
|
11465
11469
|
changes = true;
|
|
11466
11470
|
return { type: "Literal", value: null, raw: "null" };
|
|
11467
11471
|
}
|
|
11468
|
-
if (node.type === "
|
|
11469
|
-
const
|
|
11470
|
-
|
|
11471
|
-
const
|
|
11472
|
-
|
|
11473
|
-
|
|
11474
|
-
|
|
11475
|
-
|
|
11476
|
-
(parent.type !== "BlockStatement" && parent.type !== "SwitchCase")) {
|
|
11477
|
-
// Must be the init in a for statement. Fixing
|
|
11478
|
-
// it would be complicated, so just punt for now.
|
|
11479
|
-
break;
|
|
11480
|
-
}
|
|
11481
|
-
const newDeclaration = withLoc({ ...node }, node, decl.id);
|
|
11482
|
-
if (i + 1 < node.declarations.length) {
|
|
11483
|
-
newDeclaration.declarations = node.declarations.splice(0, i + 1);
|
|
11484
|
-
result.push(newDeclaration);
|
|
11485
|
-
withLoc(node, node.declarations[0], node);
|
|
11486
|
-
i = -1;
|
|
11487
|
-
}
|
|
11488
|
-
else {
|
|
11489
|
-
result.push(node);
|
|
11490
|
-
}
|
|
11491
|
-
result.push(...body);
|
|
11492
|
-
}
|
|
11493
|
-
changes = true;
|
|
11494
|
-
delete decl.init;
|
|
11495
|
-
}
|
|
11496
|
-
}
|
|
11497
|
-
if (result.length) {
|
|
11498
|
-
if (!result.includes(node)) {
|
|
11499
|
-
result.push(node);
|
|
11472
|
+
if (node.type === "VariableDeclarator") {
|
|
11473
|
+
const decl = node;
|
|
11474
|
+
if (decl.init && deadStores.has(decl)) {
|
|
11475
|
+
const body = unused(state, decl.init);
|
|
11476
|
+
delete decl.init;
|
|
11477
|
+
changes = true;
|
|
11478
|
+
if (!body.length) {
|
|
11479
|
+
return null;
|
|
11500
11480
|
}
|
|
11501
|
-
|
|
11481
|
+
body.unshift(decl);
|
|
11482
|
+
return body;
|
|
11502
11483
|
}
|
|
11503
11484
|
}
|
|
11504
11485
|
return null;
|
|
@@ -11578,8 +11559,8 @@ function buildConflictGraph(state, func) {
|
|
|
11578
11559
|
function addEquiv(ts, key, equiv) {
|
|
11579
11560
|
if (key === equiv)
|
|
11580
11561
|
return true;
|
|
11581
|
-
|
|
11582
|
-
|
|
11562
|
+
const keyVal = ts.get(key);
|
|
11563
|
+
const equivVal = ts.get(equiv);
|
|
11583
11564
|
if (!keyVal || !equivVal)
|
|
11584
11565
|
return false;
|
|
11585
11566
|
if (equivVal.equivSet) {
|
|
@@ -11591,31 +11572,25 @@ function addEquiv(ts, key, equiv) {
|
|
|
11591
11572
|
}
|
|
11592
11573
|
// equiv is not (or no longer) part of an equivSet
|
|
11593
11574
|
if (!keyVal.equivSet) {
|
|
11594
|
-
keyVal = { ...keyVal };
|
|
11595
11575
|
keyVal.equivSet = new Set([key, equiv]);
|
|
11596
|
-
ts.set(key, keyVal);
|
|
11597
11576
|
}
|
|
11598
11577
|
else {
|
|
11599
11578
|
keyVal.equivSet.add(equiv);
|
|
11600
11579
|
}
|
|
11601
|
-
equivVal =
|
|
11602
|
-
ts.set(equiv, equivVal);
|
|
11580
|
+
equivVal.equivSet = keyVal.equivSet;
|
|
11603
11581
|
return false;
|
|
11604
11582
|
}
|
|
11605
11583
|
function removeEquiv(ts, equiv) {
|
|
11606
|
-
|
|
11584
|
+
const equivVal = ts.get(equiv);
|
|
11607
11585
|
if (!equivVal?.equivSet)
|
|
11608
11586
|
return;
|
|
11609
11587
|
equivVal.equivSet.delete(equiv);
|
|
11610
11588
|
if (equivVal.equivSet.size === 1) {
|
|
11611
11589
|
const other = Array.from(equivVal.equivSet)[0];
|
|
11612
|
-
const otherVal =
|
|
11590
|
+
const otherVal = ts.get(other);
|
|
11613
11591
|
delete otherVal.equivSet;
|
|
11614
|
-
ts.set(other, otherVal);
|
|
11615
11592
|
}
|
|
11616
|
-
equivVal = { ...equivVal };
|
|
11617
11593
|
delete equivVal.equivSet;
|
|
11618
|
-
ts.set(equiv, equivVal);
|
|
11619
11594
|
}
|
|
11620
11595
|
function getEquivSet(ts, k) {
|
|
11621
11596
|
const keys = ts.get(k)?.equivSet;
|
|
@@ -11669,9 +11644,14 @@ function cloneTypeState(blockState) {
|
|
|
11669
11644
|
const { map, trackedMemberDecls, liveCopyPropEvents, ...rest } = blockState;
|
|
11670
11645
|
const clone = { map: new Map(map), ...rest };
|
|
11671
11646
|
clone.map.forEach((value, key) => {
|
|
11672
|
-
if (value.equivSet
|
|
11673
|
-
|
|
11674
|
-
|
|
11647
|
+
if (value.equivSet) {
|
|
11648
|
+
if (key === Array.from(value.equivSet)[0]) {
|
|
11649
|
+
const equivSet = new Set(value.equivSet);
|
|
11650
|
+
equivSet.forEach((k) => clone.map.set(k, { ...clone.map.get(k), equivSet }));
|
|
11651
|
+
}
|
|
11652
|
+
}
|
|
11653
|
+
else {
|
|
11654
|
+
clone.map.set(key, { ...value });
|
|
11675
11655
|
}
|
|
11676
11656
|
});
|
|
11677
11657
|
if (trackedMemberDecls) {
|
|
@@ -11708,12 +11688,9 @@ function addCopyPropEvent(blockState, item) {
|
|
|
11708
11688
|
const liveCopyPropEvents = blockState.liveCopyPropEvents;
|
|
11709
11689
|
const decl = item.event.decl;
|
|
11710
11690
|
external_node_assert_namespaceObject(declIsLocal(decl));
|
|
11711
|
-
|
|
11691
|
+
const tov = blockState.map.get(decl);
|
|
11712
11692
|
external_node_assert_namespaceObject(tov);
|
|
11713
|
-
|
|
11714
|
-
tov = { ...tov, copyPropItem: item };
|
|
11715
|
-
blockState.map.set(decl, tov);
|
|
11716
|
-
}
|
|
11693
|
+
tov.copyPropItem = item;
|
|
11717
11694
|
item.contained.forEach((value, key) => {
|
|
11718
11695
|
const decls = liveCopyPropEvents.get(key);
|
|
11719
11696
|
if (!decls) {
|
|
@@ -11746,15 +11723,13 @@ function clearRelatedCopyPropEvents(blockState, decl, nodeCopyProp) {
|
|
|
11746
11723
|
blockState.liveCopyPropEvents
|
|
11747
11724
|
?.get(decl)
|
|
11748
11725
|
?.forEach((cpDecl) => {
|
|
11749
|
-
|
|
11726
|
+
const value = blockState.map.get(cpDecl);
|
|
11750
11727
|
external_node_assert_namespaceObject(value && value.copyPropItem);
|
|
11751
11728
|
external_node_assert_namespaceObject(Array.from(value.copyPropItem.contained).some(([key]) => {
|
|
11752
11729
|
return decl === key;
|
|
11753
11730
|
}));
|
|
11754
11731
|
copyPropFailed(blockState, value.copyPropItem, nodeCopyProp);
|
|
11755
|
-
value = { ...value };
|
|
11756
11732
|
delete value.copyPropItem;
|
|
11757
|
-
blockState.map.set(cpDecl, value);
|
|
11758
11733
|
});
|
|
11759
11734
|
}
|
|
11760
11735
|
function validateTypeState(curState) {
|
|
@@ -11797,11 +11772,9 @@ function mergeTypeState(blockStates, index, from, nodeCopyProp) {
|
|
|
11797
11772
|
if (tov.equivSet) {
|
|
11798
11773
|
if (intersectEquiv(to.map, from.map, k)) {
|
|
11799
11774
|
changes = true;
|
|
11800
|
-
tov = to.map.get(k);
|
|
11801
11775
|
}
|
|
11802
11776
|
}
|
|
11803
11777
|
if (tov.assocPaths) {
|
|
11804
|
-
tov = { ...tov };
|
|
11805
11778
|
if (!fromv.assocPaths) {
|
|
11806
11779
|
changes = true;
|
|
11807
11780
|
delete tov.assocPaths;
|
|
@@ -11824,7 +11797,6 @@ function mergeTypeState(blockStates, index, from, nodeCopyProp) {
|
|
|
11824
11797
|
delete tov.assocPaths;
|
|
11825
11798
|
}
|
|
11826
11799
|
}
|
|
11827
|
-
to.map.set(k, tov);
|
|
11828
11800
|
}
|
|
11829
11801
|
// if both from and to have copyPropEvents, we can only
|
|
11830
11802
|
// keep it if they're the same event.
|
|
@@ -11842,10 +11814,8 @@ function mergeTypeState(blockStates, index, from, nodeCopyProp) {
|
|
|
11842
11814
|
}
|
|
11843
11815
|
nodeCopyProp.set(fromv.copyPropItem.event.node, false);
|
|
11844
11816
|
}
|
|
11845
|
-
tov = { ...tov };
|
|
11846
11817
|
delete tov.copyPropItem;
|
|
11847
11818
|
changes = true;
|
|
11848
|
-
to.map.set(k, tov);
|
|
11849
11819
|
}
|
|
11850
11820
|
else {
|
|
11851
11821
|
external_node_assert_namespaceObject(k === tov.copyPropItem.event.decl);
|
|
@@ -11856,7 +11826,7 @@ function mergeTypeState(blockStates, index, from, nodeCopyProp) {
|
|
|
11856
11826
|
if (subtypeOf(fromv.curType, tov.curType))
|
|
11857
11827
|
return;
|
|
11858
11828
|
if (subtypeOf(tov.curType, fromv.curType)) {
|
|
11859
|
-
|
|
11829
|
+
tov.curType = fromv.curType;
|
|
11860
11830
|
changes = true;
|
|
11861
11831
|
return;
|
|
11862
11832
|
}
|
|
@@ -11869,7 +11839,7 @@ function mergeTypeState(blockStates, index, from, nodeCopyProp) {
|
|
|
11869
11839
|
if (wide)
|
|
11870
11840
|
result = wide;
|
|
11871
11841
|
}
|
|
11872
|
-
|
|
11842
|
+
tov.curType = result;
|
|
11873
11843
|
changes = true;
|
|
11874
11844
|
});
|
|
11875
11845
|
return changes;
|
|
@@ -11894,7 +11864,6 @@ function updateAffected(blockState, objectType, baseDecl, assignedPath, affected
|
|
|
11894
11864
|
let droppedComponents = null;
|
|
11895
11865
|
const entry = blockState.map.get(key);
|
|
11896
11866
|
external_node_assert_namespaceObject(entry && entry.assocPaths);
|
|
11897
|
-
let newEntry = entry;
|
|
11898
11867
|
entry.assocPaths.forEach((path) => {
|
|
11899
11868
|
if (key === baseDecl && path === assignedPath) {
|
|
11900
11869
|
return;
|
|
@@ -11913,12 +11882,9 @@ function updateAffected(blockState, objectType, baseDecl, assignedPath, affected
|
|
|
11913
11882
|
});
|
|
11914
11883
|
if (pathItem === affectedName && couldBeShallow(type, objectType)) {
|
|
11915
11884
|
const newAssocKey = assocPath.map((av) => av.name ?? "*").join(".");
|
|
11916
|
-
if (newEntry === entry) {
|
|
11917
|
-
newEntry = { ...entry };
|
|
11918
|
-
}
|
|
11919
11885
|
if (newAssocKey !== path) {
|
|
11920
|
-
|
|
11921
|
-
|
|
11886
|
+
entry.assocPaths = new Set(entry.assocPaths);
|
|
11887
|
+
entry.assocPaths.delete(path);
|
|
11922
11888
|
// the "extra" path components will also have entries
|
|
11923
11889
|
// in blockState.trackedMemberDecls. Since they're gone
|
|
11924
11890
|
// from here, we (may) need to remove them from there
|
|
@@ -11930,8 +11896,7 @@ function updateAffected(blockState, objectType, baseDecl, assignedPath, affected
|
|
|
11930
11896
|
}
|
|
11931
11897
|
break;
|
|
11932
11898
|
}
|
|
11933
|
-
|
|
11934
|
-
newEntry.curType = baseType;
|
|
11899
|
+
entry.curType = updateByAssocPath(assocPath, assignedType, true);
|
|
11935
11900
|
break;
|
|
11936
11901
|
}
|
|
11937
11902
|
if (pathItem === "*") {
|
|
@@ -11961,14 +11926,11 @@ function updateAffected(blockState, objectType, baseDecl, assignedPath, affected
|
|
|
11961
11926
|
}
|
|
11962
11927
|
}
|
|
11963
11928
|
});
|
|
11964
|
-
if (
|
|
11965
|
-
|
|
11966
|
-
|
|
11967
|
-
|
|
11968
|
-
|
|
11969
|
-
droppedComponents.forEach((pathComponent) => blockState.trackedMemberDecls.get(pathComponent).delete(key));
|
|
11970
|
-
}
|
|
11971
|
-
blockState.map.set(key, newEntry);
|
|
11929
|
+
if (droppedComponents) {
|
|
11930
|
+
entry.assocPaths.forEach((path) => path
|
|
11931
|
+
.split(".")
|
|
11932
|
+
.forEach((pathComponent) => droppedComponents.delete(pathComponent)));
|
|
11933
|
+
droppedComponents.forEach((pathComponent) => blockState.trackedMemberDecls.get(pathComponent).delete(key));
|
|
11972
11934
|
}
|
|
11973
11935
|
});
|
|
11974
11936
|
}
|
|
@@ -12075,10 +12037,9 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, copyPropStore
|
|
|
12075
12037
|
const assocKey = assocValue.map((av) => av.name ?? "*").join(".");
|
|
12076
12038
|
const newType = updateByAssocPath(assocValue, next, false);
|
|
12077
12039
|
setStateEvent(blockState, decl.base, newType, newValue ? 1 /* UpdateKind.Inner */ : 0 /* UpdateKind.None */);
|
|
12078
|
-
const tsv =
|
|
12040
|
+
const tsv = blockState.map.get(decl.base);
|
|
12079
12041
|
tsv.assocPaths = new Set(tsv.assocPaths);
|
|
12080
12042
|
tsv.assocPaths.add(assocKey);
|
|
12081
|
-
blockState.map.set(decl.base, tsv);
|
|
12082
12043
|
addTrackedMemberDecl(blockState, decl.base, assocKey);
|
|
12083
12044
|
if (newValue) {
|
|
12084
12045
|
const baseElem = assocValue[decl.path.length - 1];
|
|
@@ -12156,34 +12117,39 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, copyPropStore
|
|
|
12156
12117
|
// that foo is side-effect free, and accesses no globals.
|
|
12157
12118
|
clearRelatedCopyPropEvents(blockState, decl, nodeCopyProp);
|
|
12158
12119
|
}
|
|
12120
|
+
const v = blockState.map.get(decl);
|
|
12121
|
+
if (!v) {
|
|
12122
|
+
blockState.map.set(decl, { curType: value });
|
|
12123
|
+
return;
|
|
12124
|
+
}
|
|
12159
12125
|
if (updateKind !== 2 /* UpdateKind.Reassign */) {
|
|
12160
12126
|
/*
|
|
12161
12127
|
* If we're not re-assigning, the equivalencies don't
|
|
12162
12128
|
* change, so this update must be applied to every
|
|
12163
12129
|
* element of the set
|
|
12164
12130
|
*/
|
|
12165
|
-
|
|
12166
|
-
if (v?.equivSet) {
|
|
12131
|
+
if (v.equivSet) {
|
|
12167
12132
|
v.equivSet.forEach((s) => {
|
|
12168
12133
|
const next = blockState.map.get(s);
|
|
12169
12134
|
external_node_assert_namespaceObject(next && next.equivSet?.has(s));
|
|
12170
|
-
|
|
12135
|
+
next.curType = value;
|
|
12171
12136
|
});
|
|
12172
12137
|
}
|
|
12173
12138
|
else {
|
|
12174
|
-
|
|
12139
|
+
v.curType = value;
|
|
12175
12140
|
}
|
|
12176
12141
|
}
|
|
12177
12142
|
else {
|
|
12178
|
-
const v = blockState.map.get(decl);
|
|
12179
12143
|
removeEquiv(blockState.map, decl);
|
|
12180
|
-
if (v
|
|
12144
|
+
if (v.assocPaths?.size) {
|
|
12181
12145
|
clearAssocPaths(blockState, decl, v);
|
|
12146
|
+
delete v.assocPaths;
|
|
12182
12147
|
}
|
|
12183
|
-
if (v
|
|
12148
|
+
if (v.copyPropItem) {
|
|
12184
12149
|
copyPropFailed(blockState, v.copyPropItem, nodeCopyProp);
|
|
12150
|
+
delete v.copyPropItem;
|
|
12185
12151
|
}
|
|
12186
|
-
|
|
12152
|
+
v.curType = value;
|
|
12187
12153
|
}
|
|
12188
12154
|
return;
|
|
12189
12155
|
}
|
|
@@ -12517,7 +12483,7 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, copyPropStore
|
|
|
12517
12483
|
break;
|
|
12518
12484
|
}
|
|
12519
12485
|
case "ref": {
|
|
12520
|
-
|
|
12486
|
+
const curEntry = getStateEntry(curState, event.decl);
|
|
12521
12487
|
typeMap.set(event.node, curEntry.curType);
|
|
12522
12488
|
nodeEquivs.delete(event.node);
|
|
12523
12489
|
if (curEntry.equivSet) {
|
|
@@ -12541,9 +12507,7 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, copyPropStore
|
|
|
12541
12507
|
nodeCopyProp.set(curEntry.copyPropItem.event.node, event.node);
|
|
12542
12508
|
}
|
|
12543
12509
|
clearCopyProp(curState, curEntry.copyPropItem);
|
|
12544
|
-
curEntry = { ...curEntry };
|
|
12545
12510
|
delete curEntry.copyPropItem;
|
|
12546
|
-
curState.map.set(event.decl, curEntry);
|
|
12547
12511
|
}
|
|
12548
12512
|
else if (declIsNonLocal(event.decl)) {
|
|
12549
12513
|
clearRelatedCopyPropEvents(curState, null, nodeCopyProp);
|
|
@@ -12618,10 +12582,9 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, copyPropStore
|
|
|
12618
12582
|
setUnionComponent(type, 32768 /* TypeTag.Object */, newData);
|
|
12619
12583
|
if (tsv.assocPaths) {
|
|
12620
12584
|
clearAssocPaths(curState, decl, tsv);
|
|
12621
|
-
tsv = { ...tsv };
|
|
12622
12585
|
delete tsv.assocPaths;
|
|
12623
12586
|
}
|
|
12624
|
-
|
|
12587
|
+
tsv.curType = type;
|
|
12625
12588
|
}
|
|
12626
12589
|
}
|
|
12627
12590
|
clearRelatedCopyPropEvents(curState, decl, nodeCopyProp);
|
|
@@ -12646,10 +12609,7 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, copyPropStore
|
|
|
12646
12609
|
(event.node.type !== "AssignmentExpression" ||
|
|
12647
12610
|
event.node.operator !== "=")) {
|
|
12648
12611
|
copyPropFailed(curState, before.copyPropItem, nodeCopyProp);
|
|
12649
|
-
|
|
12650
|
-
delete v.copyPropItem;
|
|
12651
|
-
external_node_assert_namespaceObject(isTypeStateKey(event.decl));
|
|
12652
|
-
curState.map.set(event.decl, v);
|
|
12612
|
+
delete before.copyPropItem;
|
|
12653
12613
|
}
|
|
12654
12614
|
}
|
|
12655
12615
|
const expr = event.node.type === "VariableDeclarator"
|
|
@@ -13318,11 +13278,6 @@ function minimizeLocals(state, func) {
|
|
|
13318
13278
|
return null;
|
|
13319
13279
|
}
|
|
13320
13280
|
break;
|
|
13321
|
-
case "ExpressionStatement":
|
|
13322
|
-
if (node.expression.type === "Literal") {
|
|
13323
|
-
return false;
|
|
13324
|
-
}
|
|
13325
|
-
break;
|
|
13326
13281
|
case "UpdateExpression":
|
|
13327
13282
|
if (info) {
|
|
13328
13283
|
external_node_assert_namespaceObject(node.argument.type === "Identifier");
|
|
@@ -13343,7 +13298,7 @@ function minimizeLocals(state, func) {
|
|
|
13343
13298
|
}
|
|
13344
13299
|
// VariableDeclarations aren't allowed to have
|
|
13345
13300
|
// AssignmentExpressions in them, but we'll fix that
|
|
13346
|
-
//
|
|
13301
|
+
// via variableCleanup
|
|
13347
13302
|
return withLoc({
|
|
13348
13303
|
type: "AssignmentExpression",
|
|
13349
13304
|
operator: "=",
|
|
@@ -13356,79 +13311,92 @@ function minimizeLocals(state, func) {
|
|
|
13356
13311
|
}, node, node);
|
|
13357
13312
|
}
|
|
13358
13313
|
break;
|
|
13359
|
-
|
|
13360
|
-
|
|
13361
|
-
|
|
13362
|
-
|
|
13363
|
-
|
|
13364
|
-
|
|
13365
|
-
|
|
13366
|
-
|
|
13367
|
-
|
|
13368
|
-
|
|
13369
|
-
|
|
13370
|
-
|
|
13371
|
-
|
|
13372
|
-
|
|
13373
|
-
|
|
13374
|
-
|
|
13375
|
-
|
|
13376
|
-
|
|
13377
|
-
|
|
13378
|
-
}, decl, decl));
|
|
13379
|
-
}
|
|
13380
|
-
});
|
|
13381
|
-
node.declarations = node.declarations.filter((decl) => {
|
|
13382
|
-
if (decl.type === "VariableDeclarator") {
|
|
13383
|
-
delete decl.init;
|
|
13384
|
-
return true;
|
|
13385
|
-
}
|
|
13386
|
-
return false;
|
|
13387
|
-
});
|
|
13388
|
-
if (node.declarations.length) {
|
|
13389
|
-
withLocDeep(node, node, false);
|
|
13390
|
-
results.unshift(node);
|
|
13314
|
+
}
|
|
13315
|
+
external_node_assert_namespaceObject(!info);
|
|
13316
|
+
return variableCleanup(node);
|
|
13317
|
+
});
|
|
13318
|
+
return;
|
|
13319
|
+
}
|
|
13320
|
+
function variableCleanup(node) {
|
|
13321
|
+
switch (node.type) {
|
|
13322
|
+
case "ExpressionStatement":
|
|
13323
|
+
if (node.expression.type === "Literal") {
|
|
13324
|
+
return false;
|
|
13325
|
+
}
|
|
13326
|
+
break;
|
|
13327
|
+
case "VariableDeclaration":
|
|
13328
|
+
if (node.declarations.some((decl) => decl.type !== "VariableDeclarator")) {
|
|
13329
|
+
const results = [];
|
|
13330
|
+
node.declarations.forEach((decl) => {
|
|
13331
|
+
if (isStatement(decl)) {
|
|
13332
|
+
results.push(decl);
|
|
13391
13333
|
}
|
|
13392
|
-
|
|
13393
|
-
|
|
13394
|
-
// fix that below.
|
|
13395
|
-
return results;
|
|
13396
|
-
}
|
|
13397
|
-
break;
|
|
13398
|
-
case "ForStatement":
|
|
13399
|
-
if (node.init) {
|
|
13400
|
-
if (node.init.type === "BlockStatement") {
|
|
13401
|
-
const result = node.init;
|
|
13402
|
-
delete node.init;
|
|
13403
|
-
result.body.push(node);
|
|
13404
|
-
if (node.loc && result.loc) {
|
|
13405
|
-
// result has the range of the original VariableDeclaration
|
|
13406
|
-
// but now we're moving that ahead of the 'for', so to keep
|
|
13407
|
-
// things straight, we need to set the for's start to be
|
|
13408
|
-
// where result ended, and result's end to be where the for
|
|
13409
|
-
// ends (since that block now encloses the for)
|
|
13410
|
-
node.start = result.end;
|
|
13411
|
-
node.loc.start = result.loc.end;
|
|
13412
|
-
result.end = node.end;
|
|
13413
|
-
result.loc.end = node.loc.end;
|
|
13414
|
-
}
|
|
13415
|
-
return result;
|
|
13334
|
+
else if (isExpression(decl)) {
|
|
13335
|
+
results.push(withLoc({ type: "ExpressionStatement", expression: decl }, decl, decl));
|
|
13416
13336
|
}
|
|
13417
|
-
if (
|
|
13418
|
-
|
|
13337
|
+
else if (decl.init) {
|
|
13338
|
+
results.push(withLoc({
|
|
13339
|
+
type: "ExpressionStatement",
|
|
13340
|
+
expression: withLoc({
|
|
13341
|
+
type: "AssignmentExpression",
|
|
13342
|
+
operator: "=",
|
|
13343
|
+
left: withLoc({
|
|
13344
|
+
type: "Identifier",
|
|
13345
|
+
name: (0,external_api_cjs_namespaceObject.variableDeclarationName)(decl.id),
|
|
13346
|
+
}, decl.id, decl.id),
|
|
13347
|
+
right: decl.init,
|
|
13348
|
+
}, decl, decl),
|
|
13349
|
+
}, decl, decl));
|
|
13419
13350
|
}
|
|
13351
|
+
});
|
|
13352
|
+
node.declarations = node.declarations.filter((decl) => {
|
|
13353
|
+
if (decl.type === "VariableDeclarator") {
|
|
13354
|
+
delete decl.init;
|
|
13355
|
+
return true;
|
|
13356
|
+
}
|
|
13357
|
+
return false;
|
|
13358
|
+
});
|
|
13359
|
+
if (node.declarations.length) {
|
|
13360
|
+
withLocDeep(node, node, false);
|
|
13361
|
+
results.unshift(node);
|
|
13420
13362
|
}
|
|
13421
|
-
|
|
13422
|
-
|
|
13423
|
-
|
|
13424
|
-
|
|
13363
|
+
// if this was the init of a ForStatement, this will
|
|
13364
|
+
// replace its init with a BlockStatement, so we have to
|
|
13365
|
+
// fix that below.
|
|
13366
|
+
return results;
|
|
13367
|
+
}
|
|
13368
|
+
break;
|
|
13369
|
+
case "ForStatement":
|
|
13370
|
+
if (node.init) {
|
|
13371
|
+
if (node.init.type === "BlockStatement") {
|
|
13372
|
+
const result = node.init;
|
|
13373
|
+
delete node.init;
|
|
13374
|
+
result.body.push(node);
|
|
13375
|
+
if (node.loc && result.loc) {
|
|
13376
|
+
// result has the range of the original VariableDeclaration
|
|
13377
|
+
// but now we're moving that ahead of the 'for', so to keep
|
|
13378
|
+
// things straight, we need to set the for's start to be
|
|
13379
|
+
// where result ended, and result's end to be where the for
|
|
13380
|
+
// ends (since that block now encloses the for)
|
|
13381
|
+
node.start = result.end;
|
|
13382
|
+
node.loc.start = result.loc.end;
|
|
13383
|
+
result.end = node.end;
|
|
13384
|
+
result.loc.end = node.loc.end;
|
|
13385
|
+
}
|
|
13386
|
+
return result;
|
|
13425
13387
|
}
|
|
13426
|
-
|
|
13427
|
-
|
|
13428
|
-
|
|
13429
|
-
|
|
13430
|
-
|
|
13431
|
-
|
|
13388
|
+
if (node.init.type === "Literal") {
|
|
13389
|
+
delete node.init;
|
|
13390
|
+
}
|
|
13391
|
+
}
|
|
13392
|
+
break;
|
|
13393
|
+
case "SequenceExpression":
|
|
13394
|
+
if (node.expressions.some((e) => e.type === "Literal")) {
|
|
13395
|
+
node.expressions = node.expressions.filter((e) => e.type !== "Literal");
|
|
13396
|
+
}
|
|
13397
|
+
break;
|
|
13398
|
+
}
|
|
13399
|
+
return null;
|
|
13432
13400
|
}
|
|
13433
13401
|
|
|
13434
13402
|
;// CONCATENATED MODULE: ./src/pre.ts
|
|
@@ -14181,6 +14149,199 @@ function applyReplacements(func, nodeMap, declMap) {
|
|
|
14181
14149
|
});
|
|
14182
14150
|
}
|
|
14183
14151
|
|
|
14152
|
+
;// CONCATENATED MODULE: ./src/type-flow/minimize-modules.ts
|
|
14153
|
+
|
|
14154
|
+
|
|
14155
|
+
|
|
14156
|
+
function minimizeModules(ast, state) {
|
|
14157
|
+
const { pre, post } = state;
|
|
14158
|
+
try {
|
|
14159
|
+
const replacementMap = new Map();
|
|
14160
|
+
const conflictingNames = new Set();
|
|
14161
|
+
state.pre = (node) => {
|
|
14162
|
+
if (state.inType)
|
|
14163
|
+
return null;
|
|
14164
|
+
switch (node.type) {
|
|
14165
|
+
case "ModuleDeclaration":
|
|
14166
|
+
case "ClassDeclaration":
|
|
14167
|
+
case "FunctionDeclaration":
|
|
14168
|
+
return ["body"];
|
|
14169
|
+
case "Using":
|
|
14170
|
+
conflictingNames.add(node.as?.name ??
|
|
14171
|
+
(node.id.type === "Identifier"
|
|
14172
|
+
? node.id.name
|
|
14173
|
+
: node.id.property.name));
|
|
14174
|
+
return [];
|
|
14175
|
+
case "ImportModule":
|
|
14176
|
+
conflictingNames.add(node.id.type === "Identifier" ? node.id.name : node.id.property.name);
|
|
14177
|
+
return [];
|
|
14178
|
+
case "Identifier":
|
|
14179
|
+
case "MemberExpression": {
|
|
14180
|
+
let current = node;
|
|
14181
|
+
const parts = [];
|
|
14182
|
+
while (current.type === "MemberExpression" && !current.computed) {
|
|
14183
|
+
parts.unshift(current);
|
|
14184
|
+
current = current.object;
|
|
14185
|
+
}
|
|
14186
|
+
if (current.type !== "Identifier" &&
|
|
14187
|
+
current.type !== "ThisExpression") {
|
|
14188
|
+
break;
|
|
14189
|
+
}
|
|
14190
|
+
let toReplace = null;
|
|
14191
|
+
let module = null;
|
|
14192
|
+
let addImport = false;
|
|
14193
|
+
let [, results] = state.lookupValue(current, null);
|
|
14194
|
+
let i = 0;
|
|
14195
|
+
for (; results &&
|
|
14196
|
+
results.length === 1 &&
|
|
14197
|
+
results[0].results.length === 1 &&
|
|
14198
|
+
(results[0].results[0].type === "Program" ||
|
|
14199
|
+
results[0].results[0].type === "ClassDeclaration" ||
|
|
14200
|
+
results[0].results[0].type === "ModuleDeclaration"); i++) {
|
|
14201
|
+
if (current.type === "Identifier" &&
|
|
14202
|
+
results[0].results[0].type === "ModuleDeclaration" &&
|
|
14203
|
+
isImportCandidate(results[0].results[0])) {
|
|
14204
|
+
const directResults = i
|
|
14205
|
+
? state.lookupValue(current, null)
|
|
14206
|
+
: results;
|
|
14207
|
+
if (directResults &&
|
|
14208
|
+
directResults.length === 1 &&
|
|
14209
|
+
directResults[0].results.length === 1 &&
|
|
14210
|
+
directResults[0].results[0] === results[0].results[0]) {
|
|
14211
|
+
// we would find the same thing if we just looked up
|
|
14212
|
+
// current directly.
|
|
14213
|
+
toReplace = (i ? parts[i - 1] : current);
|
|
14214
|
+
module = results[0].results[0];
|
|
14215
|
+
if ((0,external_api_cjs_namespaceObject.findUsingForNode)(state, state.stack, state.stack.length - 1, current) === directResults[0].results[0]) {
|
|
14216
|
+
// we already find it via an import, so we don't need
|
|
14217
|
+
// a new import.
|
|
14218
|
+
addImport = false;
|
|
14219
|
+
}
|
|
14220
|
+
else {
|
|
14221
|
+
addImport = true;
|
|
14222
|
+
}
|
|
14223
|
+
}
|
|
14224
|
+
else {
|
|
14225
|
+
toReplace = parts[i - 1];
|
|
14226
|
+
module = results[0].results[0];
|
|
14227
|
+
addImport = true;
|
|
14228
|
+
}
|
|
14229
|
+
}
|
|
14230
|
+
if (i === parts.length)
|
|
14231
|
+
break;
|
|
14232
|
+
current = parts[i].property;
|
|
14233
|
+
results = (0,external_api_cjs_namespaceObject.lookupNext)(state, results, "decls", current);
|
|
14234
|
+
}
|
|
14235
|
+
if (toReplace) {
|
|
14236
|
+
external_node_assert_namespaceObject(module);
|
|
14237
|
+
replacementMap.set(toReplace, { module, addImport });
|
|
14238
|
+
}
|
|
14239
|
+
else if (parts.length === 0) {
|
|
14240
|
+
external_node_assert_namespaceObject(node.type === "Identifier");
|
|
14241
|
+
conflictingNames.add(node.name);
|
|
14242
|
+
}
|
|
14243
|
+
else if (parts[0].object.type === "Identifier") {
|
|
14244
|
+
conflictingNames.add(parts[0].object.name);
|
|
14245
|
+
}
|
|
14246
|
+
return [];
|
|
14247
|
+
}
|
|
14248
|
+
}
|
|
14249
|
+
return null;
|
|
14250
|
+
};
|
|
14251
|
+
(0,external_api_cjs_namespaceObject.collectNamespaces)(ast, state);
|
|
14252
|
+
const mappedNames = new Map();
|
|
14253
|
+
replacementMap.forEach((value, key) => {
|
|
14254
|
+
let name;
|
|
14255
|
+
if (value.addImport) {
|
|
14256
|
+
name = mappedNames.get(value.module);
|
|
14257
|
+
if (!name) {
|
|
14258
|
+
name = value.module.name;
|
|
14259
|
+
for (let i = 0; conflictingNames.has(name); i++) {
|
|
14260
|
+
name = `${value.module.name}_${i}`;
|
|
14261
|
+
}
|
|
14262
|
+
mappedNames.set(value.module, name);
|
|
14263
|
+
conflictingNames.add(name);
|
|
14264
|
+
}
|
|
14265
|
+
}
|
|
14266
|
+
else {
|
|
14267
|
+
name = key.type === "Identifier" ? key.name : key.property.name;
|
|
14268
|
+
}
|
|
14269
|
+
const original = (0,external_api_cjs_namespaceObject.formatAstLongLines)(key);
|
|
14270
|
+
const repl = key;
|
|
14271
|
+
repl.type = "Identifier";
|
|
14272
|
+
repl.name = name;
|
|
14273
|
+
if (name !== original) {
|
|
14274
|
+
repl.original = original;
|
|
14275
|
+
}
|
|
14276
|
+
delete repl.property;
|
|
14277
|
+
delete repl.object;
|
|
14278
|
+
delete repl.computed;
|
|
14279
|
+
});
|
|
14280
|
+
mappedNames.forEach((name, module) => {
|
|
14281
|
+
const id = makeScopedName(module.fullName.slice(2));
|
|
14282
|
+
const as = name !== (id.type === "Identifier" ? id : id.property).name &&
|
|
14283
|
+
makeIdentifier(name);
|
|
14284
|
+
const using = withLocDeep(as ? { type: "Using", id, as } : { type: "Using", id }, ast, false, true);
|
|
14285
|
+
ast.body.unshift(using);
|
|
14286
|
+
});
|
|
14287
|
+
}
|
|
14288
|
+
finally {
|
|
14289
|
+
state.pre = pre;
|
|
14290
|
+
state.post = post;
|
|
14291
|
+
}
|
|
14292
|
+
}
|
|
14293
|
+
/**
|
|
14294
|
+
* There's a bug in garmin's runtime (although the compiler could
|
|
14295
|
+
* work around it). See
|
|
14296
|
+
*
|
|
14297
|
+
* https://forums.garmin.com/developer/connect-iq/i/bug-reports/referencing-an-imported-module-doesn-t-run-its-parent-s-init
|
|
14298
|
+
*
|
|
14299
|
+
* What this means is that if a module's parent isn't `globals`
|
|
14300
|
+
* and it needs to be initialized, then we can't risk
|
|
14301
|
+
* importing it, because the parent module might not get initialized
|
|
14302
|
+
* in time.
|
|
14303
|
+
*/
|
|
14304
|
+
function isImportCandidate(module) {
|
|
14305
|
+
if (module.fullName.startsWith("$.Toybox."))
|
|
14306
|
+
return true;
|
|
14307
|
+
if (module.fullName.startsWith("$.Rez."))
|
|
14308
|
+
return false;
|
|
14309
|
+
external_node_assert_namespaceObject(module.stack);
|
|
14310
|
+
if (module.stack.length === 1)
|
|
14311
|
+
return true;
|
|
14312
|
+
return module.stack.every((elem) => {
|
|
14313
|
+
if (!elem.sn.decls)
|
|
14314
|
+
return false;
|
|
14315
|
+
if (elem.sn.type === "Program")
|
|
14316
|
+
return true;
|
|
14317
|
+
if (elem.sn.type !== "ModuleDeclaration")
|
|
14318
|
+
return false;
|
|
14319
|
+
return Object.values(elem.sn.decls).every((decls) => decls.every((decl) => {
|
|
14320
|
+
if (decl.type !== "VariableDeclarator")
|
|
14321
|
+
return true;
|
|
14322
|
+
if (!decl.node.init)
|
|
14323
|
+
return true;
|
|
14324
|
+
if (decl.node.init.type === "UnaryExpression" &&
|
|
14325
|
+
decl.node.init.operator === ":") {
|
|
14326
|
+
return true;
|
|
14327
|
+
}
|
|
14328
|
+
if (decl.node.init.type !== "Literal")
|
|
14329
|
+
return false;
|
|
14330
|
+
switch (typeof decl.node.init.value) {
|
|
14331
|
+
case "boolean":
|
|
14332
|
+
return true;
|
|
14333
|
+
case "bigint":
|
|
14334
|
+
return false;
|
|
14335
|
+
case "number":
|
|
14336
|
+
return !/[dl]$/i.test(decl.node.init.raw);
|
|
14337
|
+
case "object":
|
|
14338
|
+
return decl.node.init.value === null;
|
|
14339
|
+
}
|
|
14340
|
+
return false;
|
|
14341
|
+
}));
|
|
14342
|
+
});
|
|
14343
|
+
}
|
|
14344
|
+
|
|
14184
14345
|
;// CONCATENATED MODULE: ./src/type-flow/optimize.ts
|
|
14185
14346
|
|
|
14186
14347
|
|
|
@@ -15031,6 +15192,7 @@ function cleanupUnusedVars(state, node) {
|
|
|
15031
15192
|
|
|
15032
15193
|
|
|
15033
15194
|
|
|
15195
|
+
|
|
15034
15196
|
/*
|
|
15035
15197
|
* Map each name to the list of StateNodes that declare that
|
|
15036
15198
|
* name (excluding Functions, which are already in allFunctions)
|
|
@@ -15618,32 +15780,30 @@ async function optimizeMonkeyC(fnMap, resourcesMap, manifestXML, config) {
|
|
|
15618
15780
|
break;
|
|
15619
15781
|
case "Identifier": {
|
|
15620
15782
|
const map = topLocals().map;
|
|
15621
|
-
if (map) {
|
|
15622
|
-
|
|
15623
|
-
|
|
15624
|
-
|
|
15625
|
-
|
|
15783
|
+
if ((0,external_api_cjs_namespaceObject.hasProperty)(map, node.name)) {
|
|
15784
|
+
const name = map[node.name];
|
|
15785
|
+
if (typeof name === "string") {
|
|
15786
|
+
renameIdentifier(node, name);
|
|
15787
|
+
}
|
|
15788
|
+
const [, results] = state.lookupValue(node);
|
|
15789
|
+
if (results) {
|
|
15790
|
+
if (results.length !== 1 || results[0].results.length !== 1) {
|
|
15791
|
+
throw new Error(`Local ${node.name} had multiple lookup results`);
|
|
15626
15792
|
}
|
|
15627
|
-
const
|
|
15628
|
-
if (
|
|
15629
|
-
|
|
15630
|
-
|
|
15631
|
-
|
|
15632
|
-
|
|
15633
|
-
|
|
15634
|
-
|
|
15635
|
-
|
|
15636
|
-
|
|
15637
|
-
|
|
15638
|
-
|
|
15639
|
-
// we can't optimize away function or catch parameters
|
|
15640
|
-
return [];
|
|
15641
|
-
}
|
|
15642
|
-
if (parent.type !== "BlockStatement") {
|
|
15643
|
-
throw new Error(`Local ${node.name} was not declared at block scope(??)`);
|
|
15644
|
-
}
|
|
15645
|
-
decl.used = true;
|
|
15793
|
+
const parent = results[0].parent;
|
|
15794
|
+
if (!parent) {
|
|
15795
|
+
throw new Error(`Local ${node.name} had no parent`);
|
|
15796
|
+
}
|
|
15797
|
+
const decl = results[0].results[0];
|
|
15798
|
+
if (parent.type === "FunctionDeclaration" ||
|
|
15799
|
+
decl.type !== "VariableDeclarator") {
|
|
15800
|
+
// we can't optimize away function or catch parameters
|
|
15801
|
+
return [];
|
|
15802
|
+
}
|
|
15803
|
+
if (parent.type !== "BlockStatement") {
|
|
15804
|
+
throw new Error(`Local ${node.name} was not declared at block scope(??)`);
|
|
15646
15805
|
}
|
|
15806
|
+
decl.used = true;
|
|
15647
15807
|
}
|
|
15648
15808
|
}
|
|
15649
15809
|
return [];
|
|
@@ -15931,6 +16091,11 @@ async function optimizeMonkeyC(fnMap, resourcesMap, manifestXML, config) {
|
|
|
15931
16091
|
state.nextExposed = {};
|
|
15932
16092
|
delete state.pre;
|
|
15933
16093
|
delete state.post;
|
|
16094
|
+
if (state.config?.minimizeModules ?? true) {
|
|
16095
|
+
Object.values(fnMap).forEach((f) => {
|
|
16096
|
+
minimizeModules(f.ast, state);
|
|
16097
|
+
});
|
|
16098
|
+
}
|
|
15934
16099
|
Object.values(state.allFunctions).forEach((fns) => fns.forEach((fn) => sizeBasedPRE(state, fn)));
|
|
15935
16100
|
const cleanup = (node) => {
|
|
15936
16101
|
switch (node.type) {
|
|
@@ -16576,6 +16741,7 @@ const configOptionsToCheck = [
|
|
|
16576
16741
|
"propagateTypes",
|
|
16577
16742
|
"singleUseCopyProp",
|
|
16578
16743
|
"minimizeLocals",
|
|
16744
|
+
"minimizeModules",
|
|
16579
16745
|
"extensionVersion",
|
|
16580
16746
|
"typeCheckLevel",
|
|
16581
16747
|
"covarianceWarnings",
|
|
@@ -16637,7 +16803,7 @@ async function generateOneConfig(buildConfig, manifestXML, dependencyFiles, conf
|
|
|
16637
16803
|
// the oldest optimized file, we don't need to regenerate
|
|
16638
16804
|
const source_time = await (0,external_util_cjs_namespaceObject.last_modified)(Object.keys(fnMap).concat(dependencyFiles));
|
|
16639
16805
|
const opt_time = await (0,external_util_cjs_namespaceObject.first_modified)(Object.values(fnMap).map((v) => v.output));
|
|
16640
|
-
if (source_time < opt_time &&
|
|
16806
|
+
if (source_time < opt_time && 1676335488374 < opt_time) {
|
|
16641
16807
|
return { hasTests, diagnostics: prevDiagnostics };
|
|
16642
16808
|
}
|
|
16643
16809
|
}
|
|
@@ -16664,7 +16830,7 @@ async function generateOneConfig(buildConfig, manifestXML, dependencyFiles, conf
|
|
|
16664
16830
|
return promises_namespaceObject.writeFile(external_path_.join(output, "build-info.json"), JSON.stringify({
|
|
16665
16831
|
hasTests,
|
|
16666
16832
|
diagnostics,
|
|
16667
|
-
optimizerVersion: "1.1.
|
|
16833
|
+
optimizerVersion: "1.1.13",
|
|
16668
16834
|
...Object.fromEntries(configOptionsToCheck.map((option) => [option, config[option]])),
|
|
16669
16835
|
}))
|
|
16670
16836
|
.then(() => ({ hasTests, diagnostics }));
|