有没有办法使用 javascript 来阻止 javascript?

Is there a way to block javascript using javascript?

我正在尝试使用新的 API 为 Safari 制作一个扩展,让用户可以在每个网站上屏蔽 javascript。 API 允许您注入一个 javascript 文件,该文件将在任何内容之前加载到网站上,与常规 javascript 相比没有太多功能,就好像它是 运行 HTML 页。有没有办法使用 javascript 来阻止所有 javascript?

API 含糊地告诉我,"The injected scripts are executed before the webpage has been fully loaded, so you can take action as resources are added to the webpage." 有没有我可以挂钩的事件来捕获正在加载的资源并阻止它们?

有一种方法可以阻止 most Javascript:在页面加载的最开始附加一个 MutationObserver,每当文档发生变化时,如果 <script>找到标签,将其删除:

<script>
new MutationObserver(() => {
  console.log('Mutation observer running...');
  document.body.querySelectorAll('script').forEach(scr => scr.remove());
})
.observe(document.documentElement, { childList: true, subtree: true });
</script>
<script>
console.log('hi');
</script>

来自内联处理程序的

Javascript 仍然可以 运行,但幸运的是,与 <script> 标签相比,内联 Javascript 并不常见(因为这是不好的做法) ,,通常,所有实质性的 Javascript 无论如何都会在 <script> 标签中,所以内联 Javascript 将 可能 由于引用了一个未定义的函数,经常简单地抛出一个错误。

尽管在动态添加元素时 subtree: true 比其他 MutationObservers 昂贵得多,因为(几乎可以肯定)页面上没有 Javascript 运行ning,它不应该是个问题,尤其是在页面完全加载后。

要同时删除内联处理程序,请检查添加的元素是否具有 on 属性,然后将其删除:

<script>
const cleanNode = (node) => {
  if (node.nodeType !== 1) {
    // Not an element node:
    return;
  }
  if (node.matches('script')) {
    node.remove();
  }
  [...node.attributes].forEach((attr) => {
    if (attr.name.startsWith('on')) {
      node.removeAttribute(attr.name);
    }
  });
};
new MutationObserver((mutations) => {
  mutations.forEach((mutation) => {
    [...mutation.addedNodes].forEach(cleanNode);
  });
})
.observe(document.documentElement, { childList: true, subtree: true });
</script>
<script>
console.log('hi');
</script>
<img onerror="alert('JS running')" src>