@markw65/monkeyc-optimizer 1.0.42 → 1.0.44
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 +21 -0
- package/build/api.cjs +404 -89
- package/build/optimizer.cjs +260 -49
- package/build/sdk-util.cjs +343 -2
- package/build/src/ast.d.ts +6 -3
- package/build/src/inliner.d.ts +2 -2
- package/build/src/optimizer-types.d.ts +1 -0
- package/build/src/resources.d.ts +3 -4
- package/build/src/worker-pool.d.ts +4 -0
- package/build/src/worker-task.d.ts +29 -0
- package/build/src/xml-util.d.ts +19 -7
- package/build/util.cjs +1 -1
- package/package.json +2 -2
- package/build/src/estree-types.d.ts +0 -324
package/build/optimizer.cjs
CHANGED
|
@@ -4731,7 +4731,13 @@ function withLoc(node, start, end) {
|
|
|
4731
4731
|
node.end = start.end;
|
|
4732
4732
|
node.loc = { ...(node.loc || start.loc), start: start.loc.start };
|
|
4733
4733
|
}
|
|
4734
|
-
if (end
|
|
4734
|
+
if (end === false) {
|
|
4735
|
+
if (node.loc) {
|
|
4736
|
+
node.loc.end = node.loc.start;
|
|
4737
|
+
node.end = node.start;
|
|
4738
|
+
}
|
|
4739
|
+
}
|
|
4740
|
+
else if (end && end.loc) {
|
|
4735
4741
|
node.end = end.end;
|
|
4736
4742
|
node.loc = { ...(node.loc || end.loc), end: end.loc.end };
|
|
4737
4743
|
}
|
|
@@ -4783,7 +4789,9 @@ function getNodeValue(node) {
|
|
|
4783
4789
|
return [node, "Long"];
|
|
4784
4790
|
}
|
|
4785
4791
|
if (type === "string") {
|
|
4786
|
-
return
|
|
4792
|
+
return node.raw.startsWith("'")
|
|
4793
|
+
? [node, "Char"]
|
|
4794
|
+
: [node, "String"];
|
|
4787
4795
|
}
|
|
4788
4796
|
if (type === "boolean") {
|
|
4789
4797
|
return [node, "Boolean"];
|
|
@@ -5092,6 +5100,12 @@ function getArgSafety(state, func, args, requireAll) {
|
|
|
5092
5100
|
let allSafe = true;
|
|
5093
5101
|
if (!args.every((arg, i) => {
|
|
5094
5102
|
switch (arg.type) {
|
|
5103
|
+
case "UnaryExpression":
|
|
5104
|
+
if (arg.operator === ":") {
|
|
5105
|
+
safeArgs.push(true);
|
|
5106
|
+
return true;
|
|
5107
|
+
}
|
|
5108
|
+
break;
|
|
5095
5109
|
case "Literal":
|
|
5096
5110
|
safeArgs.push(true);
|
|
5097
5111
|
return true;
|
|
@@ -5671,7 +5685,16 @@ function inlineWithArgs(state, func, call, context) {
|
|
|
5671
5685
|
withLocDeep(body, context, context, true);
|
|
5672
5686
|
return body;
|
|
5673
5687
|
}
|
|
5674
|
-
function
|
|
5688
|
+
function isTypecheckArg(node, arg) {
|
|
5689
|
+
return (node.type === "CallExpression" &&
|
|
5690
|
+
node.callee.type === "Identifier" &&
|
|
5691
|
+
node.callee.name === ":typecheck" &&
|
|
5692
|
+
(arg === null ||
|
|
5693
|
+
(node.arguments.length === 1 &&
|
|
5694
|
+
node.arguments[0].type === "Literal" &&
|
|
5695
|
+
node.arguments[0].value === arg)));
|
|
5696
|
+
}
|
|
5697
|
+
function inlineFunctionHelper(state, func, call, context) {
|
|
5675
5698
|
if (context) {
|
|
5676
5699
|
return inlineWithArgs(state, func, call, context);
|
|
5677
5700
|
}
|
|
@@ -5682,6 +5705,33 @@ function inlineFunction(state, func, call, context) {
|
|
|
5682
5705
|
state.localsStack[state.localsStack.length - 1].map = map;
|
|
5683
5706
|
return ret && withLocDeep(ret, call, call, true);
|
|
5684
5707
|
}
|
|
5708
|
+
function inlineFunction(state, func, call, context) {
|
|
5709
|
+
const ret = inlineFunctionHelper(state, func, call, context);
|
|
5710
|
+
if (!ret)
|
|
5711
|
+
return ret;
|
|
5712
|
+
const typecheckFalse = func.node.attrs?.attributes?.elements.find((attr) => isTypecheckArg(attr, false));
|
|
5713
|
+
if (!typecheckFalse) {
|
|
5714
|
+
return ret;
|
|
5715
|
+
}
|
|
5716
|
+
const callerSn = state.stack.find((sn) => sn.type === "FunctionDeclaration");
|
|
5717
|
+
if (!callerSn) {
|
|
5718
|
+
return ret;
|
|
5719
|
+
}
|
|
5720
|
+
const caller = callerSn.node;
|
|
5721
|
+
if (!caller.attrs) {
|
|
5722
|
+
caller.attrs = withLoc({
|
|
5723
|
+
type: "AttributeList",
|
|
5724
|
+
}, caller, false);
|
|
5725
|
+
}
|
|
5726
|
+
if (!caller.attrs.attributes) {
|
|
5727
|
+
caller.attrs.attributes = withLoc({ type: "Attributes", elements: [] }, caller.attrs, false);
|
|
5728
|
+
}
|
|
5729
|
+
if (caller.attrs.attributes.elements.find((attr) => isTypecheckArg(attr, null))) {
|
|
5730
|
+
return ret;
|
|
5731
|
+
}
|
|
5732
|
+
caller.attrs.attributes.elements.unshift(withLocDeep({ ...typecheckFalse }, caller.attrs, false));
|
|
5733
|
+
return ret;
|
|
5734
|
+
}
|
|
5685
5735
|
function applyTypeIfNeeded(node) {
|
|
5686
5736
|
if ("enumType" in node && node.enumType) {
|
|
5687
5737
|
node = {
|
|
@@ -5837,7 +5887,7 @@ function pragmaChecker(state, ast, diagnostics) {
|
|
|
5837
5887
|
if (quote == '"') {
|
|
5838
5888
|
return haystack.includes(needle);
|
|
5839
5889
|
}
|
|
5840
|
-
const re = new RegExp(needle.replace(/@([
|
|
5890
|
+
const re = new RegExp(needle.replace(/@([-\d.\w]+|"[^"]*")/g, (_match, pat) => `(?:${pat}|pre_${pat.replace(/[".]/g, "_")}(?:_\\d+)?)`));
|
|
5841
5891
|
return re.test(haystack);
|
|
5842
5892
|
};
|
|
5843
5893
|
next();
|
|
@@ -7784,7 +7834,7 @@ function getLiteralNode(node) {
|
|
|
7784
7834
|
case "-": {
|
|
7785
7835
|
const [arg, type] = getNodeValue(node.argument);
|
|
7786
7836
|
if (type === "Number" || type === "Long") {
|
|
7787
|
-
return replacementLiteral(
|
|
7837
|
+
return replacementLiteral(node, -arg.value, type);
|
|
7788
7838
|
}
|
|
7789
7839
|
}
|
|
7790
7840
|
}
|
|
@@ -7834,8 +7884,14 @@ function isBooleanExpression(state, node) {
|
|
|
7834
7884
|
}
|
|
7835
7885
|
return false;
|
|
7836
7886
|
}
|
|
7887
|
+
function roundToFloat(value) {
|
|
7888
|
+
return new Float32Array([value])[0];
|
|
7889
|
+
}
|
|
7837
7890
|
function replacementLiteral(arg, value, type) {
|
|
7838
|
-
if (
|
|
7891
|
+
if (value === null) {
|
|
7892
|
+
type = "Null";
|
|
7893
|
+
}
|
|
7894
|
+
else if (typeof value === "boolean") {
|
|
7839
7895
|
type = "Boolean";
|
|
7840
7896
|
}
|
|
7841
7897
|
else if (type === "Number") {
|
|
@@ -7844,32 +7900,189 @@ function replacementLiteral(arg, value, type) {
|
|
|
7844
7900
|
else if (type === "Long") {
|
|
7845
7901
|
value = BigInt.asIntN(64, BigInt(value));
|
|
7846
7902
|
}
|
|
7903
|
+
else if (type === "Float") {
|
|
7904
|
+
value = roundToFloat(Number(value));
|
|
7905
|
+
}
|
|
7906
|
+
let raw = type === "String"
|
|
7907
|
+
? JSON.stringify(value)
|
|
7908
|
+
: type === "Char"
|
|
7909
|
+
? value === "'"
|
|
7910
|
+
? "'\\''"
|
|
7911
|
+
: "'" + JSON.stringify(value).slice(1, -1) + "'"
|
|
7912
|
+
: value == null
|
|
7913
|
+
? "null"
|
|
7914
|
+
: value.toString();
|
|
7915
|
+
if (type === "Long") {
|
|
7916
|
+
raw += "l";
|
|
7917
|
+
}
|
|
7918
|
+
else if (type === "Double") {
|
|
7919
|
+
raw += "d";
|
|
7920
|
+
}
|
|
7921
|
+
else if (type === "Float" && prettier_plugin_monkeyc_namespaceObject.LiteralIntegerRe.test(raw)) {
|
|
7922
|
+
raw += "f";
|
|
7923
|
+
}
|
|
7924
|
+
const { start, end, loc } = arg;
|
|
7847
7925
|
return {
|
|
7848
|
-
|
|
7926
|
+
type: "Literal",
|
|
7849
7927
|
value,
|
|
7850
|
-
raw
|
|
7928
|
+
raw,
|
|
7929
|
+
start,
|
|
7930
|
+
end,
|
|
7931
|
+
loc,
|
|
7851
7932
|
};
|
|
7852
7933
|
}
|
|
7934
|
+
function classify(arg) {
|
|
7935
|
+
switch (arg) {
|
|
7936
|
+
case "Number":
|
|
7937
|
+
return { big: false, int: true };
|
|
7938
|
+
case "Long":
|
|
7939
|
+
return { big: true, int: true };
|
|
7940
|
+
case "Float":
|
|
7941
|
+
return { big: false, int: false };
|
|
7942
|
+
case "Double":
|
|
7943
|
+
return { big: true, int: false };
|
|
7944
|
+
}
|
|
7945
|
+
return null;
|
|
7946
|
+
}
|
|
7947
|
+
function common_arith_types(left, right) {
|
|
7948
|
+
const l = classify(left);
|
|
7949
|
+
if (!l)
|
|
7950
|
+
return null;
|
|
7951
|
+
const r = classify(right);
|
|
7952
|
+
if (!r)
|
|
7953
|
+
return null;
|
|
7954
|
+
if (l.big || r.big) {
|
|
7955
|
+
return l.int && r.int
|
|
7956
|
+
? ["Long", (v) => BigInt.asIntN(64, BigInt(v))]
|
|
7957
|
+
: ["Double", (v) => Number(v)];
|
|
7958
|
+
}
|
|
7959
|
+
else {
|
|
7960
|
+
return l.int && r.int
|
|
7961
|
+
? ["Number", (v) => BigInt.asIntN(32, BigInt(v))]
|
|
7962
|
+
: ["Float", (v) => roundToFloat(Number(v))];
|
|
7963
|
+
}
|
|
7964
|
+
}
|
|
7965
|
+
function common_bitwise_types(left, right) {
|
|
7966
|
+
if (left === "Boolean" && right === "Boolean") {
|
|
7967
|
+
return ["Boolean", (v) => (v ? true : false)];
|
|
7968
|
+
}
|
|
7969
|
+
const l = classify(left);
|
|
7970
|
+
if (!l)
|
|
7971
|
+
return null;
|
|
7972
|
+
const r = classify(right);
|
|
7973
|
+
if (!r)
|
|
7974
|
+
return null;
|
|
7975
|
+
if (!l.int || !r.int)
|
|
7976
|
+
return null;
|
|
7977
|
+
return l.big || r.big
|
|
7978
|
+
? ["Long", (v) => BigInt.asIntN(64, BigInt(v))]
|
|
7979
|
+
: ["Number", (v) => Number(BigInt.asIntN(32, BigInt(v)))];
|
|
7980
|
+
}
|
|
7981
|
+
function plus_types(left, right) {
|
|
7982
|
+
if (left === "String" || right === "String") {
|
|
7983
|
+
// Boolean + String is an error, and
|
|
7984
|
+
// Float/Double + String is legal, but its hard to predict
|
|
7985
|
+
// the way the float will be formatted (and it won't match
|
|
7986
|
+
// what javascript would do by default)
|
|
7987
|
+
if (/Float|Double|Boolean/.test(left + right)) {
|
|
7988
|
+
return null;
|
|
7989
|
+
}
|
|
7990
|
+
return ["String", String];
|
|
7991
|
+
}
|
|
7992
|
+
if (left === "Char" || right === "Char") {
|
|
7993
|
+
if (left === right) {
|
|
7994
|
+
// adding two chars produces a string
|
|
7995
|
+
return ["String", String];
|
|
7996
|
+
}
|
|
7997
|
+
if (/Number|Long/.test(left + right)) {
|
|
7998
|
+
return ["Char", (v) => v];
|
|
7999
|
+
}
|
|
8000
|
+
}
|
|
8001
|
+
return common_arith_types(left, right);
|
|
8002
|
+
}
|
|
8003
|
+
function shift_mod_types(left, right) {
|
|
8004
|
+
const result = common_bitwise_types(left, right);
|
|
8005
|
+
if (result && result[0] === "Boolean") {
|
|
8006
|
+
return null;
|
|
8007
|
+
}
|
|
8008
|
+
return result;
|
|
8009
|
+
}
|
|
7853
8010
|
const operators = {
|
|
7854
|
-
"+":
|
|
7855
|
-
|
|
7856
|
-
|
|
7857
|
-
|
|
7858
|
-
|
|
7859
|
-
|
|
7860
|
-
|
|
7861
|
-
|
|
7862
|
-
"
|
|
7863
|
-
|
|
7864
|
-
|
|
7865
|
-
|
|
7866
|
-
|
|
7867
|
-
|
|
7868
|
-
|
|
7869
|
-
|
|
7870
|
-
"
|
|
7871
|
-
|
|
7872
|
-
|
|
8011
|
+
"+": {
|
|
8012
|
+
typeFn: plus_types,
|
|
8013
|
+
valueFn: (left, right) => typeof left === "string" && typeof right !== "string"
|
|
8014
|
+
? String.fromCharCode(left.charCodeAt(0) + Number(right))
|
|
8015
|
+
: typeof left !== "string" && typeof right === "string"
|
|
8016
|
+
? String.fromCharCode(right.charCodeAt(0) + Number(left))
|
|
8017
|
+
: left + right,
|
|
8018
|
+
},
|
|
8019
|
+
"-": {
|
|
8020
|
+
typeFn: common_arith_types,
|
|
8021
|
+
valueFn: (left, right) => left - right,
|
|
8022
|
+
},
|
|
8023
|
+
"*": {
|
|
8024
|
+
typeFn: common_arith_types,
|
|
8025
|
+
valueFn: (left, right) => left * right,
|
|
8026
|
+
},
|
|
8027
|
+
"/": {
|
|
8028
|
+
typeFn: common_arith_types,
|
|
8029
|
+
valueFn: (left, right) => left / right,
|
|
8030
|
+
},
|
|
8031
|
+
"%": {
|
|
8032
|
+
typeFn: shift_mod_types,
|
|
8033
|
+
valueFn: (left, right) => left % right,
|
|
8034
|
+
},
|
|
8035
|
+
"&": {
|
|
8036
|
+
typeFn: common_bitwise_types,
|
|
8037
|
+
valueFn: (left, right) => left & right,
|
|
8038
|
+
},
|
|
8039
|
+
"|": {
|
|
8040
|
+
typeFn: common_bitwise_types,
|
|
8041
|
+
valueFn: (left, right) => left | right,
|
|
8042
|
+
},
|
|
8043
|
+
"^": {
|
|
8044
|
+
typeFn: common_bitwise_types,
|
|
8045
|
+
valueFn: (left, right) => left ^ right,
|
|
8046
|
+
},
|
|
8047
|
+
"<<": {
|
|
8048
|
+
typeFn: shift_mod_types,
|
|
8049
|
+
valueFn: (left, right) => typeof right === "bigint"
|
|
8050
|
+
? left << right
|
|
8051
|
+
: left << right,
|
|
8052
|
+
},
|
|
8053
|
+
">>": {
|
|
8054
|
+
typeFn: shift_mod_types,
|
|
8055
|
+
valueFn: (left, right) => typeof right === "bigint"
|
|
8056
|
+
? left >> right
|
|
8057
|
+
: left >> right,
|
|
8058
|
+
},
|
|
8059
|
+
"==": {
|
|
8060
|
+
typeFn: () => ["Boolean", (v) => v],
|
|
8061
|
+
valueFn: (left, right) =>
|
|
8062
|
+
// two string literals will compare unequal, becuase string
|
|
8063
|
+
// equality is object equality.
|
|
8064
|
+
typeof left === "string" ? false : left === right,
|
|
8065
|
+
},
|
|
8066
|
+
"!=": {
|
|
8067
|
+
typeFn: () => ["Boolean", (v) => v],
|
|
8068
|
+
valueFn: (left, right) => typeof left === "string" ? true : left !== right,
|
|
8069
|
+
},
|
|
8070
|
+
"<=": {
|
|
8071
|
+
typeFn: common_arith_types,
|
|
8072
|
+
valueFn: (left, right) => left <= right,
|
|
8073
|
+
},
|
|
8074
|
+
">=": {
|
|
8075
|
+
typeFn: common_arith_types,
|
|
8076
|
+
valueFn: (left, right) => left >= right,
|
|
8077
|
+
},
|
|
8078
|
+
"<": {
|
|
8079
|
+
typeFn: common_arith_types,
|
|
8080
|
+
valueFn: (left, right) => left < right,
|
|
8081
|
+
},
|
|
8082
|
+
">": {
|
|
8083
|
+
typeFn: common_arith_types,
|
|
8084
|
+
valueFn: (left, right) => left > right,
|
|
8085
|
+
},
|
|
7873
8086
|
as: null,
|
|
7874
8087
|
instanceof: null,
|
|
7875
8088
|
has: null,
|
|
@@ -7882,23 +8095,31 @@ function optimizeNode(state, node) {
|
|
|
7882
8095
|
break;
|
|
7883
8096
|
switch (node.operator) {
|
|
7884
8097
|
case "+":
|
|
7885
|
-
if (type === "Number" ||
|
|
8098
|
+
if (type === "Number" ||
|
|
8099
|
+
type === "Long" ||
|
|
8100
|
+
type === "Float" ||
|
|
8101
|
+
type === "Double" ||
|
|
8102
|
+
type === "Char" ||
|
|
8103
|
+
type === "String") {
|
|
7886
8104
|
return arg;
|
|
7887
8105
|
}
|
|
7888
8106
|
break;
|
|
7889
8107
|
case "-":
|
|
7890
|
-
if (type === "Number" ||
|
|
7891
|
-
|
|
8108
|
+
if (type === "Number" ||
|
|
8109
|
+
type === "Long" ||
|
|
8110
|
+
type === "Float" ||
|
|
8111
|
+
type === "Double") {
|
|
8112
|
+
return replacementLiteral(node, -arg.value, type);
|
|
7892
8113
|
}
|
|
7893
8114
|
break;
|
|
7894
8115
|
case "!":
|
|
7895
8116
|
case "~":
|
|
7896
8117
|
{
|
|
7897
8118
|
if (type === "Number" || type === "Long") {
|
|
7898
|
-
return replacementLiteral(
|
|
8119
|
+
return replacementLiteral(node, ~BigInt(arg.value), type);
|
|
7899
8120
|
}
|
|
7900
8121
|
if (type === "Boolean" && node.operator == "!") {
|
|
7901
|
-
return replacementLiteral(
|
|
8122
|
+
return replacementLiteral(node, !arg.value, type);
|
|
7902
8123
|
}
|
|
7903
8124
|
}
|
|
7904
8125
|
break;
|
|
@@ -7912,23 +8133,13 @@ function optimizeNode(state, node) {
|
|
|
7912
8133
|
const [right, right_type] = getNodeValue(node.right);
|
|
7913
8134
|
if (!left || !right)
|
|
7914
8135
|
break;
|
|
7915
|
-
|
|
7916
|
-
|
|
7917
|
-
|
|
7918
|
-
|
|
7919
|
-
if (node.operator !== "==" && node.operator !== "!=") {
|
|
7920
|
-
break;
|
|
7921
|
-
}
|
|
7922
|
-
value = operators[node.operator](left.value, right.value);
|
|
7923
|
-
type = "Boolean";
|
|
7924
|
-
}
|
|
7925
|
-
else {
|
|
7926
|
-
type = left_type;
|
|
7927
|
-
value = op(BigInt(left.value), BigInt(right.value));
|
|
7928
|
-
}
|
|
8136
|
+
const type = op.typeFn(left_type, right_type);
|
|
8137
|
+
if (!type)
|
|
8138
|
+
break;
|
|
8139
|
+
const value = op.valueFn(type[1](left.value), type[1](right.value));
|
|
7929
8140
|
if (value === null)
|
|
7930
8141
|
break;
|
|
7931
|
-
return replacementLiteral(
|
|
8142
|
+
return replacementLiteral(node, value, type[0]);
|
|
7932
8143
|
}
|
|
7933
8144
|
break;
|
|
7934
8145
|
}
|
|
@@ -9218,7 +9429,7 @@ async function generateOneConfig(buildConfig, manifestXML, dependencyFiles, conf
|
|
|
9218
9429
|
// the oldest optimized file, we don't need to regenerate
|
|
9219
9430
|
const source_time = await (0,external_util_cjs_namespaceObject.last_modified)(Object.keys(fnMap).concat(dependencyFiles));
|
|
9220
9431
|
const opt_time = await (0,external_util_cjs_namespaceObject.first_modified)(Object.values(fnMap).map((v) => v.output));
|
|
9221
|
-
if (source_time < opt_time &&
|
|
9432
|
+
if (source_time < opt_time && 1670782882733 < opt_time) {
|
|
9222
9433
|
return { hasTests, diagnostics: prevDiagnostics };
|
|
9223
9434
|
}
|
|
9224
9435
|
}
|
|
@@ -9245,7 +9456,7 @@ async function generateOneConfig(buildConfig, manifestXML, dependencyFiles, conf
|
|
|
9245
9456
|
return promises_namespaceObject.writeFile(external_path_.join(output, "build-info.json"), JSON.stringify({
|
|
9246
9457
|
hasTests,
|
|
9247
9458
|
diagnostics,
|
|
9248
|
-
optimizerVersion: "1.0.
|
|
9459
|
+
optimizerVersion: "1.0.44",
|
|
9249
9460
|
...Object.fromEntries(configOptionsToCheck.map((option) => [option, config[option]])),
|
|
9250
9461
|
}))
|
|
9251
9462
|
.then(() => ({ hasTests, diagnostics }));
|