This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const wu = require("./wuLib.js"); | |
const {VM} = require('vm2'); | |
const fs = require("fs"); | |
function catchZGroup(code, groupPreStr, cb) { | |
const debugPre = "(function(z){var a=11;function Z(ops,debugLine){"; | |
let zArr = {}; | |
let i = 0; | |
for (let preStr of groupPreStr) { | |
// console.log(preStr); | |
i++; | |
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: []}}); | |
// fs.writeFileSync(`z_func${i}_single.js`, content); | |
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*[\_XC]*[\d\_]+)/)[1]] = z; | |
} | |
// fs.writeFileSync("zArr.json", JSON.stringify(zArr)); | |
cb({"mul": zArr}); | |
} | |
function catchM0Group(code, groupPreStr, z, cb) { | |
// const debugPre = "(function(z){var a=11;function Z(ops,debugLine){"; | |
let m0Arr = {}; | |
let i = 0; | |
for (let preStr of groupPreStr) { | |
// console.log(preStr); | |
i++; | |
let name = preStr.replace(/.*var x=\['(.*\.wxml)'\].*/g, "$1"); | |
console.log(`M0_${i}_name: ${name}`); | |
let content = code.slice(code.indexOf(preStr)); | |
content = content.slice(0, content.indexOf("if(path&&e_[path]){")); | |
//var z=gz$gwx_XC_18_1() | |
let zFuncName = "" | |
content.replace(/var z=gz\$gwx([_XC\d]+)\(\)/g, (match, p1, p2, p3, offset, string) => { | |
zFuncName = p1; | |
}); | |
// content = content.replace(/var z=gz\$gwx[_XC\d\(\)]+/, ""); | |
console.log(`Z_Func_${i}_name: ${zFuncName}`); | |
// TODO: `d_`数组不知道是什么意思, 暂时不考虑了 | |
let rD = {}, rF = {}, rZ = z[zFuncName] || [], x = []; | |
let vm = new VM({ | |
sandbox: { | |
x: x, z: rZ, d_: rD, e_: m0Arr, f_: rF, debugInfo: [] | |
} | |
}); | |
// fs.writeFileSync(`m0_func${i}_single.js`, content); | |
vm.run(content); | |
// if (content.startsWith(debugPre)) for (let i = 0; i < z.length; i++) z[i] = z[i][1]; | |
// m0Arr[name] = {code: content}; | |
} | |
// fs.writeFileSync("zArr.json", JSON.stringify(zArr)); | |
cb(m0Arr); | |
} | |
function catchZ(code, cb) { | |
let groupTest = code.match(/function gz\$gwx(\d*[\_XC]*[\d\_]*)\(\)\{\s*if\( __WXML_GLOBAL__\.ops_cached\.\$gwx\d*[\_\dXC]+\)/g); | |
// console.log(groupTest); | |
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"); | |
// if (lastPtr == -1) lastPtr = code.lastIndexOf("__WXML_GLOBAL__.ops_set.$gwx1_XC_0=z"); | |
code = code.slice(code.lastIndexOf('(function(z){var a=11;function Z(ops){z.push(ops)}'), lastPtr + 4); | |
fs.writeFileSync("catchZ_vmcode.js", code); | |
vm.run(code); | |
cb(z); | |
} | |
/** | |
* 获取所有的m0函数 | |
* @param {String} code 代码 | |
* @param {Object} z z数组 | |
* @param {Function} cb 回调函数 | |
* @returns {name: {code: string}} | |
*/ | |
function catchM0(code, z, cb) { | |
let groupTest = code.match(/var x=\['.*\.wxml'];d_\[x\[0\]\]=\{\}/g); | |
// console.log(groupTest); | |
if (groupTest !== null) return catchM0Group(code, groupTest, z, 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("__WXML_GLOBAL__.ops_set.$gwx1_XC_0=z"); | |
// code = code.slice(code.lastIndexOf('(function(z){var a=11;function Z(ops){z.push(ops)}'), lastPtr + 4); | |
// fs.writeFileSync("catchM0_vmcode.js", code); | |
// 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))); | |
}, | |
catchM0 | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment