Greasemonkey: 当@run-at document-start 时 document.head 为空

创建于 2017-06-15  ·  9评论  ·  资料来源: greasemonkey/greasemonkey

环境

钥匙 | 价值
-- | --
系统平台 | AMD64、Windows-10-10.0.14393
浏览器 | Firefox 开发者版(55.0 Beta 1,64 位)
用户代理 | Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:55.0) Gecko/20100101 Firefox/55.0
构建配置 | https://hg.mozilla.org/releases/mozilla-beta/rev/6872377277a618b2b9e0d2b4c2b9e51765ac199e
油猴 | 3.11

测试用户脚本:

// ==UserScript==
// <strong i="15">@name</strong>        HeadTest
// <strong i="16">@namespace</strong>   HeadTest
// <strong i="17">@include</strong>     *
// @run-at      document-start
// <strong i="18">@version</strong>     1
// <strong i="19">@grant</strong>       none
// ==/UserScript==
AddGlobalStyle('body{background-color:red;}');

function AddGlobalStyle(css) {
    var head, style;
    head = document.getElementsByTagName("head")[0];
    console.log("[Test]: Head: %o", head); //DEBUG
    console.log("[Test]: document.head: %o", document.head); //DEBUG
}

预期结果:

[Test]: Head:  <head> 
[Test]: document.head:  <head>

实际结果:

[Test]: Head:  undefined
[Test]: document.head:  null

此问题也适用于GM_addStyle

最有用的评论

@the8472如果当前document-start的行为是正确且有意的,那么我们每次需要添加样式时都需要使用观察者
就像是

function addGlobalStyle(css){
  let headHunter = new MutationObserver(
    records => {
    ; check mutation records
    ; is added node's tag name 'head'?
    ; create a style node then throw it in
    ; then disconnect us
   }
  );
  headhunter.observer(document, {childlist : true});
}

document-end之前添加样式的每个脚本都需要。 那很无聊。

我希望GM_addstyle可以为我做到这一点,或者在 wiki 中写一些有用的警告(“GM_addstyle 不适用于带有@run-at document-start 的脚本,不要使用它,自己找到解决方案“, 等等)

所有9条评论

@janekptacijarabaci找到了解决方法:

setTimeout(()=>{
    AddGlobalStyle('body{background-color:red;}');
});

它看起来不稳定且不可靠,但这是我目前能找到的最简单的方法。

我不认为这是一个错误。 document-start早就发生了。 这允许用户脚本在任何内容 javascript 执行之前操作页面。

如果您想稍后执行,只需使用document-end或使用突变观察者等待插入特定元素。

@the8472
也许你说的对。
根据 MDN:

文档元素插入
在创建文档的根元素之后立即发送,但在对其执行任何脚本之前发送。

document-start (基于document-element-inserted )在<html></html>创建后立即触发,此时<head>为空。

但这破坏了许多在页面呈现之前尝试添加样式的脚本(如果你使用GM_addstyledocument-end你会注意到页面在闪烁),因为它以前工作

我不确定这是故意的

GM_addStyle 无论如何都是愚蠢的,它只是在<head>中插入一个<style>标记,您可以自己执行此操作,必要时使用突变观察器。

但是,如果这是真正的问题,则可以对其进行修补以检查<head>的存在,如果不存在则使用观察者。

@the8472如果当前document-start的行为是正确且有意的,那么我们每次需要添加样式时都需要使用观察者
就像是

function addGlobalStyle(css){
  let headHunter = new MutationObserver(
    records => {
    ; check mutation records
    ; is added node's tag name 'head'?
    ; create a style node then throw it in
    ; then disconnect us
   }
  );
  headhunter.observer(document, {childlist : true});
}

document-end之前添加样式的每个脚本都需要。 那很无聊。

我希望GM_addstyle可以为我做到这一点,或者在 wiki 中写一些有用的警告(“GM_addstyle 不适用于带有@run-at document-start 的脚本,不要使用它,自己找到解决方案“, 等等)

是的,gm_addstyle 应该是固定的。

但是脚本可能做的所有其他事情也必须在文档开始时跳过相同的圈,添加在这方面并不特别的样式。 没有任何 DOM 可用,因此您必须等待所需的任何内容。 即,如果您在文档开始时运行事物,则无论如何都需要使用观察者。

感谢您的详细报告,但这是 WAI,而且 3.x 分支无论如何都已经死了。 (我,一方面,欢迎我们新的网络扩展霸主。)像GM_addStyle这样的东西将在 4.x 中永远不存在。

https://arantius.com/misc/greasemonkey/amazon-url-cleaner.user.js这样的脚本根本不需要 DOM,应该尽快运行。

此页面是否有帮助?
0 / 5 - 0 等级