我正在开发一个项目,该项目要求我的用户脚本在页面上运行,而不会执行任何页面的JavaScript。也就是说,我们需要禁用JavaScript浏览。
当我尝试延迟脚本中的函数执行时,我遇到了一个问题。每当我调用window.setTimeout
时,我传入的函数永远不会被执行。
我想也许这个函数实际上是在unsafeWindow
而不是窗口上调用的。这有什么解决方法吗?
我应该提一下,当启用JavaScript并且我的脚本中的其他所有内容在没有启用JavaScript的情况下工作正常时,对setTimeout
的调用工作正常。
感谢您的帮助!
答案 0 :(得分:4)
尽管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 。
答案 1 :(得分:2)
window
引用仍然是页面的window
,只是包装在沙箱包装器中。当你打电话给setTimeout
时,你仍在设置要由页面运行的内容。我认为必须是这样的情况,当Javascript被禁用时,浏览器根本不会触发那些超时事件(或者只是忽略事件)。
答案 2 :(得分:0)
这可以像这样打补丁:
你可以对NoScript + setTimeout =失败
说NO在greasemonkey.js
中:找到[injectScripts]:function .....添加我们的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);
}
或
sandbox.setInterval = function (callback, timeout, p1,p2,p3/*....*/){
var args = Array.prototype.slice.call(arguments,2);
return sandbox.window.setInterval(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' )
}
sandbox.kk_setTimeout = function (func, timeout, repeat_type, p1,p2,p3/*....*/){
var callback = { k100: sandbox };
var args = Array.slice.call(arguments,3);
// repeat_type: 0=once 1=repeatng, after fired stopped 2=always repeat
if(repeat_type!=2){
callback.notify = function (timer){ func.apply(this.k100,args); }
var timerCC = Components.Constructor("@mozilla.org/timer;1", "nsITimer", 'initWithCallback');
var R = repeat_type?1:0;
} else {
callback.observe = function (subject, topic, data) { func.call(this.k100); };
var timerCC = Components.Constructor("@mozilla.org/timer;1", "nsITimer", 'init');
var R = 2;
}
return new timerCC(callback, timeout, R);
}
// now have to test it:
var test100 = kk_setTimeout(alert, 1000, 0, 'i am timer'); //running = setTimeout
var test100 = kk_setTimeout(alert, 1000, 2, 'i am timer'); //running = setInterval
test100.cancal() ; //clear it by cancel() method
kk_setTimeout(alert, 1000+20*j, 2, 'i am happy' );
var j=300;
for(;~j;j--){
kk_setTimeout(alert, 1000+20*j, 0, 'i am happy 2' );
}
//bug:
//this solution 2 running after about 3-8 times differently stop, why bug ? i don't know.
// you will fail to use many times(over 3-8 time) kk_timeout(); or using repeat_type = 2 after fired 3-8 times timeout
//or running total time max about 20-30 seconds stop
//--- this maybe stop by option in about:config -- about [max javascript run time]
china-kkmove patched
编辑以添加...
对不起大家,
我忘记编写的代码仍有一些补丁:
sandbox.window = sandbox._proto_; // add this line also to the solution 1#
今天早上我才想到这个错误。