我注入的< script>在目标页面的JavaScript之后运行,尽管使用了run_at:document_start? [英] My injected <script> runs after the target-page's javascript, despite using run_at: document_start?

查看:325
本文介绍了我注入的< script>在目标页面的JavaScript之后运行,尽管使用了run_at:document_start?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用内容脚本向HTML页面注入一些javascript时遇到了JavaScript执行顺序的问题:



这是我的HTML页面I用于测试 test.html

 < html> < HEAD> 
< title>测试页< /标题>< / head>
< body>
< script>
console.log(In page);
< / script>
< / body>
< / html>





这是我用来向HTML页面注入额外代码的JavaScript, injector.js


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



这是注入脚本的内容, inject.js

  console.log(Inside inject.js); 



最后,这是我的 清单。 json

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



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

 注入完成
在页面
里面inject.js



我的问题是,为什么在页面中打印出 Inside inject.js ?因为我将 run_at 设置为 document_start,所以不应该是 inject.js



如果是这样设计的,有什么办法可以确保inject.js内的内容在脚本之前执行HTML页面,而不改变HTML页面内的任何内容



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

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

解决方案

在Chrome中,注入的脚本具有 src 属性异步执行。

考虑以下HTML文件:

 < html>< head> 
< title> Chrome早期脚本注入,测试页< /标题>
< script>
var s = document.createElement(script);
s.src =localInject1.js;
document.documentElement.appendChild(s);
< / script>
< / head>
< body>
< p>请参阅控制台。< / p>
< script src =localInject2.js>< / script>
< script> console.log(In page:,new Date()。getTime()); < /脚本>
< / body>
< / html>

其中 localInject1.js 只是:

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

localInject2.js 为:

  console.log(在页面的脚本2中:,new Date()。getTime()); 



名义上,控制台应显示:

在页面的脚本1中:...
在页面的脚本2中:...
在页面中:...





但经常发生,特别是无缓存重新加载,你会看到:
$ b

 在页面的脚本2中:... 
In页面:...
在页面的脚本1中:...



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




我不确定这是否是一个错误。 Firefox也不按顺序获取脚本,但似乎更加一致。似乎没有任何相关的Chrome错误,并且规格对我来说不清楚。



$ b $ h
$ b

解决方法:

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 Running correctly!,new Date()。getTime());';
document.documentElement.appendChild(s);

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

您会看到:

 文本正确运行! ... 
注入完成...
在页面
里面inject.js



无可否认,这在内容脚本中可能会很痛苦,但在W3C和浏览器供应商解决此问题之前,您可以做的只有一件事(在Chrome中)。


I am having some problem with the order of javascript execution when I use the content script to inject some javascript into the HTML page:

This is my HTML page I use to test, test.html:

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


This is the javascript I use to inject additional code into HTML page, injector.js:

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


And this is the content of injected script, inject.js:

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


And finally, this is my manifest.json:

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


Now, when I open up the test.html, this is what I got in my console:

Inject finished
In page
Inside inject.js


My question is, why is In page printed out before Inside inject.js? Isn't inject.js supposed to be run first since I set the run_at to document_start?

If this is by design, is there any way I can make sure that the content inside inject.js is executed before the script inside the HTML page while not changing anything inside the HTML page?

Setting the async attribute to false before appendChild doesn't seem to work since it is used for the ordering between the external scripts, not between external scripts and in-page script.

BTW, I am testing this on Chrome 27.0.1453.9

解决方案

Injected scripts, with src attributes are executed asynchronously in Chrome.
Consider this HTML file:

<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>

where localInject1.js is just:

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

and localInject2.js is:

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


Nominally, the console should show:

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


But frequently, and especially on cache-less reloads, you'll see:

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


Setting s.async = false; makes no difference.


I'm not sure if this is a bug or not. Firefox also gets the scripts out of order, but seems more consistent about it. There don't seem to be any relevant Chrome bugs, and the specs are unclear to me.


Work around:

Scripts with code set by textContent, rather than a file linked by src, execute immediately as you would expect.
For example, if you changed injector.js to:

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() );

you would see:

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


Admittedly this can be a pain in a content script, but it may be all you can do (in Chrome) until this issue is resolved by the W3C and browser vendors.

这篇关于我注入的&lt; script&gt;在目标页面的JavaScript之后运行,尽管使用了run_at:document_start?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆