javascript - 尽管使用 run_at : document_start?,但我注入(inject)的 <script> 在目标页面的 javascript 之后运行

标签 javascript google-chrome-extension content-script

当我使用内容脚本将一些 javascript 注入(inject) HTML 页面时,javascript 的执行顺序有问题:

这是我用来测试的 HTML 页面,test.html:

<html><head>    
<title>Test Page</title></head>
  <body>
    <script>
      console.log("In page");
    </script>
  </body>
</html>


这是我用来将额外代码注入(inject) HTML 页面的 javascript,injector.js:

var s = document.createElement("script");
s.src = chrome.extension.getURL("inject.js");
document.documentElement.appendChild(s);
console.log("Inject finished");


这是注入(inject)脚本 inject.js 的内容:

console.log("Inside inject.js");


最后,这是我的manifest.json:

  "web_accessible_resources": [
    "inject.js"
  ],
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["/injector.js"],
      "run_at": "document_start"
    }
  ]


现在,当我打开 test.html 时,这是我在控制台中得到的:

Inject finished
In page
Inside inject.js


我的问题是,为什么在Inside inject.js之前打印出In page?自从我将 run_at 设置为 document_start 后,难道 inject.js 应该首先运行吗?

如果这是设计使然,有什么方法可以确保 inject.js 中的内容在 HTML 页面中的脚本之前执行,同时不更改 HTML 页面中的任何内容

appendChild 之前将 async 属性设置为 false 似乎不起作用,因为它用于外部脚本之间的排序,不在外部脚本和页内脚本之间。

顺便说一句,我正在 Chrome 27.0.1453.9 上测试这个

最佳答案

带有 src 属性的注入(inject)脚本在 Chrome 中异步执行。
考虑这个 HTML 文件:

<html><head>
    <title>Chrome early script inject, Test Page</title>
    <script>
        var s = document.createElement ("script");
        s.src = "localInject1.js";
        document.documentElement.appendChild (s);
    </script>
</head>
<body>
<p>See the console.</p>
<script src="localInject2.js"></script>
<script> console.log("In page: ", new Date().getTime()); </script>
</body>
</html>

localInject1.js 只是:

console.log("In page's script 1: ", new Date().getTime());

localInject2.js 是:

console.log("In page's script 2: ", new Date().getTime());


名义上,控制台应该显示:

In page's script 1:   ...
In page's script 2:   ...
In page:   ...


但经常,尤其是在无缓存重新加载时,您会看到:

In page's script 2:   ...
In page:   ...
In page's script 1:   ...


设置 s.async = false; 没有任何区别。


我不确定这是不是一个错误。 Firefox 也会让脚本乱序,但似乎更一致。好像没有any relevant Chrome bugs ,我不清楚规范。


解决方法:

代码由 textContent 设置的脚本,而不是 src 链接的文件,会像您期望的那样立即执行。
例如,如果您将 injector.js 更改为:

var s = document.createElement ("script");
s.src = chrome.extension.getURL ("inject.js");
document.documentElement.appendChild (s);

var s = document.createElement ('script');
s.textContent = 'console.log ("Text runs correctly!", new Date().getTime() );';
document.documentElement.appendChild (s);

console.log("Inject finished", new Date().getTime() );

你会看到:

Text runs correctly! ...
Inject finished ...
In page
Inside inject.js


诚然,这在内容脚本中可能会很痛苦,但在 W3C 和浏览器 vendor 解决此问题之前,您可能(在 Chrome 中)只能这样做。

关于javascript - 尽管使用 run_at : document_start?,但我注入(inject)的 &lt;script&gt; 在目标页面的 javascript 之后运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15730869/

相关文章:

javascript - 如何检测是否在我的页面中注入(inject)了不需要的 chrome 内容脚本?

javascript - 在悬停的 li 元素上相对于 li 的位置显示一个隐藏的响应式 div

javascript - 工厂函数链表问题

javascript - 未捕获的 TypeError : $. get 不是 <anonymous>:1:3 处的函数

c# - 将 C# 正则表达式转换为 javascript

firefox-addon - 如何让 firefox 附加内容脚本在其他页面脚本之前注入(inject)和运行脚本?

javascript - 获取用户正在访问的页面的 DOM 元素的 Chrome 扩展

javascript - AngularJS 无法发送内容类型为 :application/json 的发布请求

javascript - Leaflet maxBounds - 边界不起作用

crash - Google Chrome 扩展程序在更新时崩溃。