246 lines
6.8 KiB
JavaScript
246 lines
6.8 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.indexOf('(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)));
|
|
}};
|