重写浏览器 JS 代码以将全局定义转换为窗口属性

Rewrite browser JS code to transform global definitions into window properties

提问人:Renato Flores 提问时间:2/18/2023 最后编辑:Renato Flores 更新时间:2/18/2023 访问量:28

问:

我支持一个非常旧的 PHP Web 框架,它使用服务器端渲染。我决定实现 Vue 来渲染一些模块,所以我编译了一个 hello world 应用程序,并意识到部署不会那么简单。

该框架作为一个巨大的 SPA,每个模块都使用 body() 函数的 html 输出进行渲染。输出在客户端的 DOM 中被替换,而无需重新加载页面本身。 出于安全原因,<script> 标记被禁止,并且将从生成的 HTML 中清除。将 JS 交付给客户端的唯一方法是使用 eval_js() 函数。

问题很简单。我需要在同一个 DOM 中多次安全地加载 JS 代码。在应用程序编译后,我无法按原样加载它,因为从第二次执行代码开始(每次用户访问模块或执行操作时),代码将尝试重新定义全局变量并杀死整个客户端。

解决方案也相当简单,只需重写 JS 代码,以便将每个全局定义转换为窗口属性。这样,即使同一段代码在同一个 DOM 中多次执行,它也只会替换窗口属性,而不是尝试重新定义变量。

例如,以下输入:

function Yr(t){
   const b = t.prototype.hasOwnProperty;
   this._init(b);
 }
var hOe = sg(uOe, fOe, dOe, !1, null, "e687eb20", null, null);
const vOe = {
   name: "AmmFilters",
     components: {
        AmmOptionSelect: pOe
     } 
   };
new Yr({...}).$mount("#app");

将被重写为:

window.Yr = function(t){
    const b = t.prototype.hasOwnProperty;
    this._init(b);
}
window.hOe = sg(window.uOe, window.fOe, window.dOe, !1, null, "e687eb20", null, null);
window.vOe = {
   name: "AmmFilters",
     components: {
         AmmOptionSelect: window.pOe
    } 
}
new window.Yr({...}).$mount("#app");

我最初考虑编写自己的解析器,但后来意识到 ES6+ 语法不是儿戏。我将尝试重写的代码经过优化和混淆,这意味着它将具有各种复杂的语法,我必须小心不要将作用域定义转换为窗口属性。

对已经执行此任务的工具有任何想法吗?生成的 JS 代码应该与原始代码没有区别,因为全局范围的变量无论如何都会出现在 window 对象中。

我相信对于各种用例来说,这将是一个相当有用的工具,所以在尝试重新发明轮子之前考虑过询问。

JavaScript 解析 ECMAScript-6

评论

0赞 trincot 2/18/2023
我不明白分配给窗口属性有什么帮助。如果你有一个全局变量,那么赋值到也会改变全局变量的值,这是你想阻止的?你能澄清一下吗?awindow.a

答: 暂无答案