@markw65/monkeyc-optimizer 1.1.9 → 1.1.11
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 +26 -0
- package/build/api.cjs +1402 -462
- package/build/optimizer.cjs +4492 -3580
- package/build/src/api.d.ts +1 -0
- package/build/src/control-flow.d.ts +1 -1
- package/build/src/data-flow.d.ts +5 -3
- package/build/src/inliner.d.ts +2 -0
- package/build/src/optimizer-types.d.ts +2 -0
- package/build/src/optimizer.d.ts +1 -0
- package/build/src/type-flow/could-be.d.ts +2 -0
- package/build/src/type-flow/dead-store.d.ts +10 -2
- package/build/src/type-flow/interp-call.d.ts +1 -1
- package/build/src/type-flow/type-flow-util.d.ts +12 -1
- package/build/src/type-flow/types.d.ts +1 -1
- package/build/src/type-flow.d.ts +3 -10
- package/build/src/variable-renamer.d.ts +2 -0
- package/package.json +2 -2
package/build/api.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
0 && (module.exports = {checkCompilerVersion,collectNamespaces,createDocumentationMap,diagnostic,diagnosticHelper,findNamesInScope,findUsingForNode,formatAst,formatAstLongLines,getApiFunctionInfo,getApiMapping,getSuperClasses,hasProperty,isLocal,isLookupCandidate,isStateNode,lookupByFullName,lookupNext,lookupResultContains,lookupWithType,makeToyboxLink,mapVarDeclsByType,markInvokeClassMethod,parseSdkVersion,sameLookupResult,traverseAst,variableDeclarationName,visitReferences,visit_resources,visitorNode});
|
|
1
|
+
0 && (module.exports = {checkCompilerVersion,collectNamespaces,createDocumentationMap,diagnostic,diagnosticHelper,findNamesInScope,findUsingForNode,formatAst,formatAstLongLines,getApiFunctionInfo,getApiMapping,getSuperClasses,hasProperty,isClassVariable,isLocal,isLookupCandidate,isStateNode,lookupByFullName,lookupNext,lookupResultContains,lookupWithType,makeToyboxLink,mapVarDeclsByType,markInvokeClassMethod,parseSdkVersion,sameLookupResult,traverseAst,variableDeclarationName,visitReferences,visit_resources,visitorNode});
|
|
2
2
|
/******/ (() => { // webpackBootstrap
|
|
3
3
|
/******/ var __webpack_modules__ = ({
|
|
4
4
|
|
|
@@ -619,7 +619,7 @@ class LocalState {
|
|
|
619
619
|
this.unreachable = true;
|
|
620
620
|
}
|
|
621
621
|
}
|
|
622
|
-
function buildReducedGraph(state, func, notice) {
|
|
622
|
+
function buildReducedGraph(state, func, refsForUpdate, notice) {
|
|
623
623
|
const { stack, pre, post } = state;
|
|
624
624
|
try {
|
|
625
625
|
const localState = new LocalState(func.node);
|
|
@@ -627,8 +627,11 @@ function buildReducedGraph(state, func, notice) {
|
|
|
627
627
|
state.stack = [...func.stack];
|
|
628
628
|
const stmtStack = [func.node];
|
|
629
629
|
const testStack = [{ node: func.node }];
|
|
630
|
+
const allEvents = [];
|
|
631
|
+
const eventsStack = [];
|
|
630
632
|
let tryActive = 0;
|
|
631
633
|
state.pre = (node) => {
|
|
634
|
+
eventsStack.push(allEvents.length);
|
|
632
635
|
if (state.inType || localState.unreachable) {
|
|
633
636
|
return [];
|
|
634
637
|
}
|
|
@@ -954,6 +957,12 @@ function buildReducedGraph(state, func, notice) {
|
|
|
954
957
|
}
|
|
955
958
|
return [];
|
|
956
959
|
case "AssignmentExpression":
|
|
960
|
+
if (refsForUpdate && node.operator !== "=") {
|
|
961
|
+
// if its an update, we need to see a "ref"
|
|
962
|
+
// of the lhs, then whatever happens on the rhs,
|
|
963
|
+
// and then the assignment itself
|
|
964
|
+
return null;
|
|
965
|
+
}
|
|
957
966
|
if (node.left.type === "MemberExpression") {
|
|
958
967
|
state.traverse(node.left.object);
|
|
959
968
|
if (node.left.computed) {
|
|
@@ -983,6 +992,7 @@ function buildReducedGraph(state, func, notice) {
|
|
|
983
992
|
return null;
|
|
984
993
|
};
|
|
985
994
|
const addEvent = (block, event) => {
|
|
995
|
+
allEvents.push(event);
|
|
986
996
|
if (!block.events) {
|
|
987
997
|
block.events = [event];
|
|
988
998
|
}
|
|
@@ -991,11 +1001,13 @@ function buildReducedGraph(state, func, notice) {
|
|
|
991
1001
|
}
|
|
992
1002
|
};
|
|
993
1003
|
state.post = (node) => {
|
|
1004
|
+
const eventIndex = eventsStack.pop();
|
|
1005
|
+
const getContainedEvents = () => allEvents.slice(eventIndex);
|
|
994
1006
|
const curStmt = stmtStack[stmtStack.length - 1];
|
|
995
1007
|
const topTest = testStack[testStack.length - 1];
|
|
996
1008
|
if (!state.inType) {
|
|
997
1009
|
const throws = tryActive > 0 && mayThrow(node);
|
|
998
|
-
const events = notice(node, curStmt, throws);
|
|
1010
|
+
const events = notice(node, curStmt, throws, getContainedEvents);
|
|
999
1011
|
if (throws) {
|
|
1000
1012
|
if (!events) {
|
|
1001
1013
|
throw new Error("mayThrow expression in try/catch must generate an event");
|
|
@@ -1042,7 +1054,7 @@ function buildReducedGraph(state, func, notice) {
|
|
|
1042
1054
|
throw new Error("Internal error: Unexpected successor edges");
|
|
1043
1055
|
}
|
|
1044
1056
|
localState.addEdge(localState.curBlock, topTest.false);
|
|
1045
|
-
const event = notice(node, curStmt, 1);
|
|
1057
|
+
const event = notice(node, curStmt, 1, getContainedEvents);
|
|
1046
1058
|
if (event) {
|
|
1047
1059
|
if (Array.isArray(event)) {
|
|
1048
1060
|
throw new Error(`Unexpected array of flw events`);
|
|
@@ -1183,8 +1195,10 @@ function getPreOrder(head) {
|
|
|
1183
1195
|
/* harmony import */ var _ast__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(6652);
|
|
1184
1196
|
/* harmony import */ var _control_flow__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(5101);
|
|
1185
1197
|
/* harmony import */ var _function_info__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(819);
|
|
1186
|
-
/* harmony import */ var
|
|
1187
|
-
/* harmony import */ var
|
|
1198
|
+
/* harmony import */ var _type_flow_type_flow_util__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(1638);
|
|
1199
|
+
/* harmony import */ var _util__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(6906);
|
|
1200
|
+
/* harmony import */ var _util__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(_util__WEBPACK_IMPORTED_MODULE_6__);
|
|
1201
|
+
|
|
1188
1202
|
|
|
1189
1203
|
|
|
1190
1204
|
|
|
@@ -1349,7 +1363,7 @@ function buildDataFlowGraph(state, func, wantsLiteral, trackInsertionPoints, wan
|
|
|
1349
1363
|
};
|
|
1350
1364
|
return {
|
|
1351
1365
|
identifiers,
|
|
1352
|
-
graph: buildReducedGraph(state, func, (node, stmt, mayThrow) => {
|
|
1366
|
+
graph: buildReducedGraph(state, func, wantsAllRefs, (node, stmt, mayThrow, getContainedEvents) => {
|
|
1353
1367
|
if (mayThrow === 1) {
|
|
1354
1368
|
return wantsAllRefs ? getFlowEvent(node, stmt, findDecl) : null;
|
|
1355
1369
|
}
|
|
@@ -1473,6 +1487,12 @@ function buildDataFlowGraph(state, func, wantsLiteral, trackInsertionPoints, wan
|
|
|
1473
1487
|
if (rhs)
|
|
1474
1488
|
def.rhs = rhs;
|
|
1475
1489
|
}
|
|
1490
|
+
if (declIsLocal(decl)) {
|
|
1491
|
+
const contained = getContainedEvents().filter((e) => e.type === "ref" || e.type === "mod");
|
|
1492
|
+
if (contained.length) {
|
|
1493
|
+
def.containedEvents = contained;
|
|
1494
|
+
}
|
|
1495
|
+
}
|
|
1476
1496
|
return def;
|
|
1477
1497
|
}
|
|
1478
1498
|
break;
|
|
@@ -1487,13 +1507,19 @@ function buildDataFlowGraph(state, func, wantsLiteral, trackInsertionPoints, wan
|
|
|
1487
1507
|
decl,
|
|
1488
1508
|
mayThrow,
|
|
1489
1509
|
};
|
|
1490
|
-
if (wantsAllRefs &&
|
|
1491
|
-
node.
|
|
1492
|
-
|
|
1493
|
-
node.right
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1510
|
+
if (wantsAllRefs && node.operator === "=") {
|
|
1511
|
+
if (node.right.type === "Identifier" ||
|
|
1512
|
+
node.right.type === "MemberExpression") {
|
|
1513
|
+
const rhs = findDecl(node.right);
|
|
1514
|
+
if (rhs)
|
|
1515
|
+
def.rhs = rhs;
|
|
1516
|
+
}
|
|
1517
|
+
if (declIsLocal(decl)) {
|
|
1518
|
+
const contained = getContainedEvents().filter((e) => e.type === "ref" || e.type === "mod");
|
|
1519
|
+
if (contained.length) {
|
|
1520
|
+
def.containedEvents = contained;
|
|
1521
|
+
}
|
|
1522
|
+
}
|
|
1497
1523
|
}
|
|
1498
1524
|
return def;
|
|
1499
1525
|
}
|
|
@@ -1546,6 +1572,12 @@ function buildDataFlowGraph(state, func, wantsLiteral, trackInsertionPoints, wan
|
|
|
1546
1572
|
mod.calleeObj = calleeDecl.base;
|
|
1547
1573
|
}
|
|
1548
1574
|
}
|
|
1575
|
+
else if (node.callee.type === "MemberExpression") {
|
|
1576
|
+
const calleeObj = findDecl(node.callee.object);
|
|
1577
|
+
if (calleeObj) {
|
|
1578
|
+
mod.calleeObj = calleeObj;
|
|
1579
|
+
}
|
|
1580
|
+
}
|
|
1549
1581
|
return mod;
|
|
1550
1582
|
}
|
|
1551
1583
|
}
|
|
@@ -1846,7 +1878,7 @@ function findCalleesByNode(state, callee) {
|
|
|
1846
1878
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
1847
1879
|
|
|
1848
1880
|
"use strict";
|
|
1849
|
-
/* unused harmony exports inlinableSubExpression, shouldInline, unused, inlineFunction, applyTypeIfNeeded */
|
|
1881
|
+
/* unused harmony exports inlinableSubExpression, inlineRequested, shouldInline, unused, inlineDiagnostic, inlineFunction, applyTypeIfNeeded */
|
|
1850
1882
|
/* harmony import */ var _api__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6817);
|
|
1851
1883
|
/* harmony import */ var _api__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_api__WEBPACK_IMPORTED_MODULE_0__);
|
|
1852
1884
|
/* harmony import */ var _ast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6652);
|
|
@@ -2533,16 +2565,18 @@ function updateLocationForInline(node, original, context, func) {
|
|
|
2533
2565
|
throw new Error("Internal error: Inlined call had no location info");
|
|
2534
2566
|
}
|
|
2535
2567
|
traverseAst(node, (node) => {
|
|
2536
|
-
if (node.loc
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
if (
|
|
2541
|
-
node.origins
|
|
2568
|
+
if (!node.loc ||
|
|
2569
|
+
node.loc.source !== loc.source ||
|
|
2570
|
+
node.loc.start.offset > loc.end.offset ||
|
|
2571
|
+
node.loc.end.offset <= loc.start.offset) {
|
|
2572
|
+
if (node.loc) {
|
|
2573
|
+
if (!node.origins) {
|
|
2574
|
+
node.origins = [];
|
|
2575
|
+
}
|
|
2576
|
+
node.origins.unshift({ loc: node.loc, func: func.fullName });
|
|
2542
2577
|
}
|
|
2543
|
-
|
|
2578
|
+
withLoc(node, context, context === original ? context : false);
|
|
2544
2579
|
}
|
|
2545
|
-
withLoc(node, context, context === original ? context : false);
|
|
2546
2580
|
});
|
|
2547
2581
|
return node;
|
|
2548
2582
|
}
|
|
@@ -2570,8 +2604,8 @@ function inlineFunction(state, func, call, context) {
|
|
|
2570
2604
|
const ret = inlineFunctionHelper(state, func, call, context);
|
|
2571
2605
|
if (!ret)
|
|
2572
2606
|
return ret;
|
|
2573
|
-
const
|
|
2574
|
-
if (!
|
|
2607
|
+
const typecheckAttrs = func.node.attrs?.attributes?.elements.filter((attr) => isTypecheckArg(attr, null));
|
|
2608
|
+
if (!typecheckAttrs || !typecheckAttrs.length) {
|
|
2575
2609
|
return ret;
|
|
2576
2610
|
}
|
|
2577
2611
|
const callerElem = state.stack.find((elem) => elem.sn.type === "FunctionDeclaration");
|
|
@@ -2580,6 +2614,9 @@ function inlineFunction(state, func, call, context) {
|
|
|
2580
2614
|
}
|
|
2581
2615
|
const callerSn = callerElem.sn;
|
|
2582
2616
|
const caller = callerSn.node;
|
|
2617
|
+
if (caller.attrs?.attributes?.elements.find((attr) => isTypecheckArg(attr, null))) {
|
|
2618
|
+
return ret;
|
|
2619
|
+
}
|
|
2583
2620
|
if (!caller.attrs) {
|
|
2584
2621
|
caller.attrs = withLoc({
|
|
2585
2622
|
type: "AttributeList",
|
|
@@ -2588,10 +2625,7 @@ function inlineFunction(state, func, call, context) {
|
|
|
2588
2625
|
if (!caller.attrs.attributes) {
|
|
2589
2626
|
caller.attrs.attributes = withLoc({ type: "Attributes", elements: [] }, caller.attrs, false);
|
|
2590
2627
|
}
|
|
2591
|
-
|
|
2592
|
-
return ret;
|
|
2593
|
-
}
|
|
2594
|
-
caller.attrs.attributes.elements.unshift(withLocDeep({ ...typecheckFalse }, caller.attrs, false));
|
|
2628
|
+
caller.attrs.attributes.elements.unshift(...typecheckAttrs.map((typecheck) => withLocDeep({ ...typecheck }, caller.attrs, false)));
|
|
2595
2629
|
return ret;
|
|
2596
2630
|
}
|
|
2597
2631
|
function applyTypeIfNeeded(node) {
|
|
@@ -2725,10 +2759,12 @@ function fixNodeScope(state, lookupNode, nodeStack) {
|
|
|
2725
2759
|
/* harmony import */ var _type_flow_interp__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(7161);
|
|
2726
2760
|
/* harmony import */ var _type_flow_optimize__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(3687);
|
|
2727
2761
|
/* harmony import */ var _type_flow_sub_type__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(9234);
|
|
2728
|
-
/* harmony import */ var
|
|
2729
|
-
/* harmony import */ var
|
|
2730
|
-
/* harmony import */ var
|
|
2731
|
-
/* harmony import */ var
|
|
2762
|
+
/* harmony import */ var _type_flow_types__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(7255);
|
|
2763
|
+
/* harmony import */ var _unused_exprs__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(424);
|
|
2764
|
+
/* harmony import */ var _util__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(6906);
|
|
2765
|
+
/* harmony import */ var _util__WEBPACK_IMPORTED_MODULE_16___default = /*#__PURE__*/__webpack_require__.n(_util__WEBPACK_IMPORTED_MODULE_16__);
|
|
2766
|
+
/* harmony import */ var _variable_renamer__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(4405);
|
|
2767
|
+
|
|
2732
2768
|
|
|
2733
2769
|
|
|
2734
2770
|
|
|
@@ -3175,12 +3211,19 @@ async function optimizeMonkeyC(fnMap, resourcesMap, manifestXML, config) {
|
|
|
3175
3211
|
state.localsStack = [{}];
|
|
3176
3212
|
state.calledFunctions = {};
|
|
3177
3213
|
state.usedByName = {};
|
|
3214
|
+
const checkLookupRules = config.checkCompilerLookupRules;
|
|
3215
|
+
config.checkCompilerLookupRules = "OFF";
|
|
3178
3216
|
let again = false;
|
|
3179
3217
|
const optimizeCallHelper = (istate, call, node) => {
|
|
3180
3218
|
const result = optimizeCall(istate, call, node);
|
|
3181
3219
|
if (result) {
|
|
3182
3220
|
if (isExpression(result)) {
|
|
3183
|
-
istate.stack[istate.stack.length - 1]
|
|
3221
|
+
const elem = istate.stack[istate.stack.length - 1];
|
|
3222
|
+
elem.node = result;
|
|
3223
|
+
if (result.type === "Literal") {
|
|
3224
|
+
elem.value = typeFromLiteral(result);
|
|
3225
|
+
elem.embeddedEffects = false;
|
|
3226
|
+
}
|
|
3184
3227
|
}
|
|
3185
3228
|
again = true;
|
|
3186
3229
|
}
|
|
@@ -3270,7 +3313,7 @@ async function optimizeMonkeyC(fnMap, resourcesMap, manifestXML, config) {
|
|
|
3270
3313
|
throw new Error(`While renaming ${declName} to ${name}: Didn't find original declaration`);
|
|
3271
3314
|
}
|
|
3272
3315
|
}
|
|
3273
|
-
ident
|
|
3316
|
+
renameIdentifier(ident, name);
|
|
3274
3317
|
}
|
|
3275
3318
|
else {
|
|
3276
3319
|
map[declName] = true;
|
|
@@ -3330,7 +3373,7 @@ async function optimizeMonkeyC(fnMap, resourcesMap, manifestXML, config) {
|
|
|
3330
3373
|
if (hasProperty(map, node.name)) {
|
|
3331
3374
|
const name = map[node.name];
|
|
3332
3375
|
if (typeof name === "string") {
|
|
3333
|
-
node
|
|
3376
|
+
renameIdentifier(node, name);
|
|
3334
3377
|
}
|
|
3335
3378
|
const [, results] = state.lookupValue(node);
|
|
3336
3379
|
if (results) {
|
|
@@ -3365,7 +3408,7 @@ async function optimizeMonkeyC(fnMap, resourcesMap, manifestXML, config) {
|
|
|
3365
3408
|
if (hasProperty(map, lhs.name)) {
|
|
3366
3409
|
const name = map[lhs.name];
|
|
3367
3410
|
if (typeof name === "string") {
|
|
3368
|
-
lhs
|
|
3411
|
+
renameIdentifier(lhs, name);
|
|
3369
3412
|
}
|
|
3370
3413
|
}
|
|
3371
3414
|
}
|
|
@@ -3529,9 +3572,14 @@ async function optimizeMonkeyC(fnMap, resourcesMap, manifestXML, config) {
|
|
|
3529
3572
|
}
|
|
3530
3573
|
case "VariableDeclaration": {
|
|
3531
3574
|
const locals = topLocals();
|
|
3532
|
-
if (locals.map
|
|
3533
|
-
|
|
3534
|
-
|
|
3575
|
+
if (!locals.map) {
|
|
3576
|
+
if (again) {
|
|
3577
|
+
again = false;
|
|
3578
|
+
state.traverse(node);
|
|
3579
|
+
}
|
|
3580
|
+
break;
|
|
3581
|
+
}
|
|
3582
|
+
if (locals.node && locals.node.type === "BlockStatement") {
|
|
3535
3583
|
let results;
|
|
3536
3584
|
const declarations = node.declarations;
|
|
3537
3585
|
let i = 0;
|
|
@@ -3737,6 +3785,7 @@ async function optimizeMonkeyC(fnMap, resourcesMap, manifestXML, config) {
|
|
|
3737
3785
|
return ret;
|
|
3738
3786
|
});
|
|
3739
3787
|
});
|
|
3788
|
+
config.checkCompilerLookupRules = checkLookupRules;
|
|
3740
3789
|
reportMissingSymbols(state, config);
|
|
3741
3790
|
if (state.inlineDiagnostics) {
|
|
3742
3791
|
if (!state.diagnostics) {
|
|
@@ -3799,6 +3848,7 @@ function optimizeCall(istate, node, context) {
|
|
|
3799
3848
|
node.arguments.every((n) => getNodeValue(n)[0] !== null)) {
|
|
3800
3849
|
const ret = evaluateFunction(istate, callee, node.arguments);
|
|
3801
3850
|
if (ret) {
|
|
3851
|
+
inlineDiagnostic(state, callees[0], node, null);
|
|
3802
3852
|
return withLoc(ret, node, node);
|
|
3803
3853
|
}
|
|
3804
3854
|
}
|
|
@@ -3957,7 +4007,9 @@ function pragmaChecker(state, ast, diagnostics) {
|
|
|
3957
4007
|
if (quote === '"') {
|
|
3958
4008
|
return haystack.includes(needle);
|
|
3959
4009
|
}
|
|
3960
|
-
const re = new RegExp(needle.replace(/@([-\d.\w]+|"[^"]*")/g, (_match, pat) => `(?:${pat}|pre_${pat
|
|
4010
|
+
const re = new RegExp(needle.replace(/@([-\d.\w]+|"[^"]*")/g, (_match, pat) => `(?:${pat}|pre_${pat
|
|
4011
|
+
.replace(/^([a-zA-Z_]+\.)*/, "")
|
|
4012
|
+
.replace(/\W/g, "_")}(?:_\\d+)?)`));
|
|
3961
4013
|
return re.test(haystack);
|
|
3962
4014
|
};
|
|
3963
4015
|
next();
|
|
@@ -4154,7 +4206,9 @@ function sizeBasedPRE(state, func) {
|
|
|
4154
4206
|
applyReplacements(func.node, nodeMap, declMap);
|
|
4155
4207
|
func.node.body.body.unshift(variableDecl);
|
|
4156
4208
|
}
|
|
4157
|
-
|
|
4209
|
+
if (state.config?.minimizeLocals ?? true) {
|
|
4210
|
+
minimizeLocals(state, func);
|
|
4211
|
+
}
|
|
4158
4212
|
}
|
|
4159
4213
|
function buildPREGraph(state, func) {
|
|
4160
4214
|
const result = buildDataFlowGraph(state, func, (literal) => refCost(literal) > LocalRefCost, true, false);
|
|
@@ -4302,11 +4356,12 @@ const LocalRefCost = 2;
|
|
|
4302
4356
|
function refCost(node) {
|
|
4303
4357
|
if (node.type === "Literal") {
|
|
4304
4358
|
switch (typeof node.value) {
|
|
4359
|
+
case "bigint":
|
|
4360
|
+
return 9;
|
|
4305
4361
|
case "string":
|
|
4306
4362
|
return 5;
|
|
4307
|
-
case "bigint":
|
|
4308
4363
|
case "number":
|
|
4309
|
-
return 5;
|
|
4364
|
+
return node.raw.match(/d/i) ? 9 : 5;
|
|
4310
4365
|
case "boolean":
|
|
4311
4366
|
return 2;
|
|
4312
4367
|
default:
|
|
@@ -4802,26 +4857,32 @@ function applyReplacements(func, nodeMap, declMap) {
|
|
|
4802
4857
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
4803
4858
|
|
|
4804
4859
|
"use strict";
|
|
4805
|
-
/* harmony
|
|
4806
|
-
/* harmony
|
|
4807
|
-
/* harmony
|
|
4808
|
-
/*
|
|
4809
|
-
/* harmony import */ var
|
|
4810
|
-
/* harmony import */ var
|
|
4811
|
-
/* harmony import */ var
|
|
4812
|
-
/* harmony import */ var
|
|
4813
|
-
/* harmony import */ var
|
|
4814
|
-
/* harmony import */ var
|
|
4815
|
-
/* harmony import */ var
|
|
4816
|
-
/* harmony import */ var
|
|
4817
|
-
/* harmony import */ var
|
|
4818
|
-
/* harmony import */ var
|
|
4819
|
-
/* harmony import */ var
|
|
4820
|
-
/* harmony import */ var
|
|
4821
|
-
/* harmony import */ var
|
|
4822
|
-
/* harmony import */ var
|
|
4823
|
-
/* harmony import */ var
|
|
4824
|
-
/* harmony import */ var
|
|
4860
|
+
/* unused harmony exports missingNullWorkaround, buildTypeInfo, buildConflictGraph */
|
|
4861
|
+
/* harmony import */ var node_assert__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4143);
|
|
4862
|
+
/* harmony import */ var node_assert__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(node_assert__WEBPACK_IMPORTED_MODULE_0__);
|
|
4863
|
+
/* harmony import */ var _api__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6817);
|
|
4864
|
+
/* harmony import */ var _api__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_api__WEBPACK_IMPORTED_MODULE_1__);
|
|
4865
|
+
/* harmony import */ var _ast__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(6652);
|
|
4866
|
+
/* harmony import */ var _control_flow__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(5101);
|
|
4867
|
+
/* harmony import */ var _data_flow__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(8180);
|
|
4868
|
+
/* harmony import */ var _function_info__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(819);
|
|
4869
|
+
/* harmony import */ var _inliner__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(333);
|
|
4870
|
+
/* harmony import */ var _optimizer_types__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(9697);
|
|
4871
|
+
/* harmony import */ var _type_flow_could_be__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(4055);
|
|
4872
|
+
/* harmony import */ var _type_flow_dead_store__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(8486);
|
|
4873
|
+
/* harmony import */ var _type_flow_interp__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(7161);
|
|
4874
|
+
/* harmony import */ var _type_flow_interp_call__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(2222);
|
|
4875
|
+
/* harmony import */ var _type_flow_intersection_type__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(6973);
|
|
4876
|
+
/* harmony import */ var _type_flow_sub_type__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(9234);
|
|
4877
|
+
/* harmony import */ var _type_flow_type_flow_util__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(1638);
|
|
4878
|
+
/* harmony import */ var _type_flow_types__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(7255);
|
|
4879
|
+
/* harmony import */ var _type_flow_union_type__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(757);
|
|
4880
|
+
/* harmony import */ var _util__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(6906);
|
|
4881
|
+
/* harmony import */ var _util__WEBPACK_IMPORTED_MODULE_17___default = /*#__PURE__*/__webpack_require__.n(_util__WEBPACK_IMPORTED_MODULE_17__);
|
|
4882
|
+
|
|
4883
|
+
|
|
4884
|
+
|
|
4885
|
+
|
|
4825
4886
|
|
|
4826
4887
|
|
|
4827
4888
|
|
|
@@ -4857,15 +4918,24 @@ function buildTypeInfo(state, func, optimizeEquivalencies) {
|
|
|
4857
4918
|
const logThisRun = logging && loggingEnabledFor("TYPEFLOW_FUNC", func);
|
|
4858
4919
|
while (true) {
|
|
4859
4920
|
const { graph } = buildDataFlowGraph(state, func, () => false, false, true);
|
|
4860
|
-
|
|
4861
|
-
|
|
4862
|
-
|
|
4863
|
-
|
|
4864
|
-
|
|
4865
|
-
|
|
4866
|
-
|
|
4921
|
+
let copyPropStores;
|
|
4922
|
+
if (optimizeEquivalencies) {
|
|
4923
|
+
const result = eliminateDeadStores(state, func, graph, logThisRun);
|
|
4924
|
+
if (result.changes) {
|
|
4925
|
+
/*
|
|
4926
|
+
* eliminateDeadStores can change the control flow graph,
|
|
4927
|
+
* so we need to recompute it if it did anything.
|
|
4928
|
+
*/
|
|
4929
|
+
continue;
|
|
4930
|
+
}
|
|
4931
|
+
if (result.copyPropStores.size) {
|
|
4932
|
+
copyPropStores = result.copyPropStores;
|
|
4933
|
+
}
|
|
4934
|
+
}
|
|
4935
|
+
const result = propagateTypes({ ...state, stack: func.stack }, func, graph, optimizeEquivalencies, copyPropStores, logThisRun);
|
|
4936
|
+
if (!result.redo) {
|
|
4937
|
+
return result.istate;
|
|
4867
4938
|
}
|
|
4868
|
-
return propagateTypes({ ...state, stack: func.stack }, func, graph, optimizeEquivalencies, logThisRun).istate;
|
|
4869
4939
|
}
|
|
4870
4940
|
}
|
|
4871
4941
|
function buildConflictGraph(state, func) {
|
|
@@ -4873,8 +4943,8 @@ function buildConflictGraph(state, func) {
|
|
|
4873
4943
|
return;
|
|
4874
4944
|
const logThisRun = logging && loggingEnabledFor("CONFLICT_FUNC", func);
|
|
4875
4945
|
const { graph, identifiers } = buildDataFlowGraph(state, func, () => false, false, true);
|
|
4876
|
-
const { nodeEquivs } = propagateTypes({ ...state, stack: func.stack }, func, graph, false,
|
|
4877
|
-
const { locals, localConflicts } = findDeadStores(func, graph, nodeEquivs, logThisRun);
|
|
4946
|
+
const { nodeEquivs } = propagateTypes({ ...state, stack: func.stack }, func, graph, false, undefined, logThisRun);
|
|
4947
|
+
const { locals, localConflicts } = findDeadStores(func, graph, nodeEquivs, false, logThisRun);
|
|
4878
4948
|
return { graph, localConflicts, locals, identifiers, logThisRun };
|
|
4879
4949
|
}
|
|
4880
4950
|
function addEquiv(ts, key, equiv) {
|
|
@@ -4980,36 +5050,205 @@ function intersectEquiv(ts1, ts2, k) {
|
|
|
4980
5050
|
} while (s !== k);
|
|
4981
5051
|
return ret;
|
|
4982
5052
|
}
|
|
4983
|
-
function
|
|
5053
|
+
function clearAssocPaths(blockState, decl, v) {
|
|
5054
|
+
if (v.assocPaths?.size) {
|
|
5055
|
+
assert(blockState.trackedMemberDecls);
|
|
5056
|
+
v.assocPaths.forEach((assocPath) => {
|
|
5057
|
+
assocPath.split(".").forEach((pathItem) => {
|
|
5058
|
+
const tmd = blockState.trackedMemberDecls?.get(pathItem);
|
|
5059
|
+
if (tmd) {
|
|
5060
|
+
tmd.delete(decl);
|
|
5061
|
+
}
|
|
5062
|
+
});
|
|
5063
|
+
});
|
|
5064
|
+
}
|
|
5065
|
+
}
|
|
5066
|
+
function cloneTypeState(blockState) {
|
|
5067
|
+
const { map, trackedMemberDecls, liveCopyPropEvents, ...rest } = blockState;
|
|
5068
|
+
const clone = { map: new Map(map), ...rest };
|
|
5069
|
+
if (trackedMemberDecls) {
|
|
5070
|
+
clone.trackedMemberDecls = new Map();
|
|
5071
|
+
trackedMemberDecls.forEach((value, key) => {
|
|
5072
|
+
clone.trackedMemberDecls.set(key, new Set(value));
|
|
5073
|
+
});
|
|
5074
|
+
}
|
|
5075
|
+
if (liveCopyPropEvents) {
|
|
5076
|
+
clone.liveCopyPropEvents = new Map();
|
|
5077
|
+
liveCopyPropEvents.forEach((value, key) => {
|
|
5078
|
+
clone.liveCopyPropEvents?.set(key, new Set(value));
|
|
5079
|
+
});
|
|
5080
|
+
}
|
|
5081
|
+
return clone;
|
|
5082
|
+
}
|
|
5083
|
+
function addTrackedMemberDecl(blockState, key, assocKey) {
|
|
5084
|
+
if (!blockState.trackedMemberDecls) {
|
|
5085
|
+
blockState.trackedMemberDecls = new Map();
|
|
5086
|
+
}
|
|
5087
|
+
assocKey.split(".").forEach((pathItem) => {
|
|
5088
|
+
const entries = blockState.trackedMemberDecls.get(pathItem);
|
|
5089
|
+
if (!entries) {
|
|
5090
|
+
blockState.trackedMemberDecls.set(pathItem, new Set([key]));
|
|
5091
|
+
return;
|
|
5092
|
+
}
|
|
5093
|
+
entries.add(key);
|
|
5094
|
+
});
|
|
5095
|
+
}
|
|
5096
|
+
function addCopyPropEvent(blockState, item) {
|
|
5097
|
+
if (!blockState.liveCopyPropEvents) {
|
|
5098
|
+
blockState.liveCopyPropEvents = new Map();
|
|
5099
|
+
}
|
|
5100
|
+
const liveCopyPropEvents = blockState.liveCopyPropEvents;
|
|
5101
|
+
const decl = item.event.decl;
|
|
5102
|
+
assert(declIsLocal(decl));
|
|
5103
|
+
let tov = blockState.map.get(decl);
|
|
5104
|
+
assert(tov);
|
|
5105
|
+
if (tov.copyPropItem !== item) {
|
|
5106
|
+
tov = { ...tov, copyPropItem: item };
|
|
5107
|
+
blockState.map.set(decl, tov);
|
|
5108
|
+
}
|
|
5109
|
+
item.contained.forEach((value, key) => {
|
|
5110
|
+
const decls = liveCopyPropEvents.get(key);
|
|
5111
|
+
if (!decls) {
|
|
5112
|
+
liveCopyPropEvents.set(key, new Set([decl]));
|
|
5113
|
+
}
|
|
5114
|
+
else {
|
|
5115
|
+
decls.add(decl);
|
|
5116
|
+
}
|
|
5117
|
+
});
|
|
5118
|
+
}
|
|
5119
|
+
function clearCopyProp(blockState, item) {
|
|
5120
|
+
const liveCopyPropEvents = blockState.liveCopyPropEvents;
|
|
5121
|
+
assert(liveCopyPropEvents);
|
|
5122
|
+
const itemDecl = item.event.decl;
|
|
5123
|
+
item.contained.forEach((event, decl) => {
|
|
5124
|
+
const decls = liveCopyPropEvents.get(decl);
|
|
5125
|
+
assert(decls && decls.has(itemDecl));
|
|
5126
|
+
decls.delete(itemDecl);
|
|
5127
|
+
});
|
|
5128
|
+
}
|
|
5129
|
+
function copyPropFailed(blockState, item, nodeCopyProp) {
|
|
5130
|
+
clearCopyProp(blockState, item);
|
|
5131
|
+
const ref = nodeCopyProp.get(item.event.node);
|
|
5132
|
+
if (ref) {
|
|
5133
|
+
nodeCopyProp.delete(ref);
|
|
5134
|
+
}
|
|
5135
|
+
nodeCopyProp.set(item.event.node, false);
|
|
5136
|
+
}
|
|
5137
|
+
function clearRelatedCopyPropEvents(blockState, decl, nodeCopyProp) {
|
|
5138
|
+
blockState.liveCopyPropEvents
|
|
5139
|
+
?.get(decl)
|
|
5140
|
+
?.forEach((cpDecl) => {
|
|
5141
|
+
let value = blockState.map.get(cpDecl);
|
|
5142
|
+
assert(value && value.copyPropItem);
|
|
5143
|
+
assert(Array.from(value.copyPropItem.contained).some(([key]) => {
|
|
5144
|
+
return decl === key;
|
|
5145
|
+
}));
|
|
5146
|
+
copyPropFailed(blockState, value.copyPropItem, nodeCopyProp);
|
|
5147
|
+
value = { ...value };
|
|
5148
|
+
delete value.copyPropItem;
|
|
5149
|
+
blockState.map.set(cpDecl, value);
|
|
5150
|
+
});
|
|
5151
|
+
}
|
|
5152
|
+
function validateTypeState(curState) {
|
|
5153
|
+
curState.liveCopyPropEvents?.forEach((decls) => decls.forEach((cpDecl) => {
|
|
5154
|
+
const value = curState.map.get(cpDecl);
|
|
5155
|
+
assert(value && value.copyPropItem);
|
|
5156
|
+
}));
|
|
5157
|
+
curState.trackedMemberDecls?.forEach((affected, key) => {
|
|
5158
|
+
affected.forEach((decl) => {
|
|
5159
|
+
const value = curState.map.get(decl);
|
|
5160
|
+
assert(value && value.assocPaths);
|
|
5161
|
+
if (!Array.from(value.assocPaths).some((path) => `.${path}.`.includes(`.${key}.`))) {
|
|
5162
|
+
throw new Error("What");
|
|
5163
|
+
}
|
|
5164
|
+
});
|
|
5165
|
+
});
|
|
5166
|
+
}
|
|
5167
|
+
function mergeTypeState(blockStates, index, from, nodeCopyProp) {
|
|
4984
5168
|
const to = blockStates[index];
|
|
4985
5169
|
if (!to) {
|
|
4986
|
-
blockStates[index] =
|
|
4987
|
-
|
|
5170
|
+
blockStates[index] = cloneTypeState(from);
|
|
5171
|
+
blockStates[index].visits = 1;
|
|
4988
5172
|
return true;
|
|
4989
5173
|
}
|
|
4990
|
-
const widen = ++
|
|
5174
|
+
const widen = ++to.visits > 10;
|
|
5175
|
+
// we'll rebuild these from scratch
|
|
5176
|
+
delete to.trackedMemberDecls;
|
|
5177
|
+
delete to.liveCopyPropEvents;
|
|
4991
5178
|
let changes = false;
|
|
4992
|
-
to.forEach((tov, k) => {
|
|
4993
|
-
const fromv = from.get(k);
|
|
5179
|
+
to.map.forEach((tov, k) => {
|
|
5180
|
+
const fromv = from.map.get(k);
|
|
4994
5181
|
if (!fromv) {
|
|
4995
5182
|
changes = true;
|
|
4996
5183
|
if (tov.equivSet) {
|
|
4997
|
-
removeEquiv(to, k);
|
|
5184
|
+
removeEquiv(to.map, k);
|
|
4998
5185
|
}
|
|
4999
|
-
to.delete(k);
|
|
5186
|
+
to.map.delete(k);
|
|
5000
5187
|
return;
|
|
5001
5188
|
}
|
|
5002
5189
|
if (tov.equivSet) {
|
|
5003
|
-
if (intersectEquiv(to, from, k)) {
|
|
5190
|
+
if (intersectEquiv(to.map, from.map, k)) {
|
|
5191
|
+
changes = true;
|
|
5192
|
+
tov = to.map.get(k);
|
|
5193
|
+
}
|
|
5194
|
+
}
|
|
5195
|
+
if (tov.assocPaths) {
|
|
5196
|
+
tov = { ...tov };
|
|
5197
|
+
if (!fromv.assocPaths) {
|
|
5198
|
+
changes = true;
|
|
5199
|
+
delete tov.assocPaths;
|
|
5200
|
+
}
|
|
5201
|
+
else {
|
|
5202
|
+
const assocPaths = new Set(tov.assocPaths);
|
|
5203
|
+
assocPaths.forEach((key) => {
|
|
5204
|
+
if (!fromv.assocPaths.has(key)) {
|
|
5205
|
+
assocPaths.delete(key);
|
|
5206
|
+
changes = true;
|
|
5207
|
+
}
|
|
5208
|
+
else {
|
|
5209
|
+
addTrackedMemberDecl(to, k, key);
|
|
5210
|
+
}
|
|
5211
|
+
});
|
|
5212
|
+
if (assocPaths.size) {
|
|
5213
|
+
tov.assocPaths = assocPaths;
|
|
5214
|
+
}
|
|
5215
|
+
else {
|
|
5216
|
+
delete tov.assocPaths;
|
|
5217
|
+
}
|
|
5218
|
+
}
|
|
5219
|
+
to.map.set(k, tov);
|
|
5220
|
+
}
|
|
5221
|
+
// if both from and to have copyPropEvents, we can only
|
|
5222
|
+
// keep it if they're the same event.
|
|
5223
|
+
if (tov.copyPropItem) {
|
|
5224
|
+
if (tov.copyPropItem.event !== fromv.copyPropItem?.event) {
|
|
5225
|
+
const toProp = nodeCopyProp.get(tov.copyPropItem.event.node);
|
|
5226
|
+
if (toProp) {
|
|
5227
|
+
nodeCopyProp.delete(toProp);
|
|
5228
|
+
}
|
|
5229
|
+
nodeCopyProp.set(tov.copyPropItem.event.node, false);
|
|
5230
|
+
if (fromv.copyPropItem) {
|
|
5231
|
+
const fromProp = nodeCopyProp.get(fromv.copyPropItem.event.node);
|
|
5232
|
+
if (fromProp) {
|
|
5233
|
+
nodeCopyProp.delete(fromProp);
|
|
5234
|
+
}
|
|
5235
|
+
nodeCopyProp.set(fromv.copyPropItem.event.node, false);
|
|
5236
|
+
}
|
|
5237
|
+
tov = { ...tov };
|
|
5238
|
+
delete tov.copyPropItem;
|
|
5004
5239
|
changes = true;
|
|
5005
|
-
|
|
5240
|
+
to.map.set(k, tov);
|
|
5241
|
+
}
|
|
5242
|
+
else {
|
|
5243
|
+
assert(k === tov.copyPropItem.event.decl);
|
|
5244
|
+
addCopyPropEvent(to, tov.copyPropItem);
|
|
5006
5245
|
}
|
|
5007
5246
|
}
|
|
5008
5247
|
if (widen) {
|
|
5009
5248
|
if (subtypeOf(fromv.curType, tov.curType))
|
|
5010
5249
|
return;
|
|
5011
5250
|
if (subtypeOf(tov.curType, fromv.curType)) {
|
|
5012
|
-
to.set(k, { ...tov, curType: fromv.curType });
|
|
5251
|
+
to.map.set(k, { ...tov, curType: fromv.curType });
|
|
5013
5252
|
changes = true;
|
|
5014
5253
|
return;
|
|
5015
5254
|
}
|
|
@@ -5022,7 +5261,7 @@ function mergeTypeState(blockStates, blockVisits, index, from) {
|
|
|
5022
5261
|
if (wide)
|
|
5023
5262
|
result = wide;
|
|
5024
5263
|
}
|
|
5025
|
-
to.set(k, { ...tov, curType: result });
|
|
5264
|
+
to.map.set(k, { ...tov, curType: result });
|
|
5026
5265
|
changes = true;
|
|
5027
5266
|
});
|
|
5028
5267
|
return changes;
|
|
@@ -5033,9 +5272,7 @@ function tsEquivs(state, key) {
|
|
|
5033
5272
|
do {
|
|
5034
5273
|
result.push(tsKey(s));
|
|
5035
5274
|
const next = state.get(s);
|
|
5036
|
-
|
|
5037
|
-
throw new Error(`Inconsistent equivSet for ${tsKey(key)}: missing value for ${tsKey(s)}`);
|
|
5038
|
-
}
|
|
5275
|
+
assert(next && next.equivSet);
|
|
5039
5276
|
s = next.equivSet.next;
|
|
5040
5277
|
} while (s !== key);
|
|
5041
5278
|
return `[(${result.join(", ")})]`;
|
|
@@ -5049,149 +5286,105 @@ function printBlockState(block, state, indent = "") {
|
|
|
5049
5286
|
console.log(indent + "Not visited!");
|
|
5050
5287
|
return;
|
|
5051
5288
|
}
|
|
5052
|
-
state.forEach((value, key) => {
|
|
5053
|
-
console.log(`${indent} - ${typeStateEntry(value, key)}${value.equivSet ? " " + tsEquivs(state, key) : ""}`);
|
|
5289
|
+
state.map.forEach((value, key) => {
|
|
5290
|
+
console.log(`${indent} - ${typeStateEntry(value, key)}${value.equivSet ? " " + tsEquivs(state.map, key) : ""}`);
|
|
5054
5291
|
});
|
|
5055
5292
|
}
|
|
5056
|
-
|
|
5057
|
-
|
|
5058
|
-
|
|
5059
|
-
|
|
5060
|
-
|
|
5061
|
-
|
|
5062
|
-
|
|
5063
|
-
|
|
5064
|
-
|
|
5065
|
-
* tells us about object.
|
|
5066
|
-
*
|
|
5067
|
-
* The return value is two arrays of StateNode. The first
|
|
5068
|
-
* gives the refined type of object, and the second is the
|
|
5069
|
-
* array of StateNodes that could declare <name>
|
|
5070
|
-
*/
|
|
5071
|
-
function filterDecls(decls, possible, name) {
|
|
5072
|
-
if (!possible)
|
|
5073
|
-
return [null, null];
|
|
5074
|
-
const result = decls.reduce((cur, decl) => {
|
|
5075
|
-
const found = possible.reduce((flag, poss) => {
|
|
5076
|
-
if (decl === poss ||
|
|
5077
|
-
(poss.type === "ClassDeclaration" && (0,_api__WEBPACK_IMPORTED_MODULE_0__.getSuperClasses)(poss)?.has(decl))) {
|
|
5078
|
-
// poss extends decl, so decl must actually be a poss
|
|
5079
|
-
// eg we know obj is an Object, and we call obj.toNumber
|
|
5080
|
-
// so possible includes all the classes that declare toNumber
|
|
5081
|
-
// so we can refine obj's type to the union of those types
|
|
5082
|
-
if (!cur[0]) {
|
|
5083
|
-
cur = [new Set(), new Set()];
|
|
5084
|
-
}
|
|
5085
|
-
cur[0].add(poss);
|
|
5086
|
-
cur[1].add(poss);
|
|
5087
|
-
return true;
|
|
5293
|
+
function updateAffected(blockState, objectType, baseDecl, assignedPath, affectedName, affected, assignedType) {
|
|
5294
|
+
affected.forEach((key) => {
|
|
5295
|
+
let droppedComponents = null;
|
|
5296
|
+
const entry = blockState.map.get(key);
|
|
5297
|
+
assert(entry && entry.assocPaths);
|
|
5298
|
+
let newEntry = entry;
|
|
5299
|
+
entry.assocPaths.forEach((path) => {
|
|
5300
|
+
if (key === baseDecl && path === assignedPath) {
|
|
5301
|
+
return;
|
|
5088
5302
|
}
|
|
5089
|
-
|
|
5090
|
-
|
|
5091
|
-
|
|
5092
|
-
// eg we know obj is Menu2, we call obj.toString
|
|
5093
|
-
// Menu2 doesn't define toString, but Object does
|
|
5094
|
-
// so poss is Object. But we still know that
|
|
5095
|
-
// obj is Menu2
|
|
5096
|
-
if (!cur[0]) {
|
|
5097
|
-
cur = [new Set(), new Set()];
|
|
5098
|
-
}
|
|
5099
|
-
cur[0].add(decl);
|
|
5100
|
-
cur[1].add(poss);
|
|
5101
|
-
return true;
|
|
5303
|
+
const pathSegments = path.split(".");
|
|
5304
|
+
if (!pathSegments.includes(affectedName)) {
|
|
5305
|
+
return;
|
|
5102
5306
|
}
|
|
5103
|
-
|
|
5104
|
-
|
|
5105
|
-
|
|
5106
|
-
|
|
5107
|
-
|
|
5108
|
-
|
|
5109
|
-
|
|
5110
|
-
//
|
|
5111
|
-
// eg
|
|
5112
|
-
//
|
|
5113
|
-
// obj = Application.getApp();
|
|
5114
|
-
// obj.Properties.whatever
|
|
5115
|
-
//
|
|
5116
|
-
// Properties doesn't exist on AppBase, but AppBase
|
|
5117
|
-
// is declared in Application, and Application
|
|
5118
|
-
// does declare Properties. So Application.Properties
|
|
5119
|
-
// is (one of) the declarations we should find; but we
|
|
5120
|
-
// must not refine obj's type to include Application.
|
|
5121
|
-
let d = [decl];
|
|
5122
|
-
do {
|
|
5123
|
-
d.forEach((d) => {
|
|
5124
|
-
const stack = d.stack;
|
|
5125
|
-
possible.forEach((poss) => {
|
|
5126
|
-
for (let i = stack.length; i--;) {
|
|
5127
|
-
const sn = stack[i].sn;
|
|
5128
|
-
if (sn.decls === poss.decls) {
|
|
5129
|
-
if (!cur[0]) {
|
|
5130
|
-
cur = [new Set(), new Set()];
|
|
5131
|
-
}
|
|
5132
|
-
cur[0].add(decl);
|
|
5133
|
-
cur[1].add(poss);
|
|
5134
|
-
break;
|
|
5135
|
-
}
|
|
5136
|
-
if ((0,_api__WEBPACK_IMPORTED_MODULE_0__.hasProperty)(sn.decls, name)) {
|
|
5137
|
-
break;
|
|
5138
|
-
}
|
|
5139
|
-
}
|
|
5140
|
-
});
|
|
5307
|
+
const assocPath = [];
|
|
5308
|
+
let type = entry.curType;
|
|
5309
|
+
for (let i = 0; i < pathSegments.length; i++) {
|
|
5310
|
+
const pathItem = pathSegments[i];
|
|
5311
|
+
assocPath.push({
|
|
5312
|
+
name: pathItem === "*" ? null : pathItem,
|
|
5313
|
+
type,
|
|
5141
5314
|
});
|
|
5142
|
-
|
|
5143
|
-
|
|
5144
|
-
|
|
5145
|
-
|
|
5146
|
-
|
|
5315
|
+
if (pathItem === affectedName && couldBeShallow(type, objectType)) {
|
|
5316
|
+
const newAssocKey = assocPath.map((av) => av.name ?? "*").join(".");
|
|
5317
|
+
if (newEntry === entry) {
|
|
5318
|
+
newEntry = { ...entry };
|
|
5319
|
+
}
|
|
5320
|
+
if (newAssocKey !== path) {
|
|
5321
|
+
newEntry.assocPaths = new Set(newEntry.assocPaths);
|
|
5322
|
+
newEntry.assocPaths.delete(path);
|
|
5323
|
+
// the "extra" path components will also have entries
|
|
5324
|
+
// in blockState.trackedMemberDecls. Since they're gone
|
|
5325
|
+
// from here, we (may) need to remove them from there
|
|
5326
|
+
if (!droppedComponents) {
|
|
5327
|
+
droppedComponents = new Set();
|
|
5328
|
+
}
|
|
5329
|
+
while (++i < pathSegments.length) {
|
|
5330
|
+
droppedComponents.add(pathSegments[i]);
|
|
5331
|
+
}
|
|
5332
|
+
break;
|
|
5147
5333
|
}
|
|
5148
|
-
|
|
5149
|
-
|
|
5150
|
-
|
|
5334
|
+
const baseType = updateByAssocPath(assocPath, assignedType, true);
|
|
5335
|
+
newEntry.curType = baseType;
|
|
5336
|
+
break;
|
|
5337
|
+
}
|
|
5338
|
+
if (pathItem === "*") {
|
|
5339
|
+
const newType = { type: 0 /* TypeTag.Never */ };
|
|
5340
|
+
if (type.type & 512 /* TypeTag.Array */) {
|
|
5341
|
+
const atype = getUnionComponent(type, 512 /* TypeTag.Array */);
|
|
5342
|
+
if (atype) {
|
|
5343
|
+
unionInto(newType, atype);
|
|
5344
|
+
}
|
|
5345
|
+
}
|
|
5346
|
+
if (type.type & 1024 /* TypeTag.Dictionary */) {
|
|
5347
|
+
const dtype = getUnionComponent(type, 1024 /* TypeTag.Dictionary */);
|
|
5348
|
+
if (dtype) {
|
|
5349
|
+
unionInto(newType, dtype.value);
|
|
5350
|
+
}
|
|
5351
|
+
}
|
|
5352
|
+
if (newType.type === 0 /* TypeTag.Never */)
|
|
5353
|
+
break;
|
|
5354
|
+
type = newType;
|
|
5355
|
+
}
|
|
5356
|
+
else {
|
|
5357
|
+
const objValue = getObjectValue(type);
|
|
5358
|
+
if (!objValue || !hasProperty(objValue.obj, pathItem)) {
|
|
5359
|
+
break;
|
|
5360
|
+
}
|
|
5361
|
+
type = objValue.obj[pathItem];
|
|
5362
|
+
}
|
|
5363
|
+
}
|
|
5364
|
+
});
|
|
5365
|
+
if (newEntry !== entry) {
|
|
5366
|
+
if (droppedComponents) {
|
|
5367
|
+
newEntry.assocPaths.forEach((path) => path
|
|
5368
|
+
.split(".")
|
|
5369
|
+
.forEach((pathComponent) => droppedComponents.delete(pathComponent)));
|
|
5370
|
+
droppedComponents.forEach((pathComponent) => blockState.trackedMemberDecls.get(pathComponent).delete(key));
|
|
5371
|
+
}
|
|
5372
|
+
blockState.map.set(key, newEntry);
|
|
5151
5373
|
}
|
|
5152
|
-
|
|
5153
|
-
}, [null, null]);
|
|
5154
|
-
if (!result[0])
|
|
5155
|
-
return [null, null];
|
|
5156
|
-
return [Array.from(result[0]), Array.from(result[1])];
|
|
5157
|
-
}
|
|
5158
|
-
function findObjectDeclsByProperty(state, object, next) {
|
|
5159
|
-
const decls = (0,_type_flow_types__WEBPACK_IMPORTED_MODULE_11__/* .getStateNodeDeclsFromType */ .iX)(state, object);
|
|
5160
|
-
if (!decls)
|
|
5161
|
-
return [null, null];
|
|
5162
|
-
const possibleDecls = (0,_api__WEBPACK_IMPORTED_MODULE_0__.hasProperty)(state.allDeclarations, next.property.name) &&
|
|
5163
|
-
state.allDeclarations[next.property.name];
|
|
5164
|
-
return filterDecls(decls, possibleDecls, next.property.name);
|
|
5165
|
-
}
|
|
5166
|
-
function refineObjectTypeByDecls(istate, object, trueDecls) {
|
|
5167
|
-
const refinedType = typeFromTypeStateNodes(istate.state, trueDecls);
|
|
5168
|
-
return intersection(object, refinedType);
|
|
5169
|
-
}
|
|
5170
|
-
function findNextObjectType(istate, trueDecls, next) {
|
|
5171
|
-
const results = lookupNext(istate.state, [{ parent: null, results: trueDecls }], "decls", next.property);
|
|
5172
|
-
if (!results)
|
|
5173
|
-
return null;
|
|
5174
|
-
return results.reduce((cur, lookupDefn) => {
|
|
5175
|
-
unionInto(cur, typeFromTypeStateNodes(istate.state, lookupDefn.results));
|
|
5176
|
-
return cur;
|
|
5177
|
-
}, { type: 0 /* TypeTag.Never */ });
|
|
5178
|
-
}
|
|
5179
|
-
function resolveDottedMember(istate, object, next) {
|
|
5180
|
-
const [objDecls, trueDecls] = findObjectDeclsByProperty(istate.state, object, next);
|
|
5181
|
-
if (!objDecls)
|
|
5182
|
-
return null;
|
|
5183
|
-
const property = findNextObjectType(istate, trueDecls, next);
|
|
5184
|
-
if (!property)
|
|
5185
|
-
return null;
|
|
5186
|
-
const type = refineObjectTypeByDecls(istate, object, objDecls);
|
|
5187
|
-
const mayThrow = !subtypeOf(object, type);
|
|
5188
|
-
return { mayThrow, object: type, property };
|
|
5374
|
+
});
|
|
5189
5375
|
}
|
|
5190
|
-
function propagateTypes(state, func, graph, optimizeEquivalencies, logThisRun) {
|
|
5376
|
+
function propagateTypes(state, func, graph, optimizeEquivalencies, copyPropStores, logThisRun) {
|
|
5191
5377
|
// We want to traverse the blocks in reverse post order, in
|
|
5192
5378
|
// order to propagate the "availability" of the types.
|
|
5193
5379
|
const order = getPostOrder(graph).reverse();
|
|
5194
5380
|
const queue = new DataflowQueue();
|
|
5381
|
+
let selfClassDecl = null;
|
|
5382
|
+
if (!(func.attributes & StateNodeAttributes.STATIC)) {
|
|
5383
|
+
const klass = func.stack?.[func.stack?.length - 1].sn;
|
|
5384
|
+
if (klass && klass.type === "ClassDeclaration") {
|
|
5385
|
+
selfClassDecl = klass;
|
|
5386
|
+
}
|
|
5387
|
+
}
|
|
5195
5388
|
order.forEach((block, i) => {
|
|
5196
5389
|
block.order = i;
|
|
5197
5390
|
});
|
|
@@ -5202,10 +5395,10 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, logThisRun) {
|
|
|
5202
5395
|
printBlockTrailer(block);
|
|
5203
5396
|
});
|
|
5204
5397
|
}
|
|
5205
|
-
function memberDeclInfo(blockState, decl,
|
|
5398
|
+
function memberDeclInfo(blockState, decl, newValue) {
|
|
5206
5399
|
const baseType = getStateType(blockState, decl.base);
|
|
5207
5400
|
const typePath = [baseType];
|
|
5208
|
-
let next;
|
|
5401
|
+
let next = null;
|
|
5209
5402
|
let updateAny = false;
|
|
5210
5403
|
for (let i = 0, l = decl.path.length - 1; i <= l; i++) {
|
|
5211
5404
|
let cur = typePath.pop();
|
|
@@ -5276,55 +5469,62 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, logThisRun) {
|
|
|
5276
5469
|
typePath.push(cur);
|
|
5277
5470
|
typePath.push(next);
|
|
5278
5471
|
}
|
|
5279
|
-
|
|
5280
|
-
|
|
5281
|
-
|
|
5282
|
-
|
|
5283
|
-
|
|
5284
|
-
|
|
5285
|
-
|
|
5286
|
-
|
|
5287
|
-
|
|
5288
|
-
|
|
5289
|
-
|
|
5290
|
-
|
|
5291
|
-
|
|
5292
|
-
|
|
5472
|
+
const assocValue = decl.path.map((me, i) => ({
|
|
5473
|
+
name: me.computed ? null : me.property.name,
|
|
5474
|
+
type: typePath[i],
|
|
5475
|
+
}));
|
|
5476
|
+
const assocKey = assocValue.map((av) => av.name ?? "*").join(".");
|
|
5477
|
+
const newType = updateByAssocPath(assocValue, next, false);
|
|
5478
|
+
setStateEvent(blockState, decl.base, newType, newValue ? 1 /* UpdateKind.Inner */ : 0 /* UpdateKind.None */);
|
|
5479
|
+
const tsv = { ...blockState.map.get(decl.base) };
|
|
5480
|
+
tsv.assocPaths = new Set(tsv.assocPaths);
|
|
5481
|
+
tsv.assocPaths.add(assocKey);
|
|
5482
|
+
blockState.map.set(decl.base, tsv);
|
|
5483
|
+
addTrackedMemberDecl(blockState, decl.base, assocKey);
|
|
5484
|
+
if (newValue) {
|
|
5485
|
+
const baseElem = assocValue[decl.path.length - 1];
|
|
5486
|
+
if (baseElem.name) {
|
|
5487
|
+
const affected = blockState.trackedMemberDecls?.get(baseElem.name);
|
|
5488
|
+
if (affected) {
|
|
5489
|
+
updateAffected(blockState, baseElem.type, decl.base, assocKey, baseElem.name, affected, next);
|
|
5490
|
+
}
|
|
5491
|
+
}
|
|
5492
|
+
if (selfClassDecl) {
|
|
5493
|
+
// Handle interference between the MemberDecl store
|
|
5494
|
+
// and the "self" object.
|
|
5495
|
+
const baseObj = getObjectValue(baseElem.type);
|
|
5496
|
+
if (baseObj &&
|
|
5497
|
+
baseObj.klass.type === 16384 /* TypeTag.Class */ &&
|
|
5498
|
+
some(baseObj.klass.value, (cls) => cls === selfClassDecl ||
|
|
5499
|
+
getSuperClasses(cls)?.has(selfClassDecl) ||
|
|
5500
|
+
getSuperClasses(selfClassDecl)?.has(cls) ||
|
|
5501
|
+
false)) {
|
|
5502
|
+
const last = decl.path[decl.path.length - 1];
|
|
5503
|
+
if (!last.computed) {
|
|
5504
|
+
const result = lookupNext(state, [{ parent: null, results: [selfClassDecl] }], "decls", last.property);
|
|
5505
|
+
if (result) {
|
|
5506
|
+
const decls = result.flatMap((lookupDef) => lookupDef.results);
|
|
5507
|
+
const doUpdate = (key, cur) => {
|
|
5508
|
+
const update = cloneType(cur.curType);
|
|
5509
|
+
unionInto(update, next);
|
|
5510
|
+
setStateEvent(blockState, key, update, 0 /* UpdateKind.None */);
|
|
5511
|
+
};
|
|
5512
|
+
if (decls.length === 1) {
|
|
5513
|
+
const cur = blockState.map.get(decls[0]);
|
|
5514
|
+
cur && doUpdate(decls[0], cur);
|
|
5515
|
+
}
|
|
5516
|
+
else {
|
|
5517
|
+
blockState.map.forEach((cur, key) => {
|
|
5518
|
+
if (Array.isArray(key) && key[0] === decls[0]) {
|
|
5519
|
+
doUpdate(key, cur);
|
|
5520
|
+
}
|
|
5521
|
+
});
|
|
5522
|
+
}
|
|
5293
5523
|
}
|
|
5294
5524
|
}
|
|
5295
|
-
else {
|
|
5296
|
-
const obj = value.obj ? { ...value.obj } : {};
|
|
5297
|
-
obj[me.property.name] = property;
|
|
5298
|
-
object = cloneType(object);
|
|
5299
|
-
setUnionComponent(object, 32768 /* TypeTag.Object */, {
|
|
5300
|
-
klass: value.klass,
|
|
5301
|
-
obj,
|
|
5302
|
-
});
|
|
5303
|
-
}
|
|
5304
|
-
}
|
|
5305
|
-
}
|
|
5306
|
-
else {
|
|
5307
|
-
if (object.type & 512 /* TypeTag.Array */) {
|
|
5308
|
-
const avalue = getUnionComponent(object, 512 /* TypeTag.Array */);
|
|
5309
|
-
if (!avalue || !subtypeOf(property, avalue)) {
|
|
5310
|
-
object = cloneType(object);
|
|
5311
|
-
setUnionComponent(object, 512 /* TypeTag.Array */, property);
|
|
5312
|
-
}
|
|
5313
|
-
}
|
|
5314
|
-
if (object.type & 1024 /* TypeTag.Dictionary */) {
|
|
5315
|
-
const dvalue = getUnionComponent(object, 1024 /* TypeTag.Dictionary */);
|
|
5316
|
-
if (!dvalue || !subtypeOf(property, dvalue.value)) {
|
|
5317
|
-
object = cloneType(object);
|
|
5318
|
-
setUnionComponent(object, 1024 /* TypeTag.Dictionary */, {
|
|
5319
|
-
key: dvalue?.key || { type: 524287 /* TypeTag.Any */ },
|
|
5320
|
-
value: property,
|
|
5321
|
-
});
|
|
5322
|
-
}
|
|
5323
5525
|
}
|
|
5324
5526
|
}
|
|
5325
|
-
typePath.push(object);
|
|
5326
5527
|
}
|
|
5327
|
-
setStateEvent(blockState, decl.base, typePath[0], false);
|
|
5328
5528
|
return [next, updateAny];
|
|
5329
5529
|
}
|
|
5330
5530
|
function typeConstraint(decls) {
|
|
@@ -5341,38 +5541,61 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, logThisRun) {
|
|
|
5341
5541
|
return cur;
|
|
5342
5542
|
}, { type: 0 /* TypeTag.Never */ });
|
|
5343
5543
|
}
|
|
5344
|
-
function setStateEvent(blockState, decl, value,
|
|
5544
|
+
function setStateEvent(blockState, decl, value, updateKind) {
|
|
5345
5545
|
if (Array.isArray(decl) ||
|
|
5346
5546
|
(decl.type !== "MemberDecl" && decl.type !== "Unknown")) {
|
|
5347
|
-
if (
|
|
5547
|
+
if (updateKind !== 0 /* UpdateKind.None */) {
|
|
5548
|
+
// even if we're only modifying an Object, rather
|
|
5549
|
+
// than reassigning it, we need to clear the
|
|
5550
|
+
// related copy prop events, because although
|
|
5551
|
+
// we may only see the object itself, the expression
|
|
5552
|
+
// could access its fields. eg if x is the decl, then
|
|
5553
|
+
//
|
|
5554
|
+
// foo(x);
|
|
5555
|
+
//
|
|
5556
|
+
// might change when x.a.b.c is changed, even if we know
|
|
5557
|
+
// that foo is side-effect free, and accesses no globals.
|
|
5558
|
+
clearRelatedCopyPropEvents(blockState, decl, nodeCopyProp);
|
|
5559
|
+
}
|
|
5560
|
+
if (updateKind !== 2 /* UpdateKind.Reassign */) {
|
|
5348
5561
|
/*
|
|
5349
|
-
* If we're not
|
|
5350
|
-
* must be applied to every
|
|
5562
|
+
* If we're not re-assigning, the equivalencies don't
|
|
5563
|
+
* change, so this update must be applied to every
|
|
5564
|
+
* element of the set
|
|
5351
5565
|
*/
|
|
5352
|
-
const v = blockState.get(decl);
|
|
5566
|
+
const v = blockState.map.get(decl);
|
|
5353
5567
|
if (v?.equivSet) {
|
|
5354
5568
|
let s = decl;
|
|
5355
5569
|
do {
|
|
5356
|
-
const next = blockState.get(s);
|
|
5570
|
+
const next = blockState.map.get(s);
|
|
5357
5571
|
if (!next || !next.equivSet) {
|
|
5358
5572
|
throw new Error(`Inconsistent equivSet for ${tsKey(decl)}: missing value for ${tsKey(s)}`);
|
|
5359
5573
|
}
|
|
5360
|
-
blockState.set(s, { ...next, curType: value });
|
|
5574
|
+
blockState.map.set(s, { ...next, curType: value });
|
|
5361
5575
|
s = next.equivSet.next;
|
|
5362
5576
|
} while (s !== decl);
|
|
5363
|
-
|
|
5577
|
+
}
|
|
5578
|
+
else {
|
|
5579
|
+
blockState.map.set(decl, { ...v, curType: value });
|
|
5364
5580
|
}
|
|
5365
5581
|
}
|
|
5366
5582
|
else {
|
|
5367
|
-
|
|
5583
|
+
const v = blockState.map.get(decl);
|
|
5584
|
+
removeEquiv(blockState.map, decl);
|
|
5585
|
+
if (v?.assocPaths?.size) {
|
|
5586
|
+
clearAssocPaths(blockState, decl, v);
|
|
5587
|
+
}
|
|
5588
|
+
if (v?.copyPropItem) {
|
|
5589
|
+
copyPropFailed(blockState, v.copyPropItem, nodeCopyProp);
|
|
5590
|
+
}
|
|
5591
|
+
blockState.map.set(decl, { curType: value });
|
|
5368
5592
|
}
|
|
5369
|
-
blockState.set(decl, { curType: value });
|
|
5370
5593
|
return;
|
|
5371
5594
|
}
|
|
5372
5595
|
if (decl.type === "Unknown") {
|
|
5373
5596
|
return;
|
|
5374
5597
|
}
|
|
5375
|
-
return memberDeclInfo(blockState, decl,
|
|
5598
|
+
return memberDeclInfo(blockState, decl, value)?.[1];
|
|
5376
5599
|
}
|
|
5377
5600
|
function getStateType(blockState, decl) {
|
|
5378
5601
|
return getStateEntry(blockState, decl).curType;
|
|
@@ -5380,21 +5603,20 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, logThisRun) {
|
|
|
5380
5603
|
function getStateEntry(blockState, decl) {
|
|
5381
5604
|
if (Array.isArray(decl) ||
|
|
5382
5605
|
(decl.type !== "MemberDecl" && decl.type !== "Unknown")) {
|
|
5383
|
-
let tsVal = blockState.get(decl);
|
|
5606
|
+
let tsVal = blockState.map.get(decl);
|
|
5384
5607
|
if (!tsVal) {
|
|
5385
5608
|
tsVal = { curType: typeConstraint(decl) };
|
|
5386
|
-
blockState.set(decl, tsVal);
|
|
5609
|
+
blockState.map.set(decl, tsVal);
|
|
5387
5610
|
}
|
|
5388
5611
|
return tsVal;
|
|
5389
5612
|
}
|
|
5390
5613
|
if (decl.type === "Unknown") {
|
|
5391
5614
|
return { curType: { type: 0 /* TypeTag.Never */ } };
|
|
5392
5615
|
}
|
|
5393
|
-
const info = memberDeclInfo(blockState, decl
|
|
5616
|
+
const info = memberDeclInfo(blockState, decl);
|
|
5394
5617
|
return { curType: info ? info[0] : { type: 524287 /* TypeTag.Any */ } };
|
|
5395
5618
|
}
|
|
5396
5619
|
const blockStates = [];
|
|
5397
|
-
const blockVisits = [];
|
|
5398
5620
|
const typeMap = new Map();
|
|
5399
5621
|
const istate = {
|
|
5400
5622
|
state,
|
|
@@ -5412,23 +5634,58 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, logThisRun) {
|
|
|
5412
5634
|
if (succ.order == null) {
|
|
5413
5635
|
throw new Error("Unreachable block was visited");
|
|
5414
5636
|
}
|
|
5415
|
-
if (mergeTypeState(blockStates,
|
|
5637
|
+
if (mergeTypeState(blockStates, succ.order, curState, nodeCopyProp)) {
|
|
5638
|
+
if (logThisRun) {
|
|
5639
|
+
console.log(`re-merge: ${top.order} -> ${succ.order}`);
|
|
5640
|
+
}
|
|
5416
5641
|
queue.enqueue(succ);
|
|
5417
5642
|
}
|
|
5418
5643
|
});
|
|
5419
5644
|
};
|
|
5420
|
-
function
|
|
5645
|
+
function checkModResults(curState, calleeObjDecl, callees, node) {
|
|
5421
5646
|
const calleeObj = getStateType(curState, calleeObjDecl);
|
|
5422
|
-
|
|
5423
|
-
|
|
5647
|
+
const calleeResult = { type: 0 /* TypeTag.Never */ };
|
|
5648
|
+
const result = every(callees, (callee) => {
|
|
5649
|
+
const info = sysCallInfo(istate.state, callee);
|
|
5424
5650
|
if (!info)
|
|
5425
5651
|
return false;
|
|
5426
5652
|
const result = info(istate.state, callee, calleeObj, () => node.arguments.map((arg) => evaluateExpr(state, arg, typeMap).value));
|
|
5653
|
+
if (!result.effectFree) {
|
|
5654
|
+
return false;
|
|
5655
|
+
}
|
|
5427
5656
|
if (result.calleeObj) {
|
|
5428
|
-
|
|
5657
|
+
unionInto(calleeResult, result.calleeObj);
|
|
5429
5658
|
}
|
|
5430
5659
|
return true;
|
|
5431
5660
|
});
|
|
5661
|
+
return result ? calleeResult : null;
|
|
5662
|
+
}
|
|
5663
|
+
function modInterference(blockState, event, doUpdate, callback) {
|
|
5664
|
+
let callees = undefined;
|
|
5665
|
+
if (event.calleeDecl) {
|
|
5666
|
+
const calleeType = getStateType(blockState, event.calleeDecl);
|
|
5667
|
+
if (hasValue(calleeType) && calleeType.type === 8192 /* TypeTag.Function */) {
|
|
5668
|
+
callees = calleeType.value;
|
|
5669
|
+
}
|
|
5670
|
+
else {
|
|
5671
|
+
callees = findCalleesByNode(state, event.node);
|
|
5672
|
+
}
|
|
5673
|
+
}
|
|
5674
|
+
if (callees === undefined && event.callees !== undefined) {
|
|
5675
|
+
callees = event.callees;
|
|
5676
|
+
}
|
|
5677
|
+
if (event.calleeObj) {
|
|
5678
|
+
const calleeObjResult = checkModResults(blockState, event.calleeObj, callees, event.node);
|
|
5679
|
+
if (calleeObjResult) {
|
|
5680
|
+
if (calleeObjResult.type !== 0 /* TypeTag.Never */) {
|
|
5681
|
+
if (doUpdate) {
|
|
5682
|
+
setStateEvent(blockState, event.calleeObj, calleeObjResult, 0 /* UpdateKind.None */);
|
|
5683
|
+
}
|
|
5684
|
+
}
|
|
5685
|
+
return true;
|
|
5686
|
+
}
|
|
5687
|
+
}
|
|
5688
|
+
return callback(callees, event.calleeObj);
|
|
5432
5689
|
}
|
|
5433
5690
|
function handleFlowEvent(event, top, curState) {
|
|
5434
5691
|
const fixTypes = (equal, left, right, leftDecl, rightDecl) => {
|
|
@@ -5447,8 +5704,8 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, logThisRun) {
|
|
|
5447
5704
|
return false;
|
|
5448
5705
|
}
|
|
5449
5706
|
}
|
|
5450
|
-
const tmpState =
|
|
5451
|
-
setStateEvent(tmpState, leftDecl, leftr,
|
|
5707
|
+
const tmpState = cloneTypeState(curState);
|
|
5708
|
+
setStateEvent(tmpState, leftDecl, leftr, 0 /* UpdateKind.None */);
|
|
5452
5709
|
if (rightDecl) {
|
|
5453
5710
|
let rightr = restrictByEquality(left, right);
|
|
5454
5711
|
if (rightr.type === 0 /* TypeTag.Never */) {
|
|
@@ -5460,7 +5717,7 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, logThisRun) {
|
|
|
5460
5717
|
return false;
|
|
5461
5718
|
}
|
|
5462
5719
|
}
|
|
5463
|
-
setStateEvent(tmpState, rightDecl, rightr,
|
|
5720
|
+
setStateEvent(tmpState, rightDecl, rightr, 0 /* UpdateKind.None */);
|
|
5464
5721
|
}
|
|
5465
5722
|
return tmpState;
|
|
5466
5723
|
}
|
|
@@ -5473,8 +5730,8 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, logThisRun) {
|
|
|
5473
5730
|
singletonRemoved.type -= right.type;
|
|
5474
5731
|
if (singletonRemoved.type === 0 /* TypeTag.Never */)
|
|
5475
5732
|
return false;
|
|
5476
|
-
const tmpState =
|
|
5477
|
-
setStateEvent(tmpState, leftDecl, singletonRemoved,
|
|
5733
|
+
const tmpState = cloneTypeState(curState);
|
|
5734
|
+
setStateEvent(tmpState, leftDecl, singletonRemoved, 0 /* UpdateKind.None */);
|
|
5478
5735
|
return tmpState;
|
|
5479
5736
|
}
|
|
5480
5737
|
return null;
|
|
@@ -5505,8 +5762,8 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, logThisRun) {
|
|
|
5505
5762
|
singletonRemoved.type &= ~(1 /* TypeTag.Null */ | 2 /* TypeTag.False */);
|
|
5506
5763
|
if (singletonRemoved.type === 0 /* TypeTag.Never */)
|
|
5507
5764
|
return false;
|
|
5508
|
-
const tmpState =
|
|
5509
|
-
setStateEvent(tmpState, event.left, singletonRemoved,
|
|
5765
|
+
const tmpState = cloneTypeState(curState);
|
|
5766
|
+
setStateEvent(tmpState, event.left, singletonRemoved, 0 /* UpdateKind.None */);
|
|
5510
5767
|
return tmpState;
|
|
5511
5768
|
}
|
|
5512
5769
|
}
|
|
@@ -5520,8 +5777,8 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, logThisRun) {
|
|
|
5520
5777
|
});
|
|
5521
5778
|
if (nonNullRemoved.type === 0 /* TypeTag.Never */)
|
|
5522
5779
|
return false;
|
|
5523
|
-
const tmpState =
|
|
5524
|
-
setStateEvent(tmpState, event.left, nonNullRemoved,
|
|
5780
|
+
const tmpState = cloneTypeState(curState);
|
|
5781
|
+
setStateEvent(tmpState, event.left, nonNullRemoved, 0 /* UpdateKind.None */);
|
|
5525
5782
|
return tmpState;
|
|
5526
5783
|
}
|
|
5527
5784
|
break;
|
|
@@ -5578,8 +5835,8 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, logThisRun) {
|
|
|
5578
5835
|
}
|
|
5579
5836
|
}
|
|
5580
5837
|
if (result) {
|
|
5581
|
-
const tmpState =
|
|
5582
|
-
setStateEvent(tmpState, event.left, result,
|
|
5838
|
+
const tmpState = cloneTypeState(curState);
|
|
5839
|
+
setStateEvent(tmpState, event.left, result, 0 /* UpdateKind.None */);
|
|
5583
5840
|
return tmpState;
|
|
5584
5841
|
}
|
|
5585
5842
|
}
|
|
@@ -5606,7 +5863,10 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, logThisRun) {
|
|
|
5606
5863
|
console.log(` Flow (true): merge to ${trueSucc.order || -1}`);
|
|
5607
5864
|
printBlockState(top, sTrue || curState, " >true ");
|
|
5608
5865
|
}
|
|
5609
|
-
if (mergeTypeState(blockStates,
|
|
5866
|
+
if (mergeTypeState(blockStates, trueSucc.order, sTrue || curState, nodeCopyProp)) {
|
|
5867
|
+
if (logThisRun) {
|
|
5868
|
+
console.log(`re-merge: ${top.order} -> ${trueSucc.order}`);
|
|
5869
|
+
}
|
|
5610
5870
|
queue.enqueue(trueSucc);
|
|
5611
5871
|
}
|
|
5612
5872
|
}
|
|
@@ -5618,37 +5878,55 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, logThisRun) {
|
|
|
5618
5878
|
console.log(` Flow (false): merge to: ${falseSucc.order || -1}`);
|
|
5619
5879
|
printBlockState(top, sFalse || curState, " >false ");
|
|
5620
5880
|
}
|
|
5621
|
-
if (mergeTypeState(blockStates,
|
|
5881
|
+
if (mergeTypeState(blockStates, falseSucc.order, sFalse || curState, nodeCopyProp)) {
|
|
5882
|
+
if (logThisRun) {
|
|
5883
|
+
console.log(`re-merge: ${top.order} -> ${falseSucc.order}`);
|
|
5884
|
+
}
|
|
5622
5885
|
queue.enqueue(falseSucc);
|
|
5623
5886
|
}
|
|
5624
5887
|
}
|
|
5625
5888
|
return true;
|
|
5626
5889
|
}
|
|
5890
|
+
/*
|
|
5891
|
+
* nodeCopyProp contains two related maps. It maps ref nodes
|
|
5892
|
+
* to the def node that should be copy propagated. It also maps
|
|
5893
|
+
* def nodes to false, to indicate a previous failure to find
|
|
5894
|
+
* a copy prop candidate.
|
|
5895
|
+
*/
|
|
5896
|
+
const nodeCopyProp = new Map();
|
|
5627
5897
|
const nodeEquivs = new Map();
|
|
5628
5898
|
const localDecls = new Map();
|
|
5629
5899
|
const localConflicts = new Set();
|
|
5630
5900
|
const selfAssignments = new Set();
|
|
5631
5901
|
const processEvent = (top, curState, event, skipMerge) => {
|
|
5632
5902
|
if (!skipMerge && event.mayThrow && top.exsucc) {
|
|
5633
|
-
if (mergeTypeState(blockStates,
|
|
5903
|
+
if (mergeTypeState(blockStates, top.exsucc.order, curState, nodeCopyProp)) {
|
|
5634
5904
|
queue.enqueue(top.exsucc);
|
|
5635
5905
|
}
|
|
5636
5906
|
}
|
|
5907
|
+
validateTypeState(curState);
|
|
5637
5908
|
switch (event.type) {
|
|
5638
5909
|
case "kil": {
|
|
5639
5910
|
const curEntry = getStateEntry(curState, event.decl);
|
|
5640
5911
|
if (curEntry.equivSet) {
|
|
5641
|
-
removeEquiv(curState, event.decl);
|
|
5912
|
+
removeEquiv(curState.map, event.decl);
|
|
5642
5913
|
}
|
|
5643
|
-
|
|
5914
|
+
if (curEntry.assocPaths) {
|
|
5915
|
+
clearAssocPaths(curState, event.decl, curEntry);
|
|
5916
|
+
}
|
|
5917
|
+
if (curEntry.copyPropItem) {
|
|
5918
|
+
copyPropFailed(curState, curEntry.copyPropItem, nodeCopyProp);
|
|
5919
|
+
}
|
|
5920
|
+
clearRelatedCopyPropEvents(curState, event.decl, nodeCopyProp);
|
|
5921
|
+
curState.map.delete(event.decl);
|
|
5644
5922
|
break;
|
|
5645
5923
|
}
|
|
5646
5924
|
case "ref": {
|
|
5647
|
-
|
|
5925
|
+
let curEntry = getStateEntry(curState, event.decl);
|
|
5648
5926
|
typeMap.set(event.node, curEntry.curType);
|
|
5649
5927
|
nodeEquivs.delete(event.node);
|
|
5650
5928
|
if (curEntry.equivSet) {
|
|
5651
|
-
const equiv = Array.from(getEquivSet(curState, event.decl)).filter((decl) => decl !== event.decl && declIsLocal(decl));
|
|
5929
|
+
const equiv = Array.from(getEquivSet(curState.map, event.decl)).filter((decl) => decl !== event.decl && declIsLocal(decl));
|
|
5652
5930
|
if (equiv.length) {
|
|
5653
5931
|
nodeEquivs.set(event.node, {
|
|
5654
5932
|
decl: event.decl,
|
|
@@ -5656,6 +5934,26 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, logThisRun) {
|
|
|
5656
5934
|
});
|
|
5657
5935
|
}
|
|
5658
5936
|
}
|
|
5937
|
+
if (copyPropStores) {
|
|
5938
|
+
nodeCopyProp.delete(event.node);
|
|
5939
|
+
if (curEntry.copyPropItem) {
|
|
5940
|
+
const copyPropInfo = copyPropStores.get(curEntry.copyPropItem.event.node);
|
|
5941
|
+
assert(copyPropInfo && copyPropInfo.ref === event.node);
|
|
5942
|
+
const defNode = nodeCopyProp.get(curEntry.copyPropItem.event.node);
|
|
5943
|
+
assert(!defNode || defNode === event.node);
|
|
5944
|
+
if (defNode !== false) {
|
|
5945
|
+
nodeCopyProp.set(event.node, curEntry.copyPropItem.event.node);
|
|
5946
|
+
nodeCopyProp.set(curEntry.copyPropItem.event.node, event.node);
|
|
5947
|
+
}
|
|
5948
|
+
clearCopyProp(curState, curEntry.copyPropItem);
|
|
5949
|
+
curEntry = { ...curEntry };
|
|
5950
|
+
delete curEntry.copyPropItem;
|
|
5951
|
+
curState.map.set(event.decl, curEntry);
|
|
5952
|
+
}
|
|
5953
|
+
else if (declIsNonLocal(event.decl)) {
|
|
5954
|
+
clearRelatedCopyPropEvents(curState, null, nodeCopyProp);
|
|
5955
|
+
}
|
|
5956
|
+
}
|
|
5659
5957
|
if (logThisRun) {
|
|
5660
5958
|
console.log(` ${describeEvent(event)} == ${display(curEntry.curType)}`);
|
|
5661
5959
|
}
|
|
@@ -5665,44 +5963,75 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, logThisRun) {
|
|
|
5665
5963
|
if (logThisRun) {
|
|
5666
5964
|
console.log(` ${describeEvent(event)}`);
|
|
5667
5965
|
}
|
|
5668
|
-
|
|
5669
|
-
|
|
5670
|
-
|
|
5671
|
-
|
|
5672
|
-
|
|
5673
|
-
|
|
5674
|
-
|
|
5675
|
-
|
|
5966
|
+
modInterference(curState, event, true, (callees, calleeObj) => {
|
|
5967
|
+
clearRelatedCopyPropEvents(curState, null, nodeCopyProp);
|
|
5968
|
+
if (calleeObj) {
|
|
5969
|
+
const objType = getStateType(curState, calleeObj);
|
|
5970
|
+
if (objType.type &
|
|
5971
|
+
(32768 /* TypeTag.Object */ | 512 /* TypeTag.Array */ | 1024 /* TypeTag.Dictionary */)) {
|
|
5972
|
+
setStateEvent(curState, calleeObj, objType, 1 /* UpdateKind.Inner */);
|
|
5973
|
+
}
|
|
5676
5974
|
}
|
|
5677
|
-
|
|
5678
|
-
|
|
5679
|
-
|
|
5680
|
-
|
|
5681
|
-
|
|
5682
|
-
|
|
5683
|
-
|
|
5975
|
+
if (nodeCopyProp.size &&
|
|
5976
|
+
event.node.type === "CallExpression" &&
|
|
5977
|
+
some(callees, (callee) => inlineRequested(state, callee))) {
|
|
5978
|
+
// we don't want to copy-prop to the argument of
|
|
5979
|
+
// an inline function, because that could prevent
|
|
5980
|
+
// inlining.
|
|
5981
|
+
event.node.arguments.forEach((arg) => {
|
|
5982
|
+
const def = nodeCopyProp.get(arg);
|
|
5983
|
+
if (def && nodeCopyProp.get(def) !== false) {
|
|
5984
|
+
nodeCopyProp.set(def, false);
|
|
5985
|
+
nodeCopyProp.delete(arg);
|
|
5986
|
+
}
|
|
5987
|
+
});
|
|
5684
5988
|
}
|
|
5685
|
-
|
|
5686
|
-
|
|
5687
|
-
|
|
5688
|
-
|
|
5689
|
-
|
|
5690
|
-
|
|
5989
|
+
curState.map.forEach((tsv, decl) => {
|
|
5990
|
+
let type = tsv.curType;
|
|
5991
|
+
if (!some(decl, (d) => d.type === "VariableDeclarator" &&
|
|
5992
|
+
(d.node.kind === "var" ||
|
|
5993
|
+
// even a "const" could have its "inner" type altered
|
|
5994
|
+
(type.value != null && (type.type & 32768 /* TypeTag.Object */) !== 0)))) {
|
|
5995
|
+
return;
|
|
5691
5996
|
}
|
|
5692
|
-
|
|
5693
|
-
|
|
5694
|
-
|
|
5695
|
-
|
|
5696
|
-
|
|
5697
|
-
|
|
5698
|
-
if (odata?.obj) {
|
|
5699
|
-
type = cloneType(type);
|
|
5700
|
-
const newData = { klass: odata.klass };
|
|
5701
|
-
setUnionComponent(type, 32768 /* TypeTag.Object */, newData);
|
|
5702
|
-
curState.set(decl, { ...tsv, curType: type });
|
|
5997
|
+
if (modifiableDecl(decl, callees)) {
|
|
5998
|
+
if (tsv.equivSet) {
|
|
5999
|
+
removeEquiv(curState.map, decl);
|
|
6000
|
+
}
|
|
6001
|
+
if (tsv.assocPaths) {
|
|
6002
|
+
clearAssocPaths(curState, decl, tsv);
|
|
5703
6003
|
}
|
|
6004
|
+
// we only attach copyPropItems to locals,
|
|
6005
|
+
// which can't be modified by a call.
|
|
6006
|
+
assert(!tsv.copyPropItem);
|
|
6007
|
+
clearRelatedCopyPropEvents(curState, decl, nodeCopyProp);
|
|
6008
|
+
curState.map.set(decl, { curType: typeConstraint(decl) });
|
|
5704
6009
|
}
|
|
5705
|
-
|
|
6010
|
+
else if (type.value != null &&
|
|
6011
|
+
(!callees || !every(callees, (callee) => callee.info === false))) {
|
|
6012
|
+
if (type.type & 32768 /* TypeTag.Object */) {
|
|
6013
|
+
const odata = getObjectValue(tsv.curType);
|
|
6014
|
+
if (odata?.obj) {
|
|
6015
|
+
type = cloneType(type);
|
|
6016
|
+
const newData = { klass: odata.klass };
|
|
6017
|
+
setUnionComponent(type, 32768 /* TypeTag.Object */, newData);
|
|
6018
|
+
if (tsv.assocPaths) {
|
|
6019
|
+
clearAssocPaths(curState, decl, tsv);
|
|
6020
|
+
tsv = { ...tsv };
|
|
6021
|
+
delete tsv.assocPaths;
|
|
6022
|
+
}
|
|
6023
|
+
if (tsv.copyPropItem) {
|
|
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 });
|
|
6030
|
+
}
|
|
6031
|
+
}
|
|
6032
|
+
}
|
|
6033
|
+
});
|
|
6034
|
+
return true;
|
|
5706
6035
|
});
|
|
5707
6036
|
break;
|
|
5708
6037
|
}
|
|
@@ -5713,9 +6042,18 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, logThisRun) {
|
|
|
5713
6042
|
? event.node.left
|
|
5714
6043
|
: null;
|
|
5715
6044
|
if (lval) {
|
|
5716
|
-
const
|
|
5717
|
-
if (
|
|
5718
|
-
typeMap.set(lval,
|
|
6045
|
+
const before = getStateEntry(curState, event.decl);
|
|
6046
|
+
if (before.curType) {
|
|
6047
|
+
typeMap.set(lval, before.curType);
|
|
6048
|
+
}
|
|
6049
|
+
if (before.copyPropItem &&
|
|
6050
|
+
(event.node.type !== "AssignmentExpression" ||
|
|
6051
|
+
event.node.operator !== "=")) {
|
|
6052
|
+
copyPropFailed(curState, before.copyPropItem, nodeCopyProp);
|
|
6053
|
+
const v = { ...before };
|
|
6054
|
+
delete v.copyPropItem;
|
|
6055
|
+
assert(isTypeStateKey(event.decl));
|
|
6056
|
+
curState.map.set(event.decl, v);
|
|
5719
6057
|
}
|
|
5720
6058
|
}
|
|
5721
6059
|
const expr = event.node.type === "VariableDeclarator"
|
|
@@ -5724,24 +6062,47 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, logThisRun) {
|
|
|
5724
6062
|
const type = expr
|
|
5725
6063
|
? evaluate(istate, expr).value
|
|
5726
6064
|
: { type: 524287 /* TypeTag.Any */ };
|
|
5727
|
-
|
|
5728
|
-
|
|
5729
|
-
|
|
5730
|
-
|
|
5731
|
-
|
|
6065
|
+
const wasComputedDecl = setStateEvent(curState, event.decl, type, 2 /* UpdateKind.Reassign */);
|
|
6066
|
+
some(event.decl, (decl) => {
|
|
6067
|
+
if (decl.type !== "VariableDeclarator" ||
|
|
6068
|
+
decl.node.kind !== "var" ||
|
|
6069
|
+
!isClassVariable(decl)) {
|
|
6070
|
+
return false;
|
|
6071
|
+
}
|
|
6072
|
+
// A write to a class variable could interfere with
|
|
6073
|
+
// a MemberDecl
|
|
6074
|
+
const affected = curState.trackedMemberDecls?.get(decl.name);
|
|
6075
|
+
if (affected) {
|
|
6076
|
+
const objType = typeFromTypeStateNodes(istate.state, map(event.decl, (decl) => decl.type === "VariableDeclarator" &&
|
|
6077
|
+
decl.stack[decl.stack.length - 1].sn).filter((decl) => decl && decl.type === "ClassDeclaration"));
|
|
6078
|
+
updateAffected(curState, objType, event.decl, decl.name, decl.name, affected, type);
|
|
6079
|
+
}
|
|
6080
|
+
return true;
|
|
6081
|
+
});
|
|
6082
|
+
if (wasComputedDecl) {
|
|
6083
|
+
curState.map.forEach((value, decls) => {
|
|
6084
|
+
// we wrote through a computed member expression
|
|
6085
|
+
// which might have been a Class, Module or Object.
|
|
6086
|
+
// That could have affected any non-local...
|
|
5732
6087
|
if (some(decls, (decl) => decl.type === "VariableDeclarator" &&
|
|
5733
6088
|
decl.node.kind === "var" &&
|
|
5734
6089
|
!isLocal(decl))) {
|
|
5735
6090
|
if (value.equivSet) {
|
|
5736
|
-
removeEquiv(curState, decls);
|
|
6091
|
+
removeEquiv(curState.map, decls);
|
|
5737
6092
|
}
|
|
5738
|
-
|
|
6093
|
+
if (value.assocPaths) {
|
|
6094
|
+
clearAssocPaths(curState, decls, value);
|
|
6095
|
+
}
|
|
6096
|
+
assert(!value.copyPropItem);
|
|
6097
|
+
curState.map.set(decls, { curType: typeConstraint(decls) });
|
|
6098
|
+
clearRelatedCopyPropEvents(curState, decls, nodeCopyProp);
|
|
5739
6099
|
}
|
|
5740
6100
|
});
|
|
5741
6101
|
}
|
|
5742
6102
|
if (event.rhs) {
|
|
5743
|
-
const selfAssign = addEquiv(curState, event.rhs, event.decl);
|
|
5744
|
-
if (event.node.type === "AssignmentExpression"
|
|
6103
|
+
const selfAssign = addEquiv(curState.map, event.rhs, event.decl);
|
|
6104
|
+
if (event.node.type === "AssignmentExpression" &&
|
|
6105
|
+
event.node.operator === "=") {
|
|
5745
6106
|
if (selfAssign) {
|
|
5746
6107
|
// rhs and lhs are identical
|
|
5747
6108
|
selfAssignments.add(event.node);
|
|
@@ -5751,7 +6112,72 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, logThisRun) {
|
|
|
5751
6112
|
}
|
|
5752
6113
|
}
|
|
5753
6114
|
}
|
|
5754
|
-
if (declIsLocal(event.decl)) {
|
|
6115
|
+
if (!declIsLocal(event.decl)) {
|
|
6116
|
+
clearRelatedCopyPropEvents(curState, null, nodeCopyProp);
|
|
6117
|
+
}
|
|
6118
|
+
else {
|
|
6119
|
+
if (event.containedEvents &&
|
|
6120
|
+
copyPropStores &&
|
|
6121
|
+
nodeCopyProp.get(event.node) !== false &&
|
|
6122
|
+
(!event.rhs || !declIsLocal(event.rhs))) {
|
|
6123
|
+
const copyPropCandidate = copyPropStores.get(event.node);
|
|
6124
|
+
if (copyPropCandidate) {
|
|
6125
|
+
const contained = new Map();
|
|
6126
|
+
if (event.containedEvents.every((event) => {
|
|
6127
|
+
if (event.type === "mod") {
|
|
6128
|
+
if (modInterference(curState, event, false, () => false)) {
|
|
6129
|
+
return true;
|
|
6130
|
+
}
|
|
6131
|
+
if (!copyPropCandidate.ant ||
|
|
6132
|
+
// If the ref isn't anticipated, we can't propagate it
|
|
6133
|
+
// in case it has side effects.
|
|
6134
|
+
some(event.calleeDecl, (callee) => callee.type === "FunctionDeclaration" &&
|
|
6135
|
+
inlineRequested(state, callee))) {
|
|
6136
|
+
// Don't copy prop if the rhs is marked for
|
|
6137
|
+
// inline, because we might move it out of
|
|
6138
|
+
// assignment context, to somewhere it can't be
|
|
6139
|
+
// inlined.
|
|
6140
|
+
return false;
|
|
6141
|
+
}
|
|
6142
|
+
}
|
|
6143
|
+
if (!event.decl ||
|
|
6144
|
+
(isTypeStateKey(event.decl) &&
|
|
6145
|
+
some(event.decl, (decl) => (decl.type === "VariableDeclarator" &&
|
|
6146
|
+
decl.node.kind === "var") ||
|
|
6147
|
+
decl.type === "BinaryExpression" ||
|
|
6148
|
+
decl.type === "Identifier"))) {
|
|
6149
|
+
const key = event.decl ?? null;
|
|
6150
|
+
if (key &&
|
|
6151
|
+
declIsLocal(key) &&
|
|
6152
|
+
nodeCopyProp.has(event.node)) {
|
|
6153
|
+
// we might have
|
|
6154
|
+
//
|
|
6155
|
+
// var x = foo();
|
|
6156
|
+
// var y = x + 1;
|
|
6157
|
+
// bar();
|
|
6158
|
+
// return y;
|
|
6159
|
+
//
|
|
6160
|
+
// In that case, its ok to drop "x = foo()" and rewrite as y = foo() + 1"
|
|
6161
|
+
// OR its ok to drop "y = x + 1" and rewrite as "return x + 1".
|
|
6162
|
+
// But we can't do both, and rewrite as "bar(); return foo() + 1;"
|
|
6163
|
+
// So just disable copy prop for *this* node. We'll re-run and have a
|
|
6164
|
+
// second chance later.
|
|
6165
|
+
return false;
|
|
6166
|
+
}
|
|
6167
|
+
const item = contained.get(key);
|
|
6168
|
+
if (!item) {
|
|
6169
|
+
contained.set(key, [event]);
|
|
6170
|
+
}
|
|
6171
|
+
else {
|
|
6172
|
+
item.push(event);
|
|
6173
|
+
}
|
|
6174
|
+
}
|
|
6175
|
+
return true;
|
|
6176
|
+
})) {
|
|
6177
|
+
addCopyPropEvent(curState, { event, contained });
|
|
6178
|
+
}
|
|
6179
|
+
}
|
|
6180
|
+
}
|
|
5755
6181
|
const name = localDeclName(event.decl);
|
|
5756
6182
|
const locals = localDecls.get(name);
|
|
5757
6183
|
if (!locals) {
|
|
@@ -5759,7 +6185,8 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, logThisRun) {
|
|
|
5759
6185
|
}
|
|
5760
6186
|
else {
|
|
5761
6187
|
locals.forEach((local) => {
|
|
5762
|
-
if (local !== event.decl &&
|
|
6188
|
+
if (local !== event.decl &&
|
|
6189
|
+
curState.map.has(local)) {
|
|
5763
6190
|
localConflicts.add(local);
|
|
5764
6191
|
}
|
|
5765
6192
|
});
|
|
@@ -5780,7 +6207,7 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, logThisRun) {
|
|
|
5780
6207
|
}
|
|
5781
6208
|
if (logThisRun) {
|
|
5782
6209
|
console.log(` ${describeEvent(event)} : ${!Array.isArray(event.left) && event.left.type === "MemberDecl"
|
|
5783
|
-
? `${display(curState.get(event.left.base)?.curType || {
|
|
6210
|
+
? `${display(curState.map.get(event.left.base)?.curType || {
|
|
5784
6211
|
type: 524287 /* TypeTag.Any */,
|
|
5785
6212
|
})} :: `
|
|
5786
6213
|
: ""}${display(getStateType(curState, event.left))}`);
|
|
@@ -5792,13 +6219,13 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, logThisRun) {
|
|
|
5792
6219
|
}
|
|
5793
6220
|
return false;
|
|
5794
6221
|
};
|
|
5795
|
-
blockStates[0] = new Map();
|
|
6222
|
+
blockStates[0] = { map: new Map(), visits: 0 };
|
|
5796
6223
|
const head = blockStates[0];
|
|
5797
6224
|
// set the parameters to their initial types
|
|
5798
6225
|
func.node.params.forEach((param) => {
|
|
5799
6226
|
setStateEvent(head, param, param.type === "BinaryExpression"
|
|
5800
6227
|
? typeFromTypespec(state, param.right)
|
|
5801
|
-
: { type: 524287 /* TypeTag.Any */ },
|
|
6228
|
+
: { type: 524287 /* TypeTag.Any */ }, 0 /* UpdateKind.None */);
|
|
5802
6229
|
});
|
|
5803
6230
|
queue.enqueue(order[0]);
|
|
5804
6231
|
while (!queue.empty()) {
|
|
@@ -5808,7 +6235,7 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, logThisRun) {
|
|
|
5808
6235
|
}
|
|
5809
6236
|
if (!blockStates[top.order])
|
|
5810
6237
|
continue;
|
|
5811
|
-
const curState =
|
|
6238
|
+
const curState = cloneTypeState(blockStates[top.order]);
|
|
5812
6239
|
if (logThisRun) {
|
|
5813
6240
|
printBlockHeader(top);
|
|
5814
6241
|
printBlockState(top, curState);
|
|
@@ -5832,6 +6259,16 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, logThisRun) {
|
|
|
5832
6259
|
printBlockTrailer(top);
|
|
5833
6260
|
}
|
|
5834
6261
|
}
|
|
6262
|
+
nodeCopyProp.forEach((value, key) => {
|
|
6263
|
+
if (key.type === "VariableDeclarator" ||
|
|
6264
|
+
key.type === "AssignmentExpression") {
|
|
6265
|
+
if (value === false) {
|
|
6266
|
+
nodeCopyProp.delete(key);
|
|
6267
|
+
return;
|
|
6268
|
+
}
|
|
6269
|
+
assert(nodeCopyProp.get(value) === key);
|
|
6270
|
+
}
|
|
6271
|
+
});
|
|
5835
6272
|
if (logThisRun) {
|
|
5836
6273
|
order.forEach((block) => {
|
|
5837
6274
|
printBlockHeader(block);
|
|
@@ -5849,9 +6286,29 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, logThisRun) {
|
|
|
5849
6286
|
nodeEquivs.forEach((value, key) => {
|
|
5850
6287
|
console.log(`${formatAst(key)} = [${value.equiv.map((equiv) => tsKey(equiv))}] ${key.loc && key.loc.source ? ` (${sourceLocation(key.loc)})` : ""}`);
|
|
5851
6288
|
});
|
|
6289
|
+
console.log("====== Copy Prop =====");
|
|
6290
|
+
nodeCopyProp.forEach((value, key) => {
|
|
6291
|
+
assert(value !== false);
|
|
6292
|
+
if (key.type === "VariableDeclarator" ||
|
|
6293
|
+
key.type === "AssignmentExpression") {
|
|
6294
|
+
return;
|
|
6295
|
+
}
|
|
6296
|
+
assert((value.type === "VariableDeclarator" && value.init) ||
|
|
6297
|
+
value.type === "AssignmentExpression");
|
|
6298
|
+
const node = value.type === "VariableDeclarator" ? value.init : value.right;
|
|
6299
|
+
console.log(`${formatAst(key)} = [${formatAstLongLines(node)}] ${key.loc && key.loc.source ? ` (${sourceLocation(key.loc)})` : ""}`);
|
|
6300
|
+
});
|
|
6301
|
+
}
|
|
6302
|
+
if (logThisRun) {
|
|
6303
|
+
console.log(formatAstLongLines(func.node));
|
|
6304
|
+
if (copyPropStores) {
|
|
6305
|
+
copyPropStores.forEach(({ ref, ant }, node) => {
|
|
6306
|
+
console.log(`copy-prop-store: ${formatAstLongLines(node)}${ant ? "!" : ""} => ${nodeCopyProp.get(node) !== ref ? "Failed" : "Success"}`);
|
|
6307
|
+
});
|
|
6308
|
+
}
|
|
5852
6309
|
}
|
|
5853
6310
|
if (optimizeEquivalencies) {
|
|
5854
|
-
if (!nodeEquivs.size && !selfAssignments.size) {
|
|
6311
|
+
if (!nodeEquivs.size && !selfAssignments.size && !nodeCopyProp.size) {
|
|
5855
6312
|
return { istate, nodeEquivs };
|
|
5856
6313
|
}
|
|
5857
6314
|
if (logThisRun) {
|
|
@@ -5895,12 +6352,60 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, logThisRun) {
|
|
|
5895
6352
|
}
|
|
5896
6353
|
}));
|
|
5897
6354
|
traverseAst(func.node.body, null, (node) => {
|
|
6355
|
+
const copyNode = nodeCopyProp.get(node);
|
|
6356
|
+
if (copyNode) {
|
|
6357
|
+
if (node.type === "AssignmentExpression") {
|
|
6358
|
+
if (logThisRun) {
|
|
6359
|
+
console.log(`Killing copy-prop assignment ${formatAstLongLines(node)}`);
|
|
6360
|
+
}
|
|
6361
|
+
return withLoc({ type: "Literal", value: null, raw: "null" }, node, node);
|
|
6362
|
+
}
|
|
6363
|
+
if (node.type === "VariableDeclarator") {
|
|
6364
|
+
assert(node.init);
|
|
6365
|
+
if (logThisRun) {
|
|
6366
|
+
console.log(`Killing copy-prop variable initialization ${formatAstLongLines(node)}`);
|
|
6367
|
+
}
|
|
6368
|
+
const dup = { ...node };
|
|
6369
|
+
delete dup.init;
|
|
6370
|
+
return dup;
|
|
6371
|
+
}
|
|
6372
|
+
if (copyNode.type === "AssignmentExpression") {
|
|
6373
|
+
if (logThisRun) {
|
|
6374
|
+
console.log(`copy-prop ${formatAstLongLines(node)} => ${formatAstLongLines(copyNode.right)}`);
|
|
6375
|
+
}
|
|
6376
|
+
return withLocDeep(copyNode.right, node, node, false);
|
|
6377
|
+
}
|
|
6378
|
+
else if (copyNode.type === "VariableDeclarator") {
|
|
6379
|
+
assert(copyNode.init);
|
|
6380
|
+
if (logThisRun) {
|
|
6381
|
+
console.log(`copy-prop ${formatAstLongLines(node)} => ${formatAstLongLines(copyNode.init)}`);
|
|
6382
|
+
}
|
|
6383
|
+
return withLocDeep(copyNode.init, node, node, false);
|
|
6384
|
+
}
|
|
6385
|
+
assert(false);
|
|
6386
|
+
}
|
|
5898
6387
|
if (selfAssignments.has(node)) {
|
|
5899
6388
|
if (logThisRun) {
|
|
5900
6389
|
console.log(`Deleting self assignment: ${formatAst(node)} (${sourceLocation(node.loc)})`);
|
|
5901
6390
|
}
|
|
5902
6391
|
return withLoc({ type: "Literal", value: null, raw: "null" }, node, node);
|
|
5903
6392
|
}
|
|
6393
|
+
if (nodeCopyProp.size) {
|
|
6394
|
+
/*
|
|
6395
|
+
* Copy prop and equiv can interfere with each other:
|
|
6396
|
+
*
|
|
6397
|
+
* var c = g; // copy prop kills this
|
|
6398
|
+
* ...
|
|
6399
|
+
* var x = g + 2; // node equiv replaces g with c
|
|
6400
|
+
* ...
|
|
6401
|
+
* return c; // copy prop changes this to g
|
|
6402
|
+
*
|
|
6403
|
+
* So ignore equivalencies if copy prop is active.
|
|
6404
|
+
* Note that we have to re-run propagation anyway
|
|
6405
|
+
* if copy prop did anything.
|
|
6406
|
+
*/
|
|
6407
|
+
return null;
|
|
6408
|
+
}
|
|
5904
6409
|
const equiv = nodeEquivs.get(node);
|
|
5905
6410
|
if (!equiv || localConflicts.has(equiv.decl))
|
|
5906
6411
|
return null;
|
|
@@ -5952,7 +6457,62 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, logThisRun) {
|
|
|
5952
6457
|
return replacement;
|
|
5953
6458
|
});
|
|
5954
6459
|
}
|
|
5955
|
-
return {
|
|
6460
|
+
return {
|
|
6461
|
+
istate,
|
|
6462
|
+
nodeEquivs,
|
|
6463
|
+
redo: optimizeEquivalencies && nodeCopyProp.size,
|
|
6464
|
+
};
|
|
6465
|
+
}
|
|
6466
|
+
function updateByAssocPath(path, property, union) {
|
|
6467
|
+
const valueToStore = (base) => {
|
|
6468
|
+
const clone = cloneType(base);
|
|
6469
|
+
unionInto(clone, property);
|
|
6470
|
+
return clone;
|
|
6471
|
+
};
|
|
6472
|
+
for (let i = path.length; i--;) {
|
|
6473
|
+
const pathElem = path[i];
|
|
6474
|
+
let object = pathElem.type;
|
|
6475
|
+
if (pathElem.name) {
|
|
6476
|
+
const value = getObjectValue(object);
|
|
6477
|
+
if (value) {
|
|
6478
|
+
const obj = value.obj ? { ...value.obj } : {};
|
|
6479
|
+
obj[pathElem.name] = union
|
|
6480
|
+
? valueToStore(obj[pathElem.name] || { type: 524287 /* TypeTag.Any */ })
|
|
6481
|
+
: property;
|
|
6482
|
+
object = cloneType(object);
|
|
6483
|
+
setUnionComponent(object, 32768 /* TypeTag.Object */, {
|
|
6484
|
+
klass: value.klass,
|
|
6485
|
+
obj,
|
|
6486
|
+
});
|
|
6487
|
+
}
|
|
6488
|
+
}
|
|
6489
|
+
else {
|
|
6490
|
+
if (object.type & 512 /* TypeTag.Array */) {
|
|
6491
|
+
object = cloneType(object);
|
|
6492
|
+
setUnionComponent(object, 512 /* TypeTag.Array */, union
|
|
6493
|
+
? valueToStore(getUnionComponent(object, 512 /* TypeTag.Array */) || {
|
|
6494
|
+
type: 524287 /* TypeTag.Any */,
|
|
6495
|
+
})
|
|
6496
|
+
: property);
|
|
6497
|
+
}
|
|
6498
|
+
if (object.type & 1024 /* TypeTag.Dictionary */) {
|
|
6499
|
+
const dvalue = getUnionComponent(object, 1024 /* TypeTag.Dictionary */);
|
|
6500
|
+
object = cloneType(object);
|
|
6501
|
+
setUnionComponent(object, 1024 /* TypeTag.Dictionary */, {
|
|
6502
|
+
key: dvalue?.key || { type: 524287 /* TypeTag.Any */ },
|
|
6503
|
+
value: union
|
|
6504
|
+
? valueToStore(getUnionComponent(object, 1024 /* TypeTag.Dictionary */)?.value || {
|
|
6505
|
+
type: 524287 /* TypeTag.Any */,
|
|
6506
|
+
})
|
|
6507
|
+
: property,
|
|
6508
|
+
});
|
|
6509
|
+
}
|
|
6510
|
+
}
|
|
6511
|
+
path[i].type = object;
|
|
6512
|
+
property = object;
|
|
6513
|
+
union = false;
|
|
6514
|
+
}
|
|
6515
|
+
return property;
|
|
5956
6516
|
}
|
|
5957
6517
|
|
|
5958
6518
|
|
|
@@ -5962,7 +6522,7 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, logThisRun) {
|
|
|
5962
6522
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
5963
6523
|
|
|
5964
6524
|
"use strict";
|
|
5965
|
-
/* unused harmony exports couldBe, couldBeWeak */
|
|
6525
|
+
/* unused harmony exports couldBeHelper, couldBe, couldBeWeak, couldBeShallow */
|
|
5966
6526
|
/* harmony import */ var _api__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6817);
|
|
5967
6527
|
/* harmony import */ var _api__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_api__WEBPACK_IMPORTED_MODULE_0__);
|
|
5968
6528
|
/* harmony import */ var _data_flow__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(8180);
|
|
@@ -5980,7 +6540,7 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, logThisRun) {
|
|
|
5980
6540
|
* This is symmetric, and a subtypeOf b, or b subtypeOf a implies
|
|
5981
6541
|
* a couldBe b.
|
|
5982
6542
|
*/
|
|
5983
|
-
function
|
|
6543
|
+
function couldBeHelper(a, b, shallow) {
|
|
5984
6544
|
const common = a.type & b.type & ~262144 /* TypeTag.Typedef */;
|
|
5985
6545
|
if (common) {
|
|
5986
6546
|
if (a.value == null || b.value == null || a.value === b.value) {
|
|
@@ -6000,7 +6560,7 @@ function couldBe(a, b) {
|
|
|
6000
6560
|
const bvalue = getUnionComponent(b, ac.type);
|
|
6001
6561
|
if (bvalue == null ||
|
|
6002
6562
|
ac.value === bvalue ||
|
|
6003
|
-
couldBeValue({ type: ac.type, avalue: ac.value, bvalue })) {
|
|
6563
|
+
couldBeValue({ type: ac.type, avalue: ac.value, bvalue }, shallow)) {
|
|
6004
6564
|
result = true;
|
|
6005
6565
|
return false;
|
|
6006
6566
|
}
|
|
@@ -6050,12 +6610,19 @@ function couldBe(a, b) {
|
|
|
6050
6610
|
}
|
|
6051
6611
|
return false;
|
|
6052
6612
|
}
|
|
6613
|
+
function couldBe(a, b) {
|
|
6614
|
+
return couldBeHelper(a, b, false);
|
|
6615
|
+
}
|
|
6053
6616
|
function couldBeWeak(a, b) {
|
|
6054
6617
|
if (a.type === 0 /* TypeTag.Never */ || b.type === 0 /* TypeTag.Never */)
|
|
6055
6618
|
return true;
|
|
6056
6619
|
return couldBe(a, b);
|
|
6057
6620
|
}
|
|
6058
|
-
|
|
6621
|
+
//
|
|
6622
|
+
function couldBeShallow(a, b) {
|
|
6623
|
+
return couldBeHelper(a, b, true);
|
|
6624
|
+
}
|
|
6625
|
+
function couldBeValue(pair, shallow) {
|
|
6059
6626
|
switch (pair.type) {
|
|
6060
6627
|
case 1 /* TypeTag.Null */:
|
|
6061
6628
|
case 2 /* TypeTag.False */:
|
|
@@ -6071,10 +6638,11 @@ function couldBeValue(pair) {
|
|
|
6071
6638
|
case 131072 /* TypeTag.Symbol */:
|
|
6072
6639
|
return pair.avalue === pair.bvalue;
|
|
6073
6640
|
case 512 /* TypeTag.Array */:
|
|
6074
|
-
return couldBe(pair.avalue, pair.bvalue);
|
|
6641
|
+
return shallow || couldBe(pair.avalue, pair.bvalue);
|
|
6075
6642
|
case 1024 /* TypeTag.Dictionary */: {
|
|
6076
|
-
return (
|
|
6077
|
-
couldBe(pair.avalue.
|
|
6643
|
+
return (shallow ||
|
|
6644
|
+
(couldBe(pair.avalue.key, pair.bvalue.key) &&
|
|
6645
|
+
couldBe(pair.avalue.value, pair.bvalue.value)));
|
|
6078
6646
|
}
|
|
6079
6647
|
case 2048 /* TypeTag.Method */: {
|
|
6080
6648
|
return (pair.avalue.args.length === pair.bvalue.args.length &&
|
|
@@ -6100,7 +6668,7 @@ function couldBeValue(pair) {
|
|
|
6100
6668
|
}
|
|
6101
6669
|
case 32768 /* TypeTag.Object */: {
|
|
6102
6670
|
return (couldBe(pair.avalue.klass, pair.bvalue.klass) &&
|
|
6103
|
-
couldBeObj(pair.avalue.obj, pair.bvalue.obj));
|
|
6671
|
+
(shallow || couldBeObj(pair.avalue.obj, pair.bvalue.obj)));
|
|
6104
6672
|
}
|
|
6105
6673
|
case 65536 /* TypeTag.Enum */: {
|
|
6106
6674
|
return (pair.avalue.enum === pair.bvalue.enum &&
|
|
@@ -6130,20 +6698,48 @@ function couldBeObj(a, b) {
|
|
|
6130
6698
|
|
|
6131
6699
|
"use strict";
|
|
6132
6700
|
/* unused harmony exports findDeadStores, eliminateDeadStores */
|
|
6133
|
-
/* harmony import */ var
|
|
6134
|
-
/* harmony import */ var
|
|
6135
|
-
/* harmony import */ var
|
|
6136
|
-
/* harmony import */ var
|
|
6137
|
-
/* harmony import */ var
|
|
6138
|
-
/* harmony import */ var
|
|
6139
|
-
/* harmony import */ var
|
|
6701
|
+
/* harmony import */ var node_assert__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4143);
|
|
6702
|
+
/* harmony import */ var node_assert__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(node_assert__WEBPACK_IMPORTED_MODULE_0__);
|
|
6703
|
+
/* harmony import */ var _api__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6817);
|
|
6704
|
+
/* harmony import */ var _api__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_api__WEBPACK_IMPORTED_MODULE_1__);
|
|
6705
|
+
/* harmony import */ var _ast__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(6652);
|
|
6706
|
+
/* harmony import */ var _control_flow__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(5101);
|
|
6707
|
+
/* harmony import */ var _data_flow__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(8180);
|
|
6708
|
+
/* harmony import */ var _inliner__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(333);
|
|
6709
|
+
/* harmony import */ var _type_flow_util__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(1638);
|
|
6140
6710
|
|
|
6141
6711
|
|
|
6142
6712
|
|
|
6143
6713
|
|
|
6144
6714
|
|
|
6145
6715
|
|
|
6146
|
-
|
|
6716
|
+
|
|
6717
|
+
function cloneAnt(antMap) {
|
|
6718
|
+
const ant = new Map();
|
|
6719
|
+
antMap.forEach((s, k) => ant.set(k, new Set(s)));
|
|
6720
|
+
return ant;
|
|
6721
|
+
}
|
|
6722
|
+
function addAnt(antMap, decl, node) {
|
|
6723
|
+
assert(node.type === "Identifier");
|
|
6724
|
+
const ant = antMap.get(decl);
|
|
6725
|
+
if (!ant) {
|
|
6726
|
+
antMap.set(decl, new Set([node]));
|
|
6727
|
+
}
|
|
6728
|
+
else {
|
|
6729
|
+
ant.add(node);
|
|
6730
|
+
}
|
|
6731
|
+
}
|
|
6732
|
+
function cloneState(blockState) {
|
|
6733
|
+
const clone = { dead: new Set(blockState.dead) };
|
|
6734
|
+
if (blockState.anticipated) {
|
|
6735
|
+
clone.anticipated = cloneAnt(blockState.anticipated);
|
|
6736
|
+
}
|
|
6737
|
+
if (blockState.partiallyAnticipated) {
|
|
6738
|
+
clone.partiallyAnticipated = cloneAnt(blockState.partiallyAnticipated);
|
|
6739
|
+
}
|
|
6740
|
+
return clone;
|
|
6741
|
+
}
|
|
6742
|
+
function findDeadStores(func, graph, nodeEquivs, findCopyPropCandidates, logThisRun) {
|
|
6147
6743
|
const order = getPostOrder(graph);
|
|
6148
6744
|
order.forEach((block, i) => {
|
|
6149
6745
|
block.order = i;
|
|
@@ -6151,13 +6747,62 @@ function findDeadStores(func, graph, nodeEquivs, logThisRun) {
|
|
|
6151
6747
|
const blockStates = [];
|
|
6152
6748
|
const nodeConflicts = nodeEquivs && new Map();
|
|
6153
6749
|
const mergeStates = (to, from) => {
|
|
6154
|
-
|
|
6155
|
-
if (!from.has(decl)) {
|
|
6156
|
-
to.delete(decl);
|
|
6750
|
+
let changed = Array.from(to.dead).reduce((changed, decl) => {
|
|
6751
|
+
if (!from.dead.has(decl)) {
|
|
6752
|
+
to.dead.delete(decl);
|
|
6157
6753
|
changed = true;
|
|
6158
6754
|
}
|
|
6159
6755
|
return changed;
|
|
6160
6756
|
}, false);
|
|
6757
|
+
if (to.anticipated) {
|
|
6758
|
+
if (!from.anticipated) {
|
|
6759
|
+
delete to.anticipated;
|
|
6760
|
+
changed = true;
|
|
6761
|
+
}
|
|
6762
|
+
else {
|
|
6763
|
+
changed = Array.from(to.anticipated).reduce((changed, [decl, toant]) => {
|
|
6764
|
+
const fromant = from.anticipated.get(decl);
|
|
6765
|
+
if (!fromant) {
|
|
6766
|
+
to.anticipated.delete(decl);
|
|
6767
|
+
changed = true;
|
|
6768
|
+
}
|
|
6769
|
+
else {
|
|
6770
|
+
toant.forEach((node) => {
|
|
6771
|
+
if (!fromant.has(node)) {
|
|
6772
|
+
toant.delete(node);
|
|
6773
|
+
changed = true;
|
|
6774
|
+
}
|
|
6775
|
+
});
|
|
6776
|
+
}
|
|
6777
|
+
return changed;
|
|
6778
|
+
}, changed);
|
|
6779
|
+
}
|
|
6780
|
+
}
|
|
6781
|
+
if (from.partiallyAnticipated) {
|
|
6782
|
+
if (!to.partiallyAnticipated) {
|
|
6783
|
+
to.partiallyAnticipated = cloneAnt(from.partiallyAnticipated);
|
|
6784
|
+
changed = true;
|
|
6785
|
+
}
|
|
6786
|
+
else {
|
|
6787
|
+
changed = Array.from(from.partiallyAnticipated).reduce((changed, [decl, fromant]) => {
|
|
6788
|
+
const toant = to.partiallyAnticipated.get(decl);
|
|
6789
|
+
if (!toant) {
|
|
6790
|
+
to.partiallyAnticipated.set(decl, fromant);
|
|
6791
|
+
changed = true;
|
|
6792
|
+
}
|
|
6793
|
+
else {
|
|
6794
|
+
fromant.forEach((node) => {
|
|
6795
|
+
if (!toant.has(node)) {
|
|
6796
|
+
changed = true;
|
|
6797
|
+
toant.add(node);
|
|
6798
|
+
}
|
|
6799
|
+
});
|
|
6800
|
+
}
|
|
6801
|
+
return changed;
|
|
6802
|
+
}, changed);
|
|
6803
|
+
}
|
|
6804
|
+
}
|
|
6805
|
+
return changed;
|
|
6161
6806
|
};
|
|
6162
6807
|
const queue = new DataflowQueue();
|
|
6163
6808
|
const locals = new Set(order
|
|
@@ -6168,10 +6813,11 @@ function findDeadStores(func, graph, nodeEquivs, logThisRun) {
|
|
|
6168
6813
|
: [])
|
|
6169
6814
|
.concat(func.node.params));
|
|
6170
6815
|
const deadStores = new Set();
|
|
6816
|
+
const copyPropStores = new Map();
|
|
6171
6817
|
order.forEach((block) => {
|
|
6172
6818
|
if (!block.succs) {
|
|
6173
6819
|
queue.enqueue(block);
|
|
6174
|
-
blockStates[block.order] = new Set(locals);
|
|
6820
|
+
blockStates[block.order] = { dead: new Set(locals) };
|
|
6175
6821
|
}
|
|
6176
6822
|
});
|
|
6177
6823
|
while (!queue.empty()) {
|
|
@@ -6182,10 +6828,10 @@ function findDeadStores(func, graph, nodeEquivs, logThisRun) {
|
|
|
6182
6828
|
if (!blockStates[top.order]) {
|
|
6183
6829
|
throw new Error(`Block ${top.order || 0} had no state!`);
|
|
6184
6830
|
}
|
|
6185
|
-
const curState =
|
|
6831
|
+
const curState = cloneState(blockStates[top.order]);
|
|
6186
6832
|
if (logThisRun) {
|
|
6187
6833
|
printBlockHeader(top);
|
|
6188
|
-
curState.forEach((decl) => console.log(` - anticipated: ${tsKey(decl)}`));
|
|
6834
|
+
curState.dead.forEach((decl) => console.log(` - anticipated: ${tsKey(decl)}`));
|
|
6189
6835
|
}
|
|
6190
6836
|
if (top.events) {
|
|
6191
6837
|
for (let i = top.events.length; i--;) {
|
|
@@ -6200,33 +6846,67 @@ function findDeadStores(func, graph, nodeEquivs, logThisRun) {
|
|
|
6200
6846
|
switch (event.type) {
|
|
6201
6847
|
case "ref":
|
|
6202
6848
|
if (isTypeStateKey(event.decl)) {
|
|
6203
|
-
curState.delete(event.decl);
|
|
6204
6849
|
if (logThisRun) {
|
|
6850
|
+
console.log(describeEvent(event));
|
|
6205
6851
|
console.log(` kill => ${tsKey(event.decl)}`);
|
|
6206
6852
|
}
|
|
6853
|
+
if (findCopyPropCandidates && declIsLocal(event.decl)) {
|
|
6854
|
+
if (!curState.anticipated) {
|
|
6855
|
+
curState.anticipated = new Map();
|
|
6856
|
+
}
|
|
6857
|
+
addAnt(curState.anticipated, event.decl, event.node);
|
|
6858
|
+
if (!curState.partiallyAnticipated) {
|
|
6859
|
+
curState.partiallyAnticipated = new Map();
|
|
6860
|
+
}
|
|
6861
|
+
addAnt(curState.partiallyAnticipated, event.decl, event.node);
|
|
6862
|
+
if (logThisRun) {
|
|
6863
|
+
console.log(` antrefs: ${curState.partiallyAnticipated.get(event.decl)?.size ?? 0} ${curState.anticipated.get(event.decl)?.size ?? 0}`);
|
|
6864
|
+
}
|
|
6865
|
+
}
|
|
6866
|
+
curState.dead.delete(event.decl);
|
|
6207
6867
|
}
|
|
6208
6868
|
break;
|
|
6209
6869
|
case "def":
|
|
6210
6870
|
if (isTypeStateKey(event.decl) &&
|
|
6211
6871
|
(event.node.type !== "VariableDeclarator" || event.node.init)) {
|
|
6212
|
-
if (
|
|
6872
|
+
if (logThisRun) {
|
|
6873
|
+
console.log(describeEvent(event));
|
|
6874
|
+
}
|
|
6875
|
+
const assignNode = (event.node.type === "AssignmentExpression" &&
|
|
6876
|
+
event.node.operator === "=" &&
|
|
6877
|
+
event.node.right) ||
|
|
6878
|
+
(event.node.type === "VariableDeclarator" && event.node.init);
|
|
6879
|
+
if (curState.dead.has(event.decl)) {
|
|
6213
6880
|
deadStores.add(event.node);
|
|
6214
6881
|
}
|
|
6215
6882
|
else {
|
|
6216
6883
|
deadStores.delete(event.node);
|
|
6884
|
+
if (assignNode &&
|
|
6885
|
+
declIsLocal(event.decl) &&
|
|
6886
|
+
curState.partiallyAnticipated) {
|
|
6887
|
+
const pant = curState.partiallyAnticipated.get(event.decl);
|
|
6888
|
+
if (pant && pant.size === 1) {
|
|
6889
|
+
if (logThisRun) {
|
|
6890
|
+
console.log(` is copy-prop-candidate ${curState.anticipated?.get(event.decl)?.size ?? 0}`);
|
|
6891
|
+
}
|
|
6892
|
+
copyPropStores.set(event.node, {
|
|
6893
|
+
ref: Array.from(pant)[0],
|
|
6894
|
+
ant: curState.anticipated?.get(event.decl)?.size === 1,
|
|
6895
|
+
});
|
|
6896
|
+
}
|
|
6897
|
+
curState.partiallyAnticipated.delete(event.decl);
|
|
6898
|
+
curState.anticipated?.delete(event.decl);
|
|
6899
|
+
}
|
|
6900
|
+
else {
|
|
6901
|
+
copyPropStores.delete(event.node);
|
|
6902
|
+
}
|
|
6217
6903
|
}
|
|
6218
6904
|
if (nodeConflicts) {
|
|
6219
6905
|
const conflicts = new Set(locals);
|
|
6220
|
-
curState.forEach((dead) => conflicts.delete(dead));
|
|
6906
|
+
curState.dead.forEach((dead) => conflicts.delete(dead));
|
|
6221
6907
|
if (event.rhs) {
|
|
6222
6908
|
conflicts.delete(event.rhs);
|
|
6223
|
-
const equiv =
|
|
6224
|
-
event.node.operator === "="
|
|
6225
|
-
? nodeEquivs.get(event.node.right)
|
|
6226
|
-
: event.node.type === "VariableDeclarator" &&
|
|
6227
|
-
event.node.init
|
|
6228
|
-
? nodeEquivs.get(event.node.init)
|
|
6229
|
-
: null;
|
|
6909
|
+
const equiv = assignNode && nodeEquivs.get(assignNode);
|
|
6230
6910
|
if (equiv) {
|
|
6231
6911
|
equiv.equiv.forEach((e) => isTypeStateKey(e) && conflicts.delete(e));
|
|
6232
6912
|
isTypeStateKey(equiv.decl) && conflicts.delete(equiv.decl);
|
|
@@ -6235,10 +6915,8 @@ function findDeadStores(func, graph, nodeEquivs, logThisRun) {
|
|
|
6235
6915
|
conflicts.add(event.decl);
|
|
6236
6916
|
nodeConflicts.set(event.node, conflicts);
|
|
6237
6917
|
}
|
|
6238
|
-
if (
|
|
6239
|
-
event.
|
|
6240
|
-
(event.node.type === "VariableDeclarator" && event.node.init)) {
|
|
6241
|
-
curState.add(event.decl);
|
|
6918
|
+
if (assignNode) {
|
|
6919
|
+
curState.dead.add(event.decl);
|
|
6242
6920
|
if (logThisRun) {
|
|
6243
6921
|
console.log(` anticipated => ${tsKey(event.decl)}`);
|
|
6244
6922
|
}
|
|
@@ -6247,14 +6925,14 @@ function findDeadStores(func, graph, nodeEquivs, logThisRun) {
|
|
|
6247
6925
|
break;
|
|
6248
6926
|
case "kil":
|
|
6249
6927
|
if (isTypeStateKey(event.decl)) {
|
|
6250
|
-
curState.add(event.decl);
|
|
6928
|
+
curState.dead.add(event.decl);
|
|
6251
6929
|
if (logThisRun) {
|
|
6252
6930
|
console.log(` anticipated => ${tsKey(event.decl)}`);
|
|
6253
6931
|
}
|
|
6254
6932
|
}
|
|
6255
6933
|
break;
|
|
6256
6934
|
case "mod":
|
|
6257
|
-
curState.forEach((decl) => declIsLocal(decl) || curState.delete(decl));
|
|
6935
|
+
curState.dead.forEach((decl) => declIsLocal(decl) || curState.dead.delete(decl));
|
|
6258
6936
|
break;
|
|
6259
6937
|
case "flw":
|
|
6260
6938
|
break;
|
|
@@ -6264,7 +6942,7 @@ function findDeadStores(func, graph, nodeEquivs, logThisRun) {
|
|
|
6264
6942
|
const doMerge = (pred) => {
|
|
6265
6943
|
const pi = pred.order || 0;
|
|
6266
6944
|
if (!blockStates[pi]) {
|
|
6267
|
-
blockStates[pi] =
|
|
6945
|
+
blockStates[pi] = cloneState(curState);
|
|
6268
6946
|
queue.enqueue(pred);
|
|
6269
6947
|
}
|
|
6270
6948
|
else if (mergeStates(blockStates[pi], curState)) {
|
|
@@ -6296,15 +6974,18 @@ function findDeadStores(func, graph, nodeEquivs, logThisRun) {
|
|
|
6296
6974
|
nodeConflicts.forEach((conflicts) => conflicts.forEach((conflict) => addConflicts(conflict, conflicts)));
|
|
6297
6975
|
func.node.params.forEach((param, index, arr) => addConflicts(param, arr));
|
|
6298
6976
|
}
|
|
6299
|
-
return { deadStores, locals, localConflicts };
|
|
6977
|
+
return { deadStores, locals, localConflicts, copyPropStores };
|
|
6300
6978
|
}
|
|
6301
6979
|
function eliminateDeadStores(state, func, graph, logThisRun) {
|
|
6302
|
-
const { deadStores } = findDeadStores(func, graph, null, logThisRun);
|
|
6980
|
+
const { deadStores, copyPropStores } = findDeadStores(func, graph, null, state.config?.singleUseCopyProp ?? true, logThisRun);
|
|
6303
6981
|
if (!deadStores.size)
|
|
6304
|
-
return false;
|
|
6982
|
+
return { changes: false, copyPropStores };
|
|
6305
6983
|
if (logThisRun) {
|
|
6306
6984
|
console.log("====== Dead Stores =====");
|
|
6307
|
-
deadStores.forEach((dead) =>
|
|
6985
|
+
deadStores.forEach((dead) => (dead.type === "AssignmentExpression" ||
|
|
6986
|
+
dead.type === "UpdateExpression" ||
|
|
6987
|
+
dead.type === "VariableDeclarator") &&
|
|
6988
|
+
console.log(`${formatAst(dead)} (${sourceLocation(dead.loc)})`));
|
|
6308
6989
|
}
|
|
6309
6990
|
let changes = false;
|
|
6310
6991
|
traverseAst(func.node.body, null, (node, parent) => {
|
|
@@ -6367,7 +7048,7 @@ function eliminateDeadStores(state, func, graph, logThisRun) {
|
|
|
6367
7048
|
}
|
|
6368
7049
|
return null;
|
|
6369
7050
|
});
|
|
6370
|
-
return changes;
|
|
7051
|
+
return { copyPropStores, changes };
|
|
6371
7052
|
}
|
|
6372
7053
|
|
|
6373
7054
|
|
|
@@ -6378,9 +7059,13 @@ function eliminateDeadStores(state, func, graph, logThisRun) {
|
|
|
6378
7059
|
|
|
6379
7060
|
"use strict";
|
|
6380
7061
|
/* unused harmony exports evaluateBinaryTypes, evaluateLogicalTypes */
|
|
6381
|
-
/* harmony import */ var
|
|
6382
|
-
/* harmony import */ var
|
|
6383
|
-
/* harmony import */ var
|
|
7062
|
+
/* harmony import */ var _could_be__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4055);
|
|
7063
|
+
/* harmony import */ var _interp__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(7161);
|
|
7064
|
+
/* harmony import */ var _sub_type__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(9234);
|
|
7065
|
+
/* harmony import */ var _types__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(7255);
|
|
7066
|
+
/* harmony import */ var _union_type__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(757);
|
|
7067
|
+
|
|
7068
|
+
|
|
6384
7069
|
|
|
6385
7070
|
|
|
6386
7071
|
|
|
@@ -6711,14 +7396,6 @@ function evaluateBinaryTypes(op, left, right) {
|
|
|
6711
7396
|
: 2 /* TypeTag.False */,
|
|
6712
7397
|
}),
|
|
6713
7398
|
},
|
|
6714
|
-
instanceof: {
|
|
6715
|
-
allowed: 524287 /* TypeTag.Any */,
|
|
6716
|
-
typeFn: () => ({
|
|
6717
|
-
tag: 6 /* TypeTag.Boolean */,
|
|
6718
|
-
castArgs: false,
|
|
6719
|
-
}),
|
|
6720
|
-
valueFn: (_left, _right) => undefined,
|
|
6721
|
-
},
|
|
6722
7399
|
has: {
|
|
6723
7400
|
allowed: 524287 /* TypeTag.Any */,
|
|
6724
7401
|
typeFn: () => ({
|
|
@@ -6729,6 +7406,21 @@ function evaluateBinaryTypes(op, left, right) {
|
|
|
6729
7406
|
},
|
|
6730
7407
|
};
|
|
6731
7408
|
}
|
|
7409
|
+
if (op === "instanceof") {
|
|
7410
|
+
if (right.type & 16384 /* TypeTag.Class */) {
|
|
7411
|
+
if (!isExact(right)) {
|
|
7412
|
+
return { type: 6 /* TypeTag.Boolean */ };
|
|
7413
|
+
}
|
|
7414
|
+
right = { type: 32768 /* TypeTag.Object */, value: { klass: right } };
|
|
7415
|
+
}
|
|
7416
|
+
return {
|
|
7417
|
+
type: subtypeOf(left, right)
|
|
7418
|
+
? 4 /* TypeTag.True */
|
|
7419
|
+
: !couldBeWeak(left, right)
|
|
7420
|
+
? 2 /* TypeTag.False */
|
|
7421
|
+
: 6 /* TypeTag.Boolean */,
|
|
7422
|
+
};
|
|
7423
|
+
}
|
|
6732
7424
|
const info = operators[op];
|
|
6733
7425
|
if (!info)
|
|
6734
7426
|
return { type: 524287 /* TypeTag.Any */ };
|
|
@@ -6787,15 +7479,15 @@ function evaluateLogicalTypes(op, left, right) {
|
|
|
6787
7479
|
"use strict";
|
|
6788
7480
|
/* unused harmony exports evaluateCall, checkCallArgs, sysCallInfo */
|
|
6789
7481
|
/* harmony import */ var _optimizer_types__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(9697);
|
|
6790
|
-
/* harmony import */ var
|
|
6791
|
-
/* harmony import */ var
|
|
6792
|
-
/* harmony import */ var
|
|
6793
|
-
/* harmony import */ var
|
|
6794
|
-
/* harmony import */ var
|
|
6795
|
-
/* harmony import */ var
|
|
6796
|
-
/* harmony import */ var
|
|
6797
|
-
/* harmony import */ var
|
|
6798
|
-
/* harmony import */ var
|
|
7482
|
+
/* harmony import */ var _api__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6817);
|
|
7483
|
+
/* harmony import */ var _api__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_api__WEBPACK_IMPORTED_MODULE_1__);
|
|
7484
|
+
/* harmony import */ var _util__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(6906);
|
|
7485
|
+
/* harmony import */ var _util__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_util__WEBPACK_IMPORTED_MODULE_2__);
|
|
7486
|
+
/* harmony import */ var _interp__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(7161);
|
|
7487
|
+
/* harmony import */ var _sub_type__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(9234);
|
|
7488
|
+
/* harmony import */ var _types__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(7255);
|
|
7489
|
+
/* harmony import */ var _union_type__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(757);
|
|
7490
|
+
/* harmony import */ var _type_flow_util__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(1638);
|
|
6799
7491
|
|
|
6800
7492
|
|
|
6801
7493
|
|
|
@@ -6851,7 +7543,7 @@ function checkCallArgs(istate, node, callees, args) {
|
|
|
6851
7543
|
let argEffects = true;
|
|
6852
7544
|
const object = calleeObjectType(istate, node.callee);
|
|
6853
7545
|
if (object) {
|
|
6854
|
-
const info = sysCallInfo(cur);
|
|
7546
|
+
const info = sysCallInfo(istate.state, cur);
|
|
6855
7547
|
if (info) {
|
|
6856
7548
|
const result = info(istate.state, cur, object, () => args);
|
|
6857
7549
|
if (result.argTypes)
|
|
@@ -6982,16 +7674,18 @@ function isOverride(cur, funcs) {
|
|
|
6982
7674
|
return false;
|
|
6983
7675
|
}
|
|
6984
7676
|
let systemCallInfo = null;
|
|
6985
|
-
|
|
6986
|
-
|
|
7677
|
+
let systemCallVersion;
|
|
7678
|
+
function sysCallInfo(state, func) {
|
|
7679
|
+
const info = getSystemCallTable(state);
|
|
6987
7680
|
if (hasProperty(info, func.fullName)) {
|
|
6988
7681
|
return info[func.fullName];
|
|
6989
7682
|
}
|
|
6990
7683
|
return null;
|
|
6991
7684
|
}
|
|
6992
|
-
function getSystemCallTable() {
|
|
6993
|
-
if (systemCallInfo)
|
|
7685
|
+
function getSystemCallTable(state) {
|
|
7686
|
+
if (systemCallInfo && systemCallVersion === state.sdk) {
|
|
6994
7687
|
return systemCallInfo;
|
|
7688
|
+
}
|
|
6995
7689
|
const arrayAdd = (state, callee, calleeObj, getArgs) => {
|
|
6996
7690
|
const ret = {};
|
|
6997
7691
|
if (calleeObj.type & 512 /* TypeTag.Array */) {
|
|
@@ -7211,7 +7905,8 @@ function getSystemCallTable() {
|
|
|
7211
7905
|
}
|
|
7212
7906
|
return results;
|
|
7213
7907
|
};
|
|
7214
|
-
|
|
7908
|
+
systemCallVersion = state.sdk;
|
|
7909
|
+
return (systemCallInfo = expandKeys(state, {
|
|
7215
7910
|
"$.Toybox.Lang.Array.add": arrayAdd,
|
|
7216
7911
|
"$.Toybox.Lang.Array.addAll": arrayAdd,
|
|
7217
7912
|
"$.Toybox.Lang.Array.remove": mod,
|
|
@@ -7254,7 +7949,47 @@ function getSystemCallTable() {
|
|
|
7254
7949
|
"$.Toybox.Math.variance": nop,
|
|
7255
7950
|
"$.Toybox.Math.srand": mod,
|
|
7256
7951
|
"$.Toybox.Math.rand": mod,
|
|
7952
|
+
"$.Toybox.Lang.*.(to*|equals|abs)": nop,
|
|
7953
|
+
"$.Toybox.Time.Gregorian.(duration|info|localMoment|moment|utcInfo)": nop,
|
|
7954
|
+
"$.Toybox.Time.(Duration|LocalMoment|Moment).(?!initialize)*": nop,
|
|
7955
|
+
"$.Toybox.Graphics.Dc.get*": nop,
|
|
7956
|
+
}));
|
|
7957
|
+
}
|
|
7958
|
+
function expandKeys(state, table) {
|
|
7959
|
+
const result = {};
|
|
7960
|
+
const pattern = /[*()|]/;
|
|
7961
|
+
Object.entries(table).forEach(([key, value]) => {
|
|
7962
|
+
if (!pattern.test(key)) {
|
|
7963
|
+
result[key] = value;
|
|
7964
|
+
return;
|
|
7965
|
+
}
|
|
7966
|
+
if (state.stack) {
|
|
7967
|
+
const decls = key
|
|
7968
|
+
.split(".")
|
|
7969
|
+
.slice(1)
|
|
7970
|
+
.reduce((decls, decl) => {
|
|
7971
|
+
if (pattern.test(decl)) {
|
|
7972
|
+
const re = new RegExp(`^${decl.replace(/\*/g, ".*")}$`);
|
|
7973
|
+
return decls.flatMap((sn) => isStateNode(sn) && sn.decls
|
|
7974
|
+
? Object.keys(sn.decls)
|
|
7975
|
+
.filter((m) => re.test(m))
|
|
7976
|
+
.flatMap((m) => sn.decls[m])
|
|
7977
|
+
: []);
|
|
7978
|
+
}
|
|
7979
|
+
else {
|
|
7980
|
+
return decls.flatMap((sn) => (isStateNode(sn) && sn.decls?.[decl]) || []);
|
|
7981
|
+
}
|
|
7982
|
+
}, [state.stack[0].sn]);
|
|
7983
|
+
decls.forEach((decl) => {
|
|
7984
|
+
if (decl.type === "FunctionDeclaration") {
|
|
7985
|
+
if (!hasProperty(result, decl.fullName)) {
|
|
7986
|
+
result[decl.fullName] = value;
|
|
7987
|
+
}
|
|
7988
|
+
}
|
|
7989
|
+
});
|
|
7990
|
+
}
|
|
7257
7991
|
});
|
|
7992
|
+
return result;
|
|
7258
7993
|
}
|
|
7259
7994
|
|
|
7260
7995
|
|
|
@@ -7270,11 +8005,11 @@ function getSystemCallTable() {
|
|
|
7270
8005
|
/* harmony import */ var _ast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6652);
|
|
7271
8006
|
/* harmony import */ var _data_flow__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(8180);
|
|
7272
8007
|
/* harmony import */ var _optimizer_types__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(9697);
|
|
7273
|
-
/* harmony import */ var
|
|
7274
|
-
/* harmony import */ var
|
|
7275
|
-
/* harmony import */ var
|
|
7276
|
-
/* harmony import */ var
|
|
7277
|
-
/* harmony import */ var
|
|
8008
|
+
/* harmony import */ var _could_be__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(4055);
|
|
8009
|
+
/* harmony import */ var _interp_binary__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(4706);
|
|
8010
|
+
/* harmony import */ var _interp_call__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(2222);
|
|
8011
|
+
/* harmony import */ var _sub_type__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(9234);
|
|
8012
|
+
/* harmony import */ var _type_flow_util__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(1638);
|
|
7278
8013
|
/* harmony import */ var _types__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(7255);
|
|
7279
8014
|
/* harmony import */ var _union_type__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(757);
|
|
7280
8015
|
|
|
@@ -8610,12 +9345,14 @@ function restrictByEquality(a, b) {
|
|
|
8610
9345
|
/* unused harmony export minimizeLocals */
|
|
8611
9346
|
/* harmony import */ var node_assert__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4143);
|
|
8612
9347
|
/* harmony import */ var node_assert__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(node_assert__WEBPACK_IMPORTED_MODULE_0__);
|
|
8613
|
-
/* harmony import */ var
|
|
8614
|
-
/* harmony import */ var
|
|
8615
|
-
/* harmony import */ var
|
|
8616
|
-
/* harmony import */ var
|
|
9348
|
+
/* harmony import */ var _api__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6817);
|
|
9349
|
+
/* harmony import */ var _api__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_api__WEBPACK_IMPORTED_MODULE_1__);
|
|
9350
|
+
/* harmony import */ var _ast__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(6652);
|
|
9351
|
+
/* harmony import */ var _control_flow__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(5101);
|
|
8617
9352
|
/* harmony import */ var _type_flow__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(4859);
|
|
8618
|
-
/* harmony import */ var
|
|
9353
|
+
/* harmony import */ var _variable_renamer__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(4405);
|
|
9354
|
+
/* harmony import */ var _type_flow_util__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(1638);
|
|
9355
|
+
|
|
8619
9356
|
|
|
8620
9357
|
|
|
8621
9358
|
|
|
@@ -8763,8 +9500,7 @@ function minimizeLocals(state, func) {
|
|
|
8763
9500
|
switch (node.type) {
|
|
8764
9501
|
case "Identifier":
|
|
8765
9502
|
if (info && info.name !== node.name) {
|
|
8766
|
-
node
|
|
8767
|
-
node.name = info.name;
|
|
9503
|
+
renameIdentifier(node, info.name);
|
|
8768
9504
|
}
|
|
8769
9505
|
return null;
|
|
8770
9506
|
case "AssignmentExpression":
|
|
@@ -8775,8 +9511,7 @@ function minimizeLocals(state, func) {
|
|
|
8775
9511
|
return withLoc({ type: "Literal", value: null, raw: "null" }, node, node);
|
|
8776
9512
|
}
|
|
8777
9513
|
if (node.left.name !== info.name) {
|
|
8778
|
-
node.left
|
|
8779
|
-
node.left.name = info.name;
|
|
9514
|
+
renameIdentifier(node.left, info.name);
|
|
8780
9515
|
}
|
|
8781
9516
|
return null;
|
|
8782
9517
|
}
|
|
@@ -8790,8 +9525,7 @@ function minimizeLocals(state, func) {
|
|
|
8790
9525
|
if (info) {
|
|
8791
9526
|
assert(node.argument.type === "Identifier");
|
|
8792
9527
|
if (node.argument.name !== info.name) {
|
|
8793
|
-
node.argument
|
|
8794
|
-
node.argument.name = info.name;
|
|
9528
|
+
renameIdentifier(node.argument, info.name);
|
|
8795
9529
|
}
|
|
8796
9530
|
return null;
|
|
8797
9531
|
}
|
|
@@ -8934,6 +9668,24 @@ function optimizeFunction(state, func) {
|
|
|
8934
9668
|
}
|
|
8935
9669
|
function beforeEvaluate(istate, node) {
|
|
8936
9670
|
switch (node.type) {
|
|
9671
|
+
case "ExpressionStatement": {
|
|
9672
|
+
if (node.expression.type !== "Literal") {
|
|
9673
|
+
const expression = popIstate(istate, node.expression);
|
|
9674
|
+
if (expression.embeddedEffects) {
|
|
9675
|
+
istate.stack.push(expression);
|
|
9676
|
+
}
|
|
9677
|
+
else {
|
|
9678
|
+
const rep = withLoc({ type: "Literal", value: null, raw: "null" }, node, node);
|
|
9679
|
+
istate.stack.push({
|
|
9680
|
+
value: { type: 1 /* TypeTag.Null */ },
|
|
9681
|
+
embeddedEffects: false,
|
|
9682
|
+
node: rep,
|
|
9683
|
+
});
|
|
9684
|
+
node.expression = rep;
|
|
9685
|
+
}
|
|
9686
|
+
}
|
|
9687
|
+
break;
|
|
9688
|
+
}
|
|
8937
9689
|
case "ConditionalExpression": {
|
|
8938
9690
|
let alternate = tryPop(istate, node.alternate);
|
|
8939
9691
|
let consequent = tryPop(istate, node.consequent);
|
|
@@ -9679,12 +10431,23 @@ function subtypeOfObj(a, b) {
|
|
|
9679
10431
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
9680
10432
|
|
|
9681
10433
|
"use strict";
|
|
9682
|
-
/*
|
|
10434
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
10435
|
+
/* harmony export */ "nK": () => (/* binding */ findObjectDeclsByProperty)
|
|
10436
|
+
/* harmony export */ });
|
|
10437
|
+
/* unused harmony exports isTypeStateKey, declIsLocal, declIsNonLocal, localDeclName, tsKey, sourceLocation, printBlockHeader, describeEvent, printBlockEvents, printBlockTrailer, refineObjectTypeByDecls, findNextObjectType, resolveDottedMember */
|
|
9683
10438
|
/* harmony import */ var _api__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6817);
|
|
9684
10439
|
/* harmony import */ var _api__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_api__WEBPACK_IMPORTED_MODULE_0__);
|
|
9685
10440
|
/* harmony import */ var _data_flow__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(8180);
|
|
9686
10441
|
/* harmony import */ var _util__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(6906);
|
|
9687
10442
|
/* harmony import */ var _util__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_util__WEBPACK_IMPORTED_MODULE_2__);
|
|
10443
|
+
/* harmony import */ var _intersection_type__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(6973);
|
|
10444
|
+
/* harmony import */ var _sub_type__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(9234);
|
|
10445
|
+
/* harmony import */ var _types__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(7255);
|
|
10446
|
+
/* harmony import */ var _union_type__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(757);
|
|
10447
|
+
|
|
10448
|
+
|
|
10449
|
+
|
|
10450
|
+
|
|
9688
10451
|
|
|
9689
10452
|
|
|
9690
10453
|
|
|
@@ -9697,6 +10460,9 @@ function declIsLocal(decl) {
|
|
|
9697
10460
|
d.type === "Identifier" ||
|
|
9698
10461
|
(d.type === "VariableDeclarator" && isLocal(d)));
|
|
9699
10462
|
}
|
|
10463
|
+
function declIsNonLocal(decl) {
|
|
10464
|
+
return some(decl, (d) => d.type === "VariableDeclarator" && !isLocal(d));
|
|
10465
|
+
}
|
|
9700
10466
|
function localDeclName(decl) {
|
|
9701
10467
|
if (Array.isArray(decl))
|
|
9702
10468
|
decl = decl[0];
|
|
@@ -9761,6 +10527,140 @@ function printBlockTrailer(block) {
|
|
|
9761
10527
|
.map((block) => block.order)
|
|
9762
10528
|
.join(", ")} ExSucc: ${block.exsucc ? block.exsucc.order : ""}`);
|
|
9763
10529
|
}
|
|
10530
|
+
/*
|
|
10531
|
+
* We have an object, and a MemberExpression object.<name>
|
|
10532
|
+
* - decls are the StateNodes associated with the known type
|
|
10533
|
+
* of object.
|
|
10534
|
+
* - possible are all the StateNodes that declare <name>
|
|
10535
|
+
*
|
|
10536
|
+
* We want to find all the elements of possible which are
|
|
10537
|
+
* "compatible" with decls, which tells us the set of things
|
|
10538
|
+
* that object.<name> could correspond to, and also what that
|
|
10539
|
+
* tells us about object.
|
|
10540
|
+
*
|
|
10541
|
+
* The return value is two arrays of StateNode. The first
|
|
10542
|
+
* gives the refined type of object, and the second is the
|
|
10543
|
+
* array of StateNodes that could declare <name>
|
|
10544
|
+
*/
|
|
10545
|
+
function filterDecls(decls, possible, name) {
|
|
10546
|
+
if (!possible)
|
|
10547
|
+
return [null, null];
|
|
10548
|
+
const result = decls.reduce((cur, decl) => {
|
|
10549
|
+
const found = possible.reduce((flag, poss) => {
|
|
10550
|
+
if (decl === poss ||
|
|
10551
|
+
(poss.type === "ClassDeclaration" && (0,_api__WEBPACK_IMPORTED_MODULE_0__.getSuperClasses)(poss)?.has(decl))) {
|
|
10552
|
+
// poss extends decl, so decl must actually be a poss
|
|
10553
|
+
// eg we know obj is an Object, and we call obj.toNumber
|
|
10554
|
+
// so possible includes all the classes that declare toNumber
|
|
10555
|
+
// so we can refine obj's type to the union of those types
|
|
10556
|
+
if (!cur[0]) {
|
|
10557
|
+
cur = [new Set(), new Set()];
|
|
10558
|
+
}
|
|
10559
|
+
cur[0].add(poss);
|
|
10560
|
+
cur[1].add(poss);
|
|
10561
|
+
return true;
|
|
10562
|
+
}
|
|
10563
|
+
else if (decl.type === "ClassDeclaration" &&
|
|
10564
|
+
(0,_api__WEBPACK_IMPORTED_MODULE_0__.getSuperClasses)(decl)?.has(poss)) {
|
|
10565
|
+
// decl extends poss, so decl remains unchanged
|
|
10566
|
+
// eg we know obj is Menu2, we call obj.toString
|
|
10567
|
+
// Menu2 doesn't define toString, but Object does
|
|
10568
|
+
// so poss is Object. But we still know that
|
|
10569
|
+
// obj is Menu2
|
|
10570
|
+
if (!cur[0]) {
|
|
10571
|
+
cur = [new Set(), new Set()];
|
|
10572
|
+
}
|
|
10573
|
+
cur[0].add(decl);
|
|
10574
|
+
cur[1].add(poss);
|
|
10575
|
+
return true;
|
|
10576
|
+
}
|
|
10577
|
+
return flag;
|
|
10578
|
+
}, false);
|
|
10579
|
+
if (!found) {
|
|
10580
|
+
// If we didn't find the property in any of the
|
|
10581
|
+
// standard places, the runtime might still find
|
|
10582
|
+
// it by searching up the Module stack (and up
|
|
10583
|
+
// the module stack from any super classes)
|
|
10584
|
+
//
|
|
10585
|
+
// eg
|
|
10586
|
+
//
|
|
10587
|
+
// obj = Application.getApp();
|
|
10588
|
+
// obj.Properties.whatever
|
|
10589
|
+
//
|
|
10590
|
+
// Properties doesn't exist on AppBase, but AppBase
|
|
10591
|
+
// is declared in Application, and Application
|
|
10592
|
+
// does declare Properties. So Application.Properties
|
|
10593
|
+
// is (one of) the declarations we should find; but we
|
|
10594
|
+
// must not refine obj's type to include Application.
|
|
10595
|
+
let d = [decl];
|
|
10596
|
+
do {
|
|
10597
|
+
d.forEach((d) => {
|
|
10598
|
+
const stack = d.stack;
|
|
10599
|
+
possible.forEach((poss) => {
|
|
10600
|
+
for (let i = stack.length; i--;) {
|
|
10601
|
+
const sn = stack[i].sn;
|
|
10602
|
+
if (sn.decls === poss.decls) {
|
|
10603
|
+
if (!cur[0]) {
|
|
10604
|
+
cur = [new Set(), new Set()];
|
|
10605
|
+
}
|
|
10606
|
+
cur[0].add(decl);
|
|
10607
|
+
cur[1].add(poss);
|
|
10608
|
+
break;
|
|
10609
|
+
}
|
|
10610
|
+
if ((0,_api__WEBPACK_IMPORTED_MODULE_0__.hasProperty)(sn.decls, name)) {
|
|
10611
|
+
break;
|
|
10612
|
+
}
|
|
10613
|
+
}
|
|
10614
|
+
});
|
|
10615
|
+
});
|
|
10616
|
+
d = d.flatMap((d) => {
|
|
10617
|
+
if (d.type !== "ClassDeclaration" ||
|
|
10618
|
+
!d.superClass ||
|
|
10619
|
+
d.superClass === true) {
|
|
10620
|
+
return [];
|
|
10621
|
+
}
|
|
10622
|
+
return d.superClass;
|
|
10623
|
+
});
|
|
10624
|
+
} while (d.length);
|
|
10625
|
+
}
|
|
10626
|
+
return cur;
|
|
10627
|
+
}, [null, null]);
|
|
10628
|
+
if (!result[0])
|
|
10629
|
+
return [null, null];
|
|
10630
|
+
return [Array.from(result[0]), Array.from(result[1])];
|
|
10631
|
+
}
|
|
10632
|
+
function findObjectDeclsByProperty(state, object, next) {
|
|
10633
|
+
const decls = (0,_types__WEBPACK_IMPORTED_MODULE_5__/* .getStateNodeDeclsFromType */ .iX)(state, object);
|
|
10634
|
+
if (!decls)
|
|
10635
|
+
return [null, null];
|
|
10636
|
+
const possibleDecls = (0,_api__WEBPACK_IMPORTED_MODULE_0__.hasProperty)(state.allDeclarations, next.property.name) &&
|
|
10637
|
+
state.allDeclarations[next.property.name];
|
|
10638
|
+
return filterDecls(decls, possibleDecls, next.property.name);
|
|
10639
|
+
}
|
|
10640
|
+
function refineObjectTypeByDecls(istate, object, trueDecls) {
|
|
10641
|
+
const refinedType = typeFromTypeStateNodes(istate.state, trueDecls);
|
|
10642
|
+
return intersection(object, refinedType);
|
|
10643
|
+
}
|
|
10644
|
+
function findNextObjectType(istate, trueDecls, next) {
|
|
10645
|
+
const results = lookupNext(istate.state, [{ parent: null, results: trueDecls }], "decls", next.property);
|
|
10646
|
+
if (!results)
|
|
10647
|
+
return null;
|
|
10648
|
+
return results.reduce((cur, lookupDefn) => {
|
|
10649
|
+
unionInto(cur, typeFromTypeStateNodes(istate.state, lookupDefn.results));
|
|
10650
|
+
return cur;
|
|
10651
|
+
}, { type: 0 /* TypeTag.Never */ });
|
|
10652
|
+
}
|
|
10653
|
+
function resolveDottedMember(istate, object, next) {
|
|
10654
|
+
const [objDecls, trueDecls] = findObjectDeclsByProperty(istate.state, object, next);
|
|
10655
|
+
if (!objDecls)
|
|
10656
|
+
return null;
|
|
10657
|
+
const property = findNextObjectType(istate, trueDecls, next);
|
|
10658
|
+
if (!property)
|
|
10659
|
+
return null;
|
|
10660
|
+
const type = refineObjectTypeByDecls(istate, object, objDecls);
|
|
10661
|
+
const mayThrow = !subtypeOf(object, type);
|
|
10662
|
+
return { mayThrow, object: type, property };
|
|
10663
|
+
}
|
|
9764
10664
|
|
|
9765
10665
|
|
|
9766
10666
|
/***/ }),
|
|
@@ -11025,6 +11925,23 @@ function cleanupUnusedVars(state, node) {
|
|
|
11025
11925
|
return false;
|
|
11026
11926
|
const varDeclarations = new Map();
|
|
11027
11927
|
const stack = [];
|
|
11928
|
+
/*
|
|
11929
|
+
* Every local mentioned in toRemove can be removed, but
|
|
11930
|
+
* occurances of the identifier prior to its declaration
|
|
11931
|
+
* must be non-local. So reconstruct the toRemove record
|
|
11932
|
+
* as we go. This is to prevent issues with something like
|
|
11933
|
+
*
|
|
11934
|
+
* var g = 0;
|
|
11935
|
+
* function foo(var h) {
|
|
11936
|
+
* // if we just consult toRemove, we'll remove this assignment
|
|
11937
|
+
* g = h * 2;
|
|
11938
|
+
* var x = g;
|
|
11939
|
+
* ...
|
|
11940
|
+
* // *This* g is unused, and "g" gets added to activeRemove here.
|
|
11941
|
+
* var g = 42;
|
|
11942
|
+
* }
|
|
11943
|
+
*/
|
|
11944
|
+
const activeRemove = {};
|
|
11028
11945
|
let changes = false;
|
|
11029
11946
|
traverseAst(node, (node) => {
|
|
11030
11947
|
switch (node.type) {
|
|
@@ -11045,6 +11962,7 @@ function cleanupUnusedVars(state, node) {
|
|
|
11045
11962
|
node.declarations.forEach((decl, i) => {
|
|
11046
11963
|
const name = variableDeclarationName(decl.id);
|
|
11047
11964
|
if (hasProperty(toRemove, name)) {
|
|
11965
|
+
activeRemove[name] = toRemove[name];
|
|
11048
11966
|
const info = varDeclarations.get(node);
|
|
11049
11967
|
if (info) {
|
|
11050
11968
|
info.indices.push(i);
|
|
@@ -11062,14 +11980,14 @@ function cleanupUnusedVars(state, node) {
|
|
|
11062
11980
|
case "ExpressionStatement":
|
|
11063
11981
|
if (node.expression.type === "AssignmentExpression") {
|
|
11064
11982
|
if (node.expression.left.type === "Identifier" &&
|
|
11065
|
-
hasProperty(
|
|
11983
|
+
hasProperty(activeRemove, node.expression.left.name)) {
|
|
11066
11984
|
changes = true;
|
|
11067
11985
|
return unused(state, node.expression.right);
|
|
11068
11986
|
}
|
|
11069
11987
|
}
|
|
11070
11988
|
else if (node.expression.type === "UpdateExpression" &&
|
|
11071
11989
|
node.expression.argument.type === "Identifier" &&
|
|
11072
|
-
hasProperty(
|
|
11990
|
+
hasProperty(activeRemove, node.expression.argument.name)) {
|
|
11073
11991
|
return false;
|
|
11074
11992
|
}
|
|
11075
11993
|
break;
|
|
@@ -11078,7 +11996,7 @@ function cleanupUnusedVars(state, node) {
|
|
|
11078
11996
|
const expr = node.expressions[i];
|
|
11079
11997
|
if (expr.type === "AssignmentExpression") {
|
|
11080
11998
|
if (expr.left.type === "Identifier" &&
|
|
11081
|
-
hasProperty(
|
|
11999
|
+
hasProperty(activeRemove, expr.left.name)) {
|
|
11082
12000
|
const rep = unused(state, expr.right);
|
|
11083
12001
|
if (!rep.length) {
|
|
11084
12002
|
changes = true;
|
|
@@ -11087,14 +12005,14 @@ function cleanupUnusedVars(state, node) {
|
|
|
11087
12005
|
else {
|
|
11088
12006
|
// Sequence expressions can only be assignments
|
|
11089
12007
|
// or update expressions. Even calls aren't allowed
|
|
11090
|
-
|
|
12008
|
+
activeRemove[expr.left.name] = null;
|
|
11091
12009
|
expr.operator = "=";
|
|
11092
12010
|
}
|
|
11093
12011
|
}
|
|
11094
12012
|
}
|
|
11095
12013
|
else if (expr.type === "UpdateExpression" &&
|
|
11096
12014
|
expr.argument.type === "Identifier" &&
|
|
11097
|
-
hasProperty(
|
|
12015
|
+
hasProperty(activeRemove, expr.argument.name)) {
|
|
11098
12016
|
changes = true;
|
|
11099
12017
|
node.expressions.splice(i, 1);
|
|
11100
12018
|
}
|
|
@@ -11110,7 +12028,7 @@ function cleanupUnusedVars(state, node) {
|
|
|
11110
12028
|
const i = info.indices[ii];
|
|
11111
12029
|
const vdecl = decl.declarations[i];
|
|
11112
12030
|
const name = variableDeclarationName(vdecl.id);
|
|
11113
|
-
if (hasProperty(
|
|
12031
|
+
if (hasProperty(activeRemove, name)) {
|
|
11114
12032
|
const rep = vdecl.init ? unused(state, vdecl.init) : [];
|
|
11115
12033
|
if (rep.length) {
|
|
11116
12034
|
if ((state.sdkVersion || 0) < 4001007 &&
|
|
@@ -11155,7 +12073,7 @@ function cleanupUnusedVars(state, node) {
|
|
|
11155
12073
|
j = i;
|
|
11156
12074
|
continue;
|
|
11157
12075
|
}
|
|
11158
|
-
if (
|
|
12076
|
+
if (activeRemove[name]) {
|
|
11159
12077
|
changes = true;
|
|
11160
12078
|
j--;
|
|
11161
12079
|
decl.declarations.splice(i, 1);
|
|
@@ -11180,12 +12098,18 @@ function cleanupUnusedVars(state, node) {
|
|
|
11180
12098
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
11181
12099
|
|
|
11182
12100
|
"use strict";
|
|
11183
|
-
/* unused harmony
|
|
12101
|
+
/* unused harmony exports renameIdentifier, renameVariable */
|
|
11184
12102
|
/* harmony import */ var _api__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6817);
|
|
11185
12103
|
/* harmony import */ var _api__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_api__WEBPACK_IMPORTED_MODULE_0__);
|
|
11186
12104
|
/* harmony import */ var _ast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6652);
|
|
11187
12105
|
|
|
11188
12106
|
|
|
12107
|
+
function renameIdentifier(ident, newName) {
|
|
12108
|
+
if (!ident.original) {
|
|
12109
|
+
ident.original = ident.name;
|
|
12110
|
+
}
|
|
12111
|
+
ident.name = newName;
|
|
12112
|
+
}
|
|
11189
12113
|
function renameVariable(state, locals, declName) {
|
|
11190
12114
|
const map = locals.map;
|
|
11191
12115
|
if (declName) {
|
|
@@ -11377,6 +12301,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
11377
12301
|
"getApiMapping": () => (/* binding */ getApiMapping),
|
|
11378
12302
|
"getSuperClasses": () => (/* binding */ getSuperClasses),
|
|
11379
12303
|
"hasProperty": () => (/* reexport */ src_ast/* hasProperty */.l$),
|
|
12304
|
+
"isClassVariable": () => (/* binding */ isClassVariable),
|
|
11380
12305
|
"isLocal": () => (/* binding */ isLocal),
|
|
11381
12306
|
"isLookupCandidate": () => (/* binding */ isLookupCandidate),
|
|
11382
12307
|
"isStateNode": () => (/* binding */ isStateNode),
|
|
@@ -11778,7 +12703,7 @@ function visit_resource_refs(state, doc, e) {
|
|
|
11778
12703
|
function add_one_resource(state, doc, module, e) {
|
|
11779
12704
|
let id;
|
|
11780
12705
|
let func;
|
|
11781
|
-
const
|
|
12706
|
+
const makeVarDecl = (id, outer) => {
|
|
11782
12707
|
const loc = id && (0,src_ast/* adjustLoc */.b5)(id.value.loc);
|
|
11783
12708
|
return (0,src_ast/* wrap */.re)({
|
|
11784
12709
|
type: "VariableDeclaration",
|
|
@@ -11801,17 +12726,24 @@ function add_one_resource(state, doc, module, e) {
|
|
|
11801
12726
|
},
|
|
11802
12727
|
},
|
|
11803
12728
|
init,
|
|
11804
|
-
},
|
|
12729
|
+
}, outer),
|
|
11805
12730
|
],
|
|
11806
12731
|
kind: "var",
|
|
11807
|
-
},
|
|
12732
|
+
}, outer);
|
|
11808
12733
|
};
|
|
12734
|
+
const varDecl = () => makeVarDecl(id, e.loc);
|
|
11809
12735
|
const classDecl = (parent) => {
|
|
11810
12736
|
if (!id)
|
|
11811
12737
|
return null;
|
|
11812
12738
|
const loc = id.value.loc;
|
|
11813
12739
|
const items = init
|
|
11814
|
-
? [
|
|
12740
|
+
? [
|
|
12741
|
+
{
|
|
12742
|
+
type: "ClassElement",
|
|
12743
|
+
item: makeVarDecl(undefined, init.loc),
|
|
12744
|
+
loc: e.loc,
|
|
12745
|
+
},
|
|
12746
|
+
]
|
|
11815
12747
|
: [];
|
|
11816
12748
|
return {
|
|
11817
12749
|
type: "ClassDeclaration",
|
|
@@ -11825,7 +12757,9 @@ function add_one_resource(state, doc, module, e) {
|
|
|
11825
12757
|
if (!id)
|
|
11826
12758
|
return null;
|
|
11827
12759
|
const loc = id.value.loc;
|
|
11828
|
-
const items = init
|
|
12760
|
+
const items = init
|
|
12761
|
+
? [makeVarDecl(undefined, init.loc)]
|
|
12762
|
+
: [];
|
|
11829
12763
|
return {
|
|
11830
12764
|
type: "FunctionDeclaration",
|
|
11831
12765
|
body: { type: "BlockStatement", body: items, loc: e.loc },
|
|
@@ -11917,8 +12851,10 @@ function add_one_resource(state, doc, module, e) {
|
|
|
11917
12851
|
if (!func)
|
|
11918
12852
|
return;
|
|
11919
12853
|
const elements = visit_resource_refs(state, doc, e);
|
|
12854
|
+
const startLoc = elements[0]?.loc;
|
|
12855
|
+
const endLoc = elements[elements.length - 1]?.loc;
|
|
11920
12856
|
const init = elements.length
|
|
11921
|
-
? { type: "ArrayExpression", elements }
|
|
12857
|
+
? (0,src_ast/* wrap */.re)({ type: "ArrayExpression", elements }, startLoc && endLoc && (0,src_ast/* locRange */.ht)(startLoc, endLoc))
|
|
11922
12858
|
: undefined;
|
|
11923
12859
|
if (!id) {
|
|
11924
12860
|
if (!init)
|
|
@@ -11930,8 +12866,8 @@ function add_one_resource(state, doc, module, e) {
|
|
|
11930
12866
|
}
|
|
11931
12867
|
}
|
|
11932
12868
|
|
|
11933
|
-
// EXTERNAL MODULE: ./src/type-flow.ts
|
|
11934
|
-
var
|
|
12869
|
+
// EXTERNAL MODULE: ./src/type-flow/type-flow-util.ts
|
|
12870
|
+
var type_flow_util = __webpack_require__(1638);
|
|
11935
12871
|
// EXTERNAL MODULE: ./src/type-flow/types.ts
|
|
11936
12872
|
var types = __webpack_require__(7255);
|
|
11937
12873
|
// EXTERNAL MODULE: external "./util.cjs"
|
|
@@ -12564,7 +13500,7 @@ function lookupWithType(state, node, typeMap, nonLocal = false, stack = null) {
|
|
|
12564
13500
|
const objectType = typeMap.get(node.object);
|
|
12565
13501
|
if (!objectType)
|
|
12566
13502
|
return results;
|
|
12567
|
-
const [, decls] = (0,
|
|
13503
|
+
const [, decls] = (0,type_flow_util/* findObjectDeclsByProperty */.nK)(state, objectType, node);
|
|
12568
13504
|
if (decls) {
|
|
12569
13505
|
const next = lookupNext(state, [{ parent: null, results: decls }], "decls", node.property);
|
|
12570
13506
|
if (next) {
|
|
@@ -13099,13 +14035,14 @@ async function createDocumentationMap(functionDocumentation) {
|
|
|
13099
14035
|
state.allFunctions[info.name]?.forEach((decl) => decl.node?.loc?.source === "api.mir" &&
|
|
13100
14036
|
decl.fullName.endsWith(`.${info.parent}.${info.name}`) &&
|
|
13101
14037
|
docMap.set(decl.fullName, info.doc
|
|
14038
|
+
.replace(/@example\s*(.*?)<br\/>(.*?)(@|$)/g, (match, title, m1, m2) => `\n#### Example: ${title}\n\`\`\`${m1.replace(/<br\/>/g, "\n")}\`\`\`${m2}`)
|
|
13102
14039
|
.replace(/(\*.*?)\s*<br\/>\s*(?!\s*\*)/g, "$1\n\n")
|
|
13103
|
-
.replace(/@example(.*?)(@|$)/g, (match, m1, m2) => `\n#### Example\n\`\`\`${m1.replace(/<br\/>/g, "\n")}\`\`\`${m2}`)
|
|
13104
14040
|
.replace(/@note/g, "\n#### Note\n")
|
|
13105
14041
|
.replace(/@see/, "\n#### See Also:\n$&")
|
|
13106
14042
|
.replace(/@see\s+(.*?)(?=<br\/>)/g, "\n * {$1}")
|
|
13107
14043
|
.replace(/@throws/, "\n#### Throws:\n$&")
|
|
13108
14044
|
.replace(/@throws\s+(.*?)(?=<br\/>)/g, "\n * $1")
|
|
14045
|
+
.replace(/@option\s+\w+\s+(.*?)(?=<br\/>)/g, "\n - $1")
|
|
13109
14046
|
.replace(/@since\s+(.*?)(?=<br\/>)/, "\n#### Since:\nAPI Level $1\n")
|
|
13110
14047
|
.replace(/<div class="description">/, "### Description\n")
|
|
13111
14048
|
.replace(/<div class="param">/, "\n#### Parameters\n$&")
|
|
@@ -13304,6 +14241,9 @@ function markInvokeClassMethod(state, func) {
|
|
|
13304
14241
|
function isLocal(v) {
|
|
13305
14242
|
return v.stack[v.stack.length - 1]?.sn.type === "BlockStatement";
|
|
13306
14243
|
}
|
|
14244
|
+
function isClassVariable(v) {
|
|
14245
|
+
return v.stack[v.stack.length - 1]?.sn.type === "ClassDeclaration";
|
|
14246
|
+
}
|
|
13307
14247
|
function diagnostic(state, node, message, type = "INFO", extra) {
|
|
13308
14248
|
if (!state.diagnostics)
|
|
13309
14249
|
state.diagnostics = {};
|