Javascript 浏览器中禁用JS时,setTimeout无法在Greasemonkey用户脚本中工作

Javascript 浏览器中禁用JS时,setTimeout无法在Greasemonkey用户脚本中工作,javascript,greasemonkey,settimeout,Javascript,Greasemonkey,Settimeout,我正在从事一个项目,该项目要求在呈现页面时在页面上运行我的用户脚本,而不执行页面的任何JavaScript。也就是说,我们需要禁用JavaScript进行浏览 但是,当我试图延迟脚本中函数的执行时,遇到了一个问题。每当我调用window.setTimeout时,我传入的函数永远不会执行 我想可能这个函数实际上是在unsafeWindow而不是window上被调用的。有什么解决办法吗 我应该提到,当启用JavaScript时,对setTimeout的调用可以正常工作,而脚本中的所有其他内容在不启用

我正在从事一个项目,该项目要求在呈现页面时在页面上运行我的用户脚本,而不执行页面的任何JavaScript。也就是说,我们需要禁用JavaScript进行浏览

但是,当我试图延迟脚本中函数的执行时,遇到了一个问题。每当我调用
window.setTimeout
时,我传入的函数永远不会执行

我想可能这个函数实际上是在
unsafeWindow
而不是window上被调用的。有什么解决办法吗

我应该提到,当启用JavaScript时,对
setTimeout
的调用可以正常工作,而脚本中的所有其他内容在不启用JavaScript的情况下都可以正常工作


谢谢你的帮助

窗口
引用仍然是页面的
窗口
,只是用沙盒包装器包装。当您在上面调用
setTimeout
时,您仍然在设置要由页面运行的内容。我想,当禁用Javascript时,浏览器根本不会触发这些超时事件(或者忽略这些事件)。

即使Greasemonkey Javascript以提升的权限运行,正如Pointy所说,
setTimeout
函数被附加到页面的JavaScript空间——根据需要封装在闭包中。(在正常操作中,Greasemonkey实例通常会在任何计时器启动时消失。)

因此,如果页面的主JavaScript被禁用,计时器将永远不会运行

可能的解决办法:

  • 使用
    GM_xmlhttpRequest
    作为原始延迟。您可以设置一个页面,故意提取其响应。所以代码如下:

    GM_xmlhttpRequest
    (
        {
            method: "GET",
            url:    "http://YourTestServer.com/DelayService.php?Seconds=2",
            onload: function (response) {YourDelayedFunctionHere (); }
        }
    );
    
    将调用您设置的实用程序页来为您执行延迟

  • 使用NoScript禁用除主页之外的所有页面JavaScript。例如,对于页面,YourSite.com/testpage.htm,其中包括来自(比如)SpamGenerator.net的脚本。。。允许来自YourSite.com的脚本,但阻止来自SpamGenerator.net的脚本


可以这样修补:

setTimeout(alert,1000, 'i am happy');
var loopid = setInterval(alert, 1000, 'I am happy again');
setTimeout(clearInterval, 5000, loopid);

var j=300;
for(;~j;j--){ //running perfectly!
    setTimeout(alert, 1000+20*j, 'I am happy' )
}
您可以对NoScript+setTimeout=failed说不

greasemonkey.js
中:查找[injectScripts]:函数。。。。。添加我们的GM api

添加此代码:

sandbox.setTimeOut = function (callback, timeout, p1,p2,p3/*....*/){
    var args = Array.prototype.slice.call(arguments,2);
    return  sandbox.window.setTimeout(function(){
        return callback.apply(sandbox, args);
    } ,timeout);
}

这段代码运行良好,我从2010年5月开始使用它

user.js
中,您可以这样测试它:

setTimeout(alert,1000, 'i am happy');
var loopid = setInterval(alert, 1000, 'I am happy again');
setTimeout(clearInterval, 5000, loopid);

var j=300;
for(;~j;j--){ //running perfectly!
    setTimeout(alert, 1000+20*j, 'I am happy' )
}
解决方案2 中国移动已修补


编辑以添加

对不起各位

我忘记编写的代码中还有一些补丁:

sandbox.window = sandbox._proto_; // add this line also to the solution 1#

今天早上我突然想到了这个错误。

我不知道,但也许NoScript扩展可以帮你一些忙:NoScript看起来很有前途。我会进一步调查的。我没有时间测试atm,但我想如果我将localhost设置为唯一受信任的站点,那么我应该得到我想要的行为。。。谢谢你!但是因为它已经包装好了,所以它实际上不是页面的窗口,对吗?Greasemonkey可以定义其行为,而不是允许页面这样做。我想知道通用汽车是否可能只是在函数调用上下赌注,并允许原始窗口(即unsafeWindow)来处理它。(编辑:最后,我的理解和你的一样。调用被设置并忽略。现在我只是想知道是否有办法解决这个问题。也许可以在使用窗口对象之外延迟函数执行…?)如果浏览器认为它不应该运行任何Javascript事件处理程序,那么Greasemonkey可能就没有发言权。我还没有找到任何明确的文档说明当页面上禁用Javascript时会发生什么。显然,“本机”事件处理仍然有效——例如,您仍然可以通过单击“提交”按钮提交表单,而复选框和单选按钮对我无效。NoScript对我无效,因为我需要从主页以及任何其他非我的用户脚本源禁用JavaScript。另一方面,XMLhttpRequest工作得很好(尽管它完全是一个黑客程序)。谢谢你的洞察力,布洛克!这不是每次GM附加组件更新时都会被覆盖吗?此外,此解决方案是不可移植的,这使得共享用户脚本变得更加困难。
sandbox.window = sandbox._proto_; // add this line also to the solution 1#