毎秒100回対策を20分で書いてみようとして失敗したという話

  1. Googleのトップページを開くと毎秒100回JavaScriptが実行されるよ
  2. そうですか。
  3. window.focusとwindow.blurが切り替わる度に実行を止めるsetTimeoutラッパー作ればいいんじゃねーの?(window.focusはFirefoxだとちゃんと考えているような挙動するっぽいので正しいと仮定する)
  4. 書いた。
  5. テストはなんか上手くいった。
  6. Greasemonkeyに移植した。
  7. うまく動かなかった←今ここ
// ==UserScript==
// @name           Google 100
// @namespace      userscript
// @include        http://www.google.co.jp/
// ==/UserScript==

var script = document.createElementNS("http://www.w3.org/1999/xhtml", "script");
script.type = "application/javascript; version=1.7";
script.text = <><![CDATA[
(function () {

	var flag = false, cnt = 0, ids = {}, gns = {},
	    $setTimeout    = setTimeout,
	    $clearTimeout  = clearTimeout,
	    $setInterval   = setInterval,
	    $clearInterval = clearInterval;

	window.addEventListener("focus", function () {
		flag = true;
		for (var id in gns) {
			var g = gns[id];
			delete gns[id];
			g.next();
		}
	}, false);
	window.addEventListener("blur", function () {
		flag = false;
	}, false);

	var _setTimeout = function (fn, ms) {
		++cnt;
		var id = cnt;
		yield id;
		ids[id] = $setTimeout(fn, ms);
	};

	window.setTimeout = function (fn, ms) {
		var f = _setTimeout(fn, ms);
		var id = f.next();
		if (flag) {
			f.next();
		}
		else {
			gns[id] = f;
		}
		return id;
	};

	window.clearTimeout = function (id) {
		delete gns[id];
		$clearTimeout(ids[id]);
		delete ids[id];
	};

	var _setInterval = function (fn, ms, id) {
		if (!id) {
			++cnt;
			id = cnt;
		}
		yield id;
		ids[id] = $setInterval(function () {
			fn();
			if (!flag) {
				$clearInterval(ids[id]);
				var f = _setInterval(fn, ms, id); f.next();
				gns[id] = f;
			}
		}, ms);
	};

	window.setInterval = function (fn, ms) {
		var f = _setInterval(fn, ms);
		var id = f.next();
		if (flag) {
			f.next();
		}
		else {
			gns[id] = f;
		}
		return id;
	};

	window.clearInterval = function (id) {
		delete gns[id];
		$clearInterval(ids[id]);
		delete ids[id];
	};

})();
]]></>;
document.documentElement.appendChild(script);

誰かGreasemonkeyJavaScript 1.7を実行する方法を教えてくれると助かります。ちなみにyieldは使ってみたかっただけです。使わなくてもできると思う。

まぁ、何が言いたいかというと、10回だろうが100回だろうが1000回だろうが、とりあえず、気にくわないところがあれば、Greasemonkey書けばいいのさ。