definePropertyとか__defineGetter__で設定するgetterです

Chromeの拡張機能のcontent_scriptsで使うと思ったとおりに動いてくれません

※getter関係なくChromeのcontent_scriptsのせいでした

今回、cookie使った拡張機能でも作ろうかなと思って参考にするためcookie扱う拡張機能を拾ってきてソースを読んでました

そこで明らかに無限ループになりそうなコードがあって、コンソールに貼り付けると案の定ループして
Uncaught RangeError: Maximum call stack size exceeded.
とエラーが出ました

なのに、拡張機能の方では起きてませんでした…

そのコードを必要なとこだけ取り出したのが↓です
function defineGetter() {
    var script;
    script = "(" + function() {
        document.__defineGetter__("cookie",function(){
            var event = new CustomEvent("COOKIE-GET");
            console.log("getter-dispatch-start");
            document.dispatchEvent(event);
            console.log("getter-dispatch-end");
            return "getter-result";
        }) 
    } + ")()";
    var script_element = document.createElement("script");
    script_element.appendChild(document.createTextNode(script));
    document.documentElement.appendChild(script_element);
}

// define event listener
document.addEventListener("COOKIE-GET", function() {
    console.log("listener-start");
    var a = document.cookie;
    console.log('document.cookie is "'+a+'"');
    console.log("listener-end");
});
defineGetter();
このコードをコンソールに貼り付けたり、jsファイルとして読み込むとスタックサイズを超えるとエラーがでます

コードの内容は、
defineGetter関数はdocumentオブジェクトのプロパティcookieに読み取るアクセスがあった場合にイベントCOOKIE-GETを発火させます

読んでみると、defineGetter関数は↓だけでいいのではと思うかもですが
function defineGetter() {
    document.__defineGetter__("cookie",function(){
        var event = new CustomEvent("COOKIE-GET");
        console.log("getter-dispatch-start");
        document.dispatchEvent(event);
        console.log("getter-dispatch-end");
        return "getter-result";
    }) 
}
関数を文字列化してscriptタグ作ってそれに入れて、ロードするという風にしているのは、content_scriptsとして実行した場合に作られた変数などはcontent_scriptsが終わると消えてしまうのでscriptタグを読み込みcontent_scriptsの外でgetterを設定するようにしています
getterを設定するのも変数同様content_scripts内で行うと消えるのを確認しました

下のイベントリスナは、COOKIE-GETイベントが発生した時にdocument.cookieを読み取り表示します

つまり、document.cookieにアクセスすると、getterで指定された関数が呼ばれ、それがCOOKIE-GETイベントを発生させて、COOKIE-GETのイベントリスナでdocument.cookieにアクセスするので
getter→イベントリスナ→getter→……
とループするはずです

しかし、Chrome拡張機能のcontent_scriptsから実行されると
document.cookie
getter-dispatch-start VM2900:5
listener-start content.js:20
document.cookie is "" content.js:22
listener-end content.js:23
getter-dispatch-end VM2900:7
"getter-result"
となってループしていません
イベントリスナの関数内でのdocument.cookieへのアクセスではgetterが機能せず普通にdocument.cookieの値を返しています(なんで?)

content_scripts以外でコンソールなどでこのコードを実行した場合は↓のようにループしてます
長いので途中略してます
document.cookie
getter-dispatch-start
listener-start
getter-dispatch-start
listener-start
getter-dispatch-start
listener-start
:
:
:
Uncaught RangeError: Maximum call stack size exceeded.
getter-dispatch-end
document.cookie is "getter-result"
listener-end
getter-dispatch-end
document.cookie is "getter-result"
listener-end
getter-dispatch-end
document.cookie is "getter-result"
listener-end
getter-dispatch-end
:
:
:
"getter-result"
Chromeのcontent_scriptsだけで起こるのでdatalistが動かないみたいにバグの一種かなとも思いましたが実際に使われてる拡張機能でこの方法を使ってるので裏ワザみたいなものかなとも思えます

推測ですが、content_scripts内で作った変数とか保存できないので、content_scriptsが動いてるところは実はページ内と同じ環境の別な場所であって、getter登録したのは本物のページの方だけでcontent_scriptsが動いてる方のdocumentにはgetter登録されてないから元々のdocument.cookieの値が返される…かな?

----
*追記*

推測が当たってました
content_scripts内のグローバルと、content_scriptsからscriptタグ追加による方法でグローバルにそれぞれ変数を作りました
そして、content_scripts内とコンソールの2つからグローバルに作った変数にアクセスできるか調べてみました

content_scripts内で
作成した変数
scriptタグでグローバル
に作成した変数
content_scriptsからアクセス×
コンソールでアクセス×

結果はこんな感じでcontent_scripts内は別のスコープが適用されてるみたいです
content_scriptsが終了してもcontent_scripts内の関数からはデータが見えるようにclosureとして扱われてるようです

だとすると、content_scripts内での変更をページの方でも引き継ぐ変更や、イベントリスナは受け取れるとかはどういうことなんだろう
やっぱりよくわからない…