diff --git a/.mocharc.js b/.mocharc.js index b50b0f6..906c8cc 100644 --- a/.mocharc.js +++ b/.mocharc.js @@ -14,6 +14,7 @@ module.exports = { // 'test/spec/wcc/module/module.spec.ts', // 'test/spec/wcc/wxs/wxs.spec.ts', // 'test/spec/wcsc/raw/raw.spec.ts', + // 'test/spec/wcc/empty/version.spec.ts' ], // spec: "test/spec/wcc/wxs/wxs.spec.ts", timeout: 20000, diff --git a/changelog.md b/changelog.md index 6fc92ae..203bb28 100644 --- a/changelog.md +++ b/changelog.md @@ -3,6 +3,7 @@ 🚀Features - 架构:添加龙芯支持 - 编译器:跟进v2.01.2510250版本 +- 编译器:添加 `--runtime-globals` 选项,移除 `--gdc` 选项 ## 🌈 v0.1.5 / 2025-05-02 diff --git a/src/include/define.h b/src/include/define.h index d7d670f..a9b9510 100644 --- a/src/include/define.h +++ b/src/include/define.h @@ -9,5 +9,5 @@ const char aIfThisThisGUnd[] = "if(this&&this.__g===undefined)Object.definePrope const char aGwnConsoleWarn[] = "$gwn=console.warn;\n$gwl=console.log;\nfunction $gwh()\n{\nfunction x()\n{\n}\nx.prototype = \n{\nhn: function( obj, all )\n{\nif( typeof(obj) == 'object' )\n{\nvar cnt=0;\nvar any1=false,any2=false;\nfor(var x in obj)\n{\nany1=any1|x==='__value__';\nany2=any2|x==='__wxspec__';\ncnt++;\nif(cnt>2)break;\n}\nreturn cnt == 2 && any1 && any2 && ( all || obj.__wxspec__ !== 'm' || this.hn(obj.__value__) === 'h' ) ? \"h\" : \"n\";\n}\nreturn \"n\";\n},\nnh: function( obj, special )\n{\nreturn { __value__: obj, __wxspec__: special ? special : true }\n},\nrv: function( obj )\n{\nreturn this.hn(obj,true)==='n'?obj:this.rv(obj.__value__);\n},\nhm: function( obj )\n{\nif( typeof(obj) == 'object' )\n{\nvar cnt=0;\nvar any1=false,any2=false;\nfor(var x in obj)\n{\nany1=any1|x==='__value__';\nany2=any2|x==='__wxspec__';\ncnt++;\nif(cnt>2)break;\n}\nreturn cnt == 2 && any1 && any2 && (obj.__wxspec__ === 'm' || this.hm(obj.__value__) );\n}\nreturn false;\n}\n}\nreturn new x;\n}\nwh=$gwh();\nfunction $gstack(s){\nvar tmp=s.split('\\n '+' '+' '+' ');\nfor(var i=0;i=':\ncase '<=':\ncase '>':\ncase '<':\ncase '<<':\ncase '>>':\n_a = rev( ops[1], e, s, g, o, _f );\n_b = rev( ops[2], e, s, g, o, _f );\n_c = should_pass_type_info && (wh.hn( _a ) === 'h' || wh.hn( _b ) === 'h');\nswitch( rop )\n{\ncase '+':\n_d = wh.rv( _a ) + wh.rv( _b );\nbreak;\ncase '*':\n_d = wh.rv( _a ) * wh.rv( _b );\nbreak;\ncase '/':\n_d = wh.rv( _a ) / wh.rv( _b );\nbreak;\ncase '%':\n_d = wh.rv( _a ) % wh.rv( _b );\nbreak;\ncase '|':\n_d = wh.rv( _a ) | wh.rv( _b );\nbreak;\ncase '^':\n_d = wh.rv( _a ) ^ wh.rv( _b );\nbreak;\ncase '&':\n_d = wh.rv( _a ) & wh.rv( _b );\nbreak;\ncase '===':\n_d = wh.rv( _a ) === wh.rv( _b );\nbreak;\ncase '==':\n_d = wh.rv( _a ) == wh.rv( _b );\nbreak;\ncase '!=':\n_d = wh.rv( _a ) != wh.rv( _b );\nbreak;\ncase '!==':\n_d = wh.rv( _a ) !== wh.rv( _b );\nbreak;\ncase '>=':\n_d = wh.rv( _a ) >= wh.rv( _b );\nbreak;\ncase '<=':\n_d = wh.rv( _a ) <= wh.rv( _b );\nbreak;\ncase '>':\n_d = wh.rv( _a ) > wh.rv( _b );\nbreak;\ncase '<':\n_d = wh.rv( _a ) < wh.rv( _b );\nbreak;\ncase '<<':\n_d = wh.rv( _a ) << wh.rv( _b );\nbreak;\ncase '>>':\n_d = wh.rv( _a ) >> wh.rv( _b );\nbreak;\ndefault:\nbreak;\n}\nreturn _c ? wh.nh( _d, \"c\" ) : _d;\nbreak;\ncase '-':\n_a = ops.length === 3 ? rev( ops[1], e, s, g, o, _f ) : 0;\n_b = ops.length === 3 ? rev( ops[2], e, s, g, o, _f ) : rev( ops[1], e, s, g, o, _f );\n_c = should_pass_type_info && (wh.hn( _a ) === 'h' || wh.hn( _b ) === 'h');\n_d = _c ? wh.rv( _a ) - wh.rv( _b ) : _a - _b;\nreturn _c ? wh.nh( _d, \"c\" ) : _d;\nbreak;\ncase '!':\n_a = rev( ops[1], e, s, g, o, _f );\n_c = should_pass_type_info && (wh.hn( _a ) == 'h');\n_d = !wh.rv(_a);\nreturn _c ? wh.nh( _d, \"c\" ) : _d;\ncase '~':\n_a = rev( ops[1], e, s, g, o, _f );\n_c = should_pass_type_info && (wh.hn( _a ) == 'h');\n_d = ~wh.rv(_a);\nreturn _c ? wh.nh( _d, \"c\" ) : _d;\ndefault:\n$gwn('unrecognized op' + rop );\n}\n}\nfunction rev( ops, e, s, g, o, newap )\n{\nvar op = ops[0];\nvar _f = false;\nif ( typeof newap !== \"undefined\" ) o.ap = newap;\nif( typeof(op)==='object' )\n{\nvar vop=op[0];\nvar _a, _aa, _b, _bb, _c, _d, _s, _e, _ta, _tb, _td;\nswitch(vop)\n{\ncase 2:\nreturn ArithmeticEv(ops,e,s,g,o);\nbreak;\ncase 4: \nreturn rev( ops[1], e, s, g, o, _f );\nbreak;\ncase 5: \nswitch( ops.length )\n{\ncase 2: \n_a = rev( ops[1],e,s,g,o,_f );\nreturn should_pass_type_info?[_a]:[wh.rv(_a)];\nreturn [_a];\nbreak;\ncase 1: \nreturn [];\nbreak;\ndefault:\n_a = rev( ops[1],e,s,g,o,_f );\n_b = rev( ops[2],e,s,g,o,_f );\n_a.push( \nshould_pass_type_info ?\n_b :\nwh.rv( _b )\n);\nreturn _a;\nbreak;\n}\nbreak;\ncase 6:\n_a = rev(ops[1],e,s,g,o);\nvar ap = o.ap;\n_ta = wh.hn(_a)==='h';\n_aa = _ta ? wh.rv(_a) : _a;\no.is_affected |= _ta;\nif( should_pass_type_info )\n{\nif( _aa===null || typeof(_aa) === 'undefined' )\n{\nreturn _ta ? wh.nh(undefined, 'e') : undefined;\n}\n_b = rev(ops[2],e,s,g,o,_f);\n_tb = wh.hn(_b) === 'h';\n_bb = _tb ? wh.rv(_b) : _b;\no.ap = ap;\no.is_affected |= _tb;\nif( _bb===null || typeof(_bb) === 'undefined' || \n_bb === \"__proto__\" || _bb === \"prototype\" || _bb === \"caller\" ) \n{\nreturn (_ta || _tb) ? wh.nh(undefined, 'e') : undefined;\n}\n_d = _aa[_bb];\nif ( typeof _d === 'function' && !ap ) _d = undefined;\n_td = wh.hn(_d)==='h';\no.is_affected |= _td;\nreturn (_ta || _tb) ? (_td ? _d : wh.nh(_d, 'e')) : _d;\n}\nelse\n{\nif( _aa===null || typeof(_aa) === 'undefined' )\n{\nreturn undefined;\n}\n_b = rev(ops[2],e,s,g,o,_f);\n_tb = wh.hn(_b) === 'h';\n_bb = _tb ? wh.rv(_b) : _b;\no.ap = ap;\no.is_affected |= _tb;\nif( _bb===null || typeof(_bb) === 'undefined' || \n_bb === \"__proto__\" || _bb === \"prototype\" || _bb === \"caller\" ) \n{\nreturn undefined;\n}\n_d = _aa[_bb];\nif ( typeof _d === 'function' && !ap ) _d = undefined;\n_td = wh.hn(_d)==='h';\no.is_affected |= _td;\nreturn _td ? wh.rv(_d) : _d;\n}\ncase 7: \nswitch(ops[1][0])\n{\ncase 11:\no.is_affected |= wh.hn(g)==='h';\nreturn g;\ncase 3:\n_s = wh.rv( s );\n_e = wh.rv( e );\n_b = ops[1][1];\nif (g && g.f && g.f.hasOwnProperty(_b) )\n{\n_a = g.f;\no.ap = true;\n}\nelse\n{\n_a = _s && _s.hasOwnProperty(_b) ? \ns : (_e && _e.hasOwnProperty(_b) ? e : undefined );\n}\nif( should_pass_type_info )\n{\nif( _a )\n{\n_ta = wh.hn(_a) === 'h';\n_aa = _ta ? wh.rv( _a ) : _a;\n_d = _aa[_b];\n_td = wh.hn(_d) === 'h';\no.is_affected |= _ta || _td;\n_d = _ta && !_td ? wh.nh(_d,'e') : _d;\nreturn _d;\n}\n}\nelse\n{\nif( _a )\n{\n_ta = wh.hn(_a) === 'h';\n_aa = _ta ? wh.rv( _a ) : _a;\n_d = _aa[_b];\n_td = wh.hn(_d) === 'h';\no.is_affected |= _ta || _td;\nreturn wh.rv(_d);\n}\n}\nreturn undefined;\n}\nbreak;\ncase 8: \n_a = {};\n_a[ops[1]] = rev(ops[2],e,s,g,o,_f);\nreturn _a;\nbreak;\ncase 9: \n_a = rev(ops[1],e,s,g,o,_f);\n_b = rev(ops[2],e,s,g,o,_f);\nfunction merge( _a, _b, _ow )\n{\nvar ka, _bbk;\n_ta = wh.hn(_a)==='h';\n_tb = wh.hn(_b)==='h';\n_aa = wh.rv(_a);\n_bb = wh.rv(_b);\nfor(var k in _bb)\n{\nif ( _ow || !_aa.hasOwnProperty(k) )\n{\n_aa[k] = should_pass_type_info ? (_tb ? wh.nh(_bb[k],'e') : _bb[k]) : wh.rv(_bb[k]);\n}\n}\nreturn _a;\n}\nvar _c = _a\nvar _ow = true\nif ( typeof(ops[1][0]) === \"object\" && ops[1][0][0] === 10 ) {\n_a = _b\n_b = _c\n_ow = false\n}\nif ( typeof(ops[1][0]) === \"object\" && ops[1][0][0] === 10 ) {\nvar _r = {}\nreturn merge( merge( _r, _a, _ow ), _b, _ow );\n}\nelse\nreturn merge( _a, _b, _ow );\nbreak;\ncase 10:\n_a = rev(ops[1],e,s,g,o,_f);\n_a = should_pass_type_info ? _a : wh.rv( _a );\nreturn _a ;\nbreak;\ncase 12:\nvar _r;\n_a = rev(ops[1],e,s,g,o);\nif ( !o.ap )\n{\nreturn should_pass_type_info && wh.hn(_a)==='h' ? wh.nh( _r, 'f' ) : _r;\n}\nvar ap = o.ap;\n_b = rev(ops[2],e,s,g,o,_f);\no.ap = ap;\n_ta = wh.hn(_a)==='h';\n_tb = _ca(_b);\n_aa = wh.rv(_a);\t\n_bb = wh.rv(_b); snap_bb=$gdc(_bb,\"nv_\");\ntry{\n_r = typeof _aa === \"function\" ? $gdc(_aa.apply(null, snap_bb)) : undefined;\n} catch (e){\ne.message = e.message.replace(/nv_/g,\"\");\ne.stack = e.stack.substring(0,e.stack.indexOf(\"\\n\", e.stack.lastIndexOf(\"at nv_\")));\ne.stack = e.stack.replace(/\\snv_/g,\" \"); \ne.stack = $gstack(e.stack);\t\nif(g.debugInfo)\n{\ne.stack += \"\\n \"+\" \"+\" \"+\" at \"+g.debugInfo[0]+\":\"+g.debugInfo[1]+\":\"+g.debugInfo[2];\nconsole.error(e);\n}\n_r = undefined;\n}\nreturn should_pass_type_info && (_tb || _ta) ? wh.nh( _r, 'f' ) : _r;\n}\n}\nelse\n{\nif( op === 3 || op === 1) return ops[1];\nelse if( op === 11 ) \n{\nvar _a='';\nfor( var i = 1 ; i < ops.length ; i++ )\n{\nvar xp = wh.rv(rev(ops[i],e,s,g,o,_f));\n_a += typeof(xp) === 'undefined' ? '' : xp;\n}\nreturn _a;\n}\n}\n}\nfunction wrapper( ops, e, s, g, o, newap )\n{\nif( ops[0] == '11182016' )\n{\ng.debugInfo = ops[2];\nreturn rev( ops[1], e, s, g, o, newap );\n}\nelse\n{\ng.debugInfo = null;\nreturn rev( ops, e, s, g, o, newap );\n}\n}\nreturn wrapper;\n}\ngra=$gwrt(true); \ngrb=$gwrt(false); \nfunction TestTest( expr, ops, e,s,g, expect_a, expect_b, expect_affected )\n{\n{\nvar o = {is_affected:false};\nvar a = gra( ops, e,s,g, o );\nif( JSON.stringify(a) != JSON.stringify( expect_a )\n|| o.is_affected != expect_affected )\n{\nconsole.warn( \"A. \" + expr + \" get result \" + JSON.stringify(a) + \", \" + o.is_affected + \", but \" + JSON.stringify( expect_a ) + \", \" + expect_affected + \" is expected\" );\n}\n}\n{\nvar o = {is_affected:false};\nvar a = grb( ops, e,s,g, o );\nif( JSON.stringify(a) != JSON.stringify( expect_b )\n|| o.is_affected != expect_affected )\n{\nconsole.warn( \"B. \" + expr + \" get result \" + JSON.stringify(a) + \", \" + o.is_affected + \", but \" + JSON.stringify( expect_b ) + \", \" + expect_affected + \" is expected\" );\n}\n}\n}\n"; // idb const char aVarNfInitFunct[] = "var nf_init=function(){\nif(typeof __WXML_GLOBAL__===\"undefined\"||undefined===__WXML_GLOBAL__.wxs_nf_init){\nnf_init_Object();nf_init_Function();nf_init_Array();nf_init_String();nf_init_Boolean();nf_init_Number();nf_init_Math();nf_init_Date();nf_init_RegExp();\n}\nif(typeof __WXML_GLOBAL__!==\"undefined\") __WXML_GLOBAL__.wxs_nf_init=true;\n};\nvar nf_init_Object=function(){\nObject.defineProperty(Object.prototype,\"nv_constructor\",{writable:true,value:\"Object\"})\nObject.defineProperty(Object.prototype,\"nv_toString\",{writable:true,value:function(){return \"[object Object]\"}})\n}\nvar nf_init_Function=function(){\nObject.defineProperty(Function.prototype,\"nv_constructor\",{writable:true,value:\"Function\"})\nObject.defineProperty(Function.prototype,\"nv_length\",{get:function(){return this.length;},set:function(){}});\nObject.defineProperty(Function.prototype,\"nv_toString\",{writable:true,value:function(){return \"[function Function]\"}})\n}\nvar nf_init_Array=function(){\nObject.defineProperty(Array.prototype,\"nv_toString\",{writable:true,value:function(){return this.nv_join();}})\nObject.defineProperty(Array.prototype,\"nv_join\",{writable:true,value:function(s){\ns=undefined==s?',':s;\nvar r=\"\";\nfor(var i=0;i{const o=n[t];if(void 0===o)throw ne" + "w Error(`no such WXS module: ${t}`);if(!o.t){const n={exports:{}};let e;o.o=n.exports,o.t=!0;try{e=o.u(r(t),n.export" + "s,n)}catch(n){throw o.t=!1,n}o.o=void 0!==n.exports?n.exports:e}return o.o},r=n=>function(r){if(\"string\"!=typeof r" + ")throw new Error(\"WXS require args must be a string\");if(r.startsWith(\"p_\")&&r.endsWith(\".wxs\")){const n=r.sli" + "ce(2,-4);return()=>gdc(t(n),\"nv_\",2)}{const o=((n,t)=>{let r;r=\"/\"!==n[0]?t.split(\"/\").slice(0,-1).concat(n.sp" + "lit(\"/\")):n.split(\"/\");const o=[];for(let n=0;nt(o)}};return(r,o)=>(((t,r)=>{void 0===n[t]&&(n[t]={t:!1,u:r,o" + ":null})})(r,o),()=>t(r))}(),gdc=function(n,t,r){if(null==n)return n;if(\"string\"==typeof n||\"boolean\"==typeof n||" + "\"number\"==typeof n)return n;if(Array.isArray(n)){const o=[];for(let e=0;e fileList; @@ -270,14 +270,14 @@ int main(int argc, const char **argv) { isWxs = true; } - else if (!param.compare("--gdc")) - { - isGDC = true; - } else if (!param.compare("--wxs-env")) { isWxsEnv = true; } + else if (!param.compare("--runtime-globals")) + { + isRuntimeGlobals = true; + } } } @@ -330,9 +330,9 @@ int main(int argc, const char **argv) fprintf(stderr, "Error in file %s: %s\n", v152.c_str(), v146.c_str()); return -2; } - auto v31 = snprintf(0, 0, WXML::GlassEaselWxs::sWrapper.c_str(), v146.c_str()) + 1; + auto v31 = snprintf(0, 0, WXML::GlassEasel::WXS::sWrapper.c_str(), v146.c_str()) + 1; char *v32 = (char *)operator new[](v31); - snprintf(v32, v31, WXML::GlassEaselWxs::sWrapper.c_str(), v146.c_str()); + snprintf(v32, v31, WXML::GlassEasel::WXS::sWrapper.c_str(), v146.c_str()); cfg[v152] = v32; delete[] v32; } @@ -345,9 +345,9 @@ int main(int argc, const char **argv) return fclose(f); return 0; } - if (isGDC) + if (isWxsEnv) { - std::string v136 = WXML::GlassEaselWxs::sGenFuncDeepCopy.c_str(); + std::string v136 = WXML::GlassEasel::WXS::sEnvInit.c_str(); FILE *f = stdout; if (!outputFileName.empty()) f = fopen(outputFileName.c_str(), "w"); @@ -356,9 +356,9 @@ int main(int argc, const char **argv) return fclose(f); return 0; } - if (isWxsEnv) + if (isRuntimeGlobals) { - std::string v136 = WXML::GlassEaselWxs::sWxsEnvInit.c_str(); + std::string v136 = WXML::GlassEasel::sRuntimeGlobals.c_str(); FILE *f = stdout; if (!outputFileName.empty()) f = fopen(outputFileName.c_str(), "w"); diff --git a/test/spec/wcc/empty/version.spec.ts b/test/spec/wcc/empty/version.spec.ts index 7164de6..21e6981 100644 --- a/test/spec/wcc/empty/version.spec.ts +++ b/test/spec/wcc/empty/version.spec.ts @@ -30,6 +30,60 @@ describe("wcc - empty", function () { fs.mkdirSync(storagePath, { recursive: true }); } catch (error) {} + fs.writeFileSync(`${storagePath}/wine-output.js`, w); + fs.writeFileSync(`${storagePath}/node-output.js`, n); + assert.equal(n, w, `wine: ${w}\n\nlinux: ${n}`); + }); + it("wxs-env", async function () { + const projectPath = __dirname; + const args: string[] = [ + "--wxs-env" + ]; + let w = "" + try + { + w = (await windows.wcc(args, projectPath)).replace(/\r\n/g, '\n') + } + catch(err: any){ + console.error('error:', err) + w = err.stdout.replace(/\r\n/g, '\n') + } + const n = await linux.wcc(args, projectPath); + const storagePath = path.resolve( + __dirname, + `wxs-env/${this.test?.title}` + ); + try { + fs.mkdirSync(storagePath, { recursive: true }); + } catch (error) {} + + fs.writeFileSync(`${storagePath}/wine-output.js`, w); + fs.writeFileSync(`${storagePath}/node-output.js`, n); + assert.equal(n, w, `wine: ${w}\n\nlinux: ${n}`); + }); + it("runtime-globals", async function () { + const projectPath = __dirname; + const args: string[] = [ + "--runtime-globals" + ]; + let w = "" + try + { + w = (await windows.wcc(args, projectPath)).replace(/\r\n/g, '\n') + } + catch(err: any){ + console.error('error:', err) + w = err.stdout.replace(/\r\n/g, '\n') + } + const n = await linux.wcc(args, projectPath); + const storagePath = path.resolve( + __dirname, + `runtime-globals/${this.test?.title}` + ); + try { + fs.mkdirSync(storagePath, { recursive: true }); + } catch (error) {} + fs.writeFileSync(`${storagePath}/wine-output.js`, w); fs.writeFileSync(`${storagePath}/node-output.js`, n); assert.equal(n, w, `wine: ${w}\n\nlinux: ${n}`); diff --git a/test/wcc.disassembly.cpp b/test/wcc.disassembly.cpp index 998aa40..883f5c1 100644 --- a/test/wcc.disassembly.cpp +++ b/test/wcc.disassembly.cpp @@ -195705,7 +195705,7 @@ int __cdecl main(int argc, const char **argv, const char **envp) else { v12 = *(_DWORD *)v103; - if ( *(_BYTE *)(*(_DWORD *)v103 + 1) == 99 && *(_BYTE *)(v12 + 2) == 98 ) + if ( *(_BYTE *)(*(_DWORD *)v103 + 1) == 99/*c*/ && *(_BYTE *)(v12 + 2) == 98 /*b*/) { ++v5; LOBYTE(v170[0]) = 0; @@ -195733,7 +195733,7 @@ int __cdecl main(int argc, const char **argv, const char **envp) std::string::_M_dispose((void **)&String); ++v5; } - else if ( v89 == 108 && *(_BYTE *)(v12 + 2) == 108 ) + else if ( v89 == 108/*l*/ && *(_BYTE *)(v12 + 2) == 108/*l*/ ) { v16 = *(_BYTE *)(v12 + 3); if ( v16 != 119 ) @@ -195811,15 +195811,15 @@ int __cdecl main(int argc, const char **argv, const char **envp) fclose(v24); std::string::_M_dispose((void **)&v168); } - if ( !v88 ) + if ( !v88 ) // wxs { - if ( v87 ) + if ( v87 ) // isRuntimeGlobals { v39 = (const char **)&WXML::GlassEasel::sRuntimeGlobals; LABEL_112: main::{lambda(std::string const&)#1}::operator()((const char **)&FileName, v39); v111 = 0; - goto LABEL_192; + goto LABEL_192; // return } v39 = (const char **)&WXML::GlassEasel::WXS::sEnvInit; if ( v93 )