283 lines
7.7 KiB
JavaScript
283 lines
7.7 KiB
JavaScript
const wu = require("./wuLib.js");
|
|
const {VM} = require('vm2');
|
|
|
|
function catchZGroup(code, groupPreStr, cb) {
|
|
const debugPre = "(function(z){var a=11;function Z(ops,debugLine){";
|
|
let zArr = {};
|
|
for (let preStr of groupPreStr) {
|
|
let content = code.slice(code.indexOf(preStr)), z = [];
|
|
content = content.slice(content.indexOf("(function(z){var a=11;"));
|
|
content = content.slice(0, content.indexOf("})(__WXML_GLOBAL__.ops_cached.$gwx")) + "})(z);";
|
|
let vm = new VM({sandbox: {z: z, debugInfo: []}});
|
|
vm.run(content);
|
|
if (content.startsWith(debugPre)) for (let i = 0; i < z.length; i++) z[i] = z[i][1];
|
|
zArr[preStr.match(/function gz\$gwx(\d*\_\d+)/)[1]] = z;
|
|
}
|
|
cb({"mul": zArr});
|
|
}
|
|
|
|
function catchZ(code, cb) {
|
|
let groupTest = code.match(/function gz\$gwx(\d*\_\d+)\(\)\{\s*if\( __WXML_GLOBAL__\.ops_cached\.\$gwx\d*\_\d+\)/g);
|
|
if (groupTest !== null) return catchZGroup(code, groupTest, cb);
|
|
let z = [], vm = new VM({
|
|
sandbox: {
|
|
z: z,
|
|
debugInfo: []
|
|
}
|
|
});
|
|
let lastPtr = code.lastIndexOf("(z);__WXML_GLOBAL__.ops_set.$gwx=z;");
|
|
if (lastPtr == -1) lastPtr = code.lastIndexOf("(z);__WXML_GLOBAL__.ops_set.$gwx");
|
|
code = code.slice(code.lastIndexOf('(function(z){var a=11;function Z(ops){z.push(ops)}'), lastPtr + 4);
|
|
vm.run(code);
|
|
cb(z);
|
|
}
|
|
|
|
function restoreSingle(ops, withScope = false) {
|
|
if (typeof ops == "undefined") return "";
|
|
|
|
function scope(value) {
|
|
if (value.startsWith('{') && value.endsWith('}')) return withScope ? value : "{" + value + "}";
|
|
return withScope ? value : "{{" + value + "}}";
|
|
}
|
|
|
|
function enBrace(value, type = '{') {
|
|
if (value.startsWith('{') || value.startsWith('[') || value.startsWith('(') || value.endsWith('}') || value.endsWith(']') || value.endsWith(')')) value = ' ' + value + ' ';
|
|
switch (type) {
|
|
case '{':
|
|
return '{' + value + '}';
|
|
case '[':
|
|
return '[' + value + ']';
|
|
case '(':
|
|
return '(' + value + ')';
|
|
default:
|
|
throw Error("Unknown brace type " + type);
|
|
}
|
|
}
|
|
|
|
function restoreNext(ops, w = withScope) {
|
|
return restoreSingle(ops, w);
|
|
}
|
|
|
|
function jsoToWxon(obj) {//convert JS Object to Wechat Object Notation(No quotes@key+str)
|
|
let ans = "";
|
|
if (typeof obj === "undefined") {
|
|
return 'undefined';
|
|
} else if (obj === null) {
|
|
return 'null';
|
|
} else if (obj instanceof RegExp) {
|
|
return obj.toString();
|
|
} else if (obj instanceof Array) {
|
|
for (let i = 0; i < obj.length; i++) ans += ',' + jsoToWxon(obj[i]);
|
|
return enBrace(ans.slice(1), '[');
|
|
} else if (typeof obj == "object") {
|
|
for (let k in obj) ans += "," + k + ":" + jsoToWxon(obj[k]);
|
|
return enBrace(ans.slice(1), '{');
|
|
} else if (typeof obj == "string") {
|
|
let parts = obj.split('"'), ret = [];
|
|
for (let part of parts) {
|
|
let atoms = part.split("'"), ans = [];
|
|
for (let atom of atoms) ans.push(JSON.stringify(atom).slice(1, -1));
|
|
ret.push(ans.join("\\'"));
|
|
}
|
|
return "'" + ret.join('"') + "'";
|
|
} else return JSON.stringify(obj);
|
|
}
|
|
|
|
let op = ops[0];
|
|
if (typeof op != "object") {
|
|
switch (op) {
|
|
case 3://string
|
|
return ops[1];//may cause problems if wx use it to be string
|
|
case 1://direct value
|
|
return scope(jsoToWxon(ops[1]));
|
|
case 11://values list, According to var a = 11;
|
|
let ans = "";
|
|
ops.shift();
|
|
for (let perOp of ops) ans += restoreNext(perOp);
|
|
return ans;
|
|
}
|
|
} else {
|
|
let ans = "";
|
|
switch (op[0]) {//vop
|
|
case 2://arithmetic operator
|
|
{
|
|
function getPrior(op, len) {
|
|
const priorList = {
|
|
"?:": 4,
|
|
"&&": 6,
|
|
"||": 5,
|
|
"+": 13,
|
|
"*": 14,
|
|
"/": 14,
|
|
"%": 14,
|
|
"|": 7,
|
|
"^": 8,
|
|
"&": 9,
|
|
"!": 16,
|
|
"~": 16,
|
|
"===": 10,
|
|
"==": 10,
|
|
"!=": 10,
|
|
"!==": 10,
|
|
">=": 11,
|
|
"<=": 11,
|
|
">": 11,
|
|
"<": 11,
|
|
"<<": 12,
|
|
">>": 12,
|
|
"-": len == 3 ? 13 : 16
|
|
};
|
|
return priorList[op] ? priorList[op] : 0;
|
|
}
|
|
|
|
function getOp(i) {
|
|
let ret = restoreNext(ops[i], true);
|
|
if (ops[i] instanceof Object && typeof ops[i][0] == "object" && ops[i][0][0] == 2) {
|
|
//Add brackets if we need
|
|
if (getPrior(op[1], ops.length) > getPrior(ops[i][0][1], ops[i].length)) ret = enBrace(ret, '(');
|
|
;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
switch (op[1]) {
|
|
case"?:":
|
|
ans = getOp(1) + "?" + getOp(2) + ":" + getOp(3);
|
|
break;
|
|
case "!":
|
|
case "~":
|
|
ans = op[1] + getOp(1);
|
|
break;
|
|
case"-":
|
|
if (ops.length != 3) {
|
|
ans = op[1] + getOp(1);
|
|
break;
|
|
}//shoud not add more in there![fall through]
|
|
default:
|
|
ans = getOp(1) + op[1] + getOp(2);
|
|
}
|
|
break;
|
|
}
|
|
case 4://unkown-arrayStart?
|
|
ans = restoreNext(ops[1], true);
|
|
break;
|
|
case 5://merge-array
|
|
{
|
|
switch (ops.length) {
|
|
case 2:
|
|
ans = enBrace(restoreNext(ops[1], true), '[');
|
|
break;
|
|
case 1:
|
|
ans = '[]';
|
|
break;
|
|
default: {
|
|
let a = restoreNext(ops[1], true);
|
|
//console.log(a,a.startsWith('[')&&a.endsWith(']'));
|
|
if (a.startsWith('[') && a.endsWith(']')) {
|
|
if (a != '[]') {
|
|
ans = enBrace(a.slice(1, -1).trim() + ',' + restoreNext(ops[2], true), '[');
|
|
//console.log('-',a);
|
|
} else {
|
|
ans = enBrace(restoreNext(ops[2], true), '[');
|
|
}
|
|
} else {
|
|
ans = enBrace('...' + a + ',' + restoreNext(ops[2], true), '[');//may/must not support in fact
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case 6://get value of an object
|
|
{
|
|
let sonName = restoreNext(ops[2], true);
|
|
if (sonName._type === "var")
|
|
ans = restoreNext(ops[1], true) + enBrace(sonName, '[');
|
|
else {
|
|
let attach = "";
|
|
if (/^[A-Za-z\_][A-Za-z\d\_]*$/.test(sonName)/*is a qualified id*/)
|
|
attach = '.' + sonName;
|
|
else attach = enBrace(sonName, '[');
|
|
ans = restoreNext(ops[1], true) + attach;
|
|
}
|
|
break;
|
|
}
|
|
case 7://get value of str
|
|
{
|
|
switch (ops[1][0]) {
|
|
case 11:
|
|
ans = enBrace("__unTestedGetValue:" + enBrace(jsoToWxon(ops), '['), '{');
|
|
break;
|
|
case 3:
|
|
ans = new String(ops[1][1]);
|
|
ans._type = "var";
|
|
break;
|
|
default:
|
|
throw Error("Unknown type to get value");
|
|
}
|
|
break;
|
|
}
|
|
case 8://first object
|
|
ans = enBrace(ops[1] + ':' + restoreNext(ops[2], true), '{');//ops[1] have only this way to define
|
|
break;
|
|
case 9://object
|
|
{
|
|
function type(x) {
|
|
if (x.startsWith('...')) return 1;
|
|
if (x.startsWith('{') && x.endsWith('}')) return 0;
|
|
return 2;
|
|
}
|
|
|
|
let a = restoreNext(ops[1], true);
|
|
let b = restoreNext(ops[2], true);
|
|
let xa = type(a), xb = type(b);
|
|
if (xa == 2 || xb == 2) ans = enBrace("__unkownMerge:" + enBrace(a + "," + b, '['), '{');
|
|
else {
|
|
if (!xa) a = a.slice(1, -1).trim();
|
|
if (!xb) b = b.slice(1, -1).trim();
|
|
//console.log(l,r);
|
|
ans = enBrace(a + ',' + b, '{');
|
|
}
|
|
break;
|
|
}
|
|
case 10://...object
|
|
ans = '...' + restoreNext(ops[1], true);
|
|
break;
|
|
case 12: {
|
|
let arr = restoreNext(ops[2], true);
|
|
if (arr.startsWith('[') && arr.endsWith(']'))
|
|
ans = restoreNext(ops[1], true) + enBrace(arr.slice(1, -1).trim(), '(');
|
|
else ans = restoreNext(ops[1], true) + '.apply' + enBrace('null,' + arr, '(');
|
|
break;
|
|
}
|
|
default:
|
|
ans = enBrace("__unkownSpecific:" + jsoToWxon(ops), '{');
|
|
}
|
|
return scope(ans);
|
|
}
|
|
}
|
|
|
|
function restoreGroup(z) {
|
|
let ans = [];
|
|
for (let g in z.mul) {
|
|
let singleAns = [];
|
|
for (let e of z.mul[g]) singleAns.push(restoreSingle(e, false));
|
|
ans[g] = singleAns;
|
|
}
|
|
let ret = [];//Keep a null array for remaining global Z array.
|
|
ret.mul = ans;
|
|
return ret;
|
|
}
|
|
|
|
function restoreAll(z) {
|
|
if (z.mul) return restoreGroup(z);
|
|
let ans = [];
|
|
for (let e of z) ans.push(restoreSingle(e, false));
|
|
return ans;
|
|
}
|
|
|
|
module.exports = {
|
|
getZ(code, cb) {
|
|
catchZ(code, z => cb(restoreAll(z)));
|
|
}
|
|
};
|