revisiting __parent__ traverse

__parent__のlexical scope, activation objectのやつ。


Bug 355590 – __parent__ should not expose lexical scope or activation objects

__parent__ was always just a reflection of JSSLOT_PARENT. So compatibility is
maintained by leaving the code alone, just censoring the lexical scope objects.
It turns out that __parent__ is handy for debugging (possibly for the
testsuite too) as a way to get to the Call object, but we can provide an
alternative method for the suite if we have to. The other, valid uses of
__parent__ (e.g. to get to the DOM scope chain link) continue to work.

We don't want to let would-be lexical scopes to leak via either __proto__ or
__parent__, and so the patch does not depend on the id of the built-in property
being accessed.

よく読んだらECMAのscope chainが__parent__で取れるのはまずいから取れなくしたってことだった。lexical scopeといっているのはscope chainのひとつひとつのscopeのこと。でも 10 実行コンテキスト (Execution Contexts)によればscopeであるactivation objectは

Activation オブジェクトは純粋に仕様のメカニズムである。 Activation オブジェクトへのアクセスは ECMAScript プログラムには不可能である。

で、いちおう原文を確認してみたらやっぱり

It is impossible for an ECMAScript program to access the activation object.

なのでviolationでも never exposes the activation objects to scripts. でもなくて、実装上出すべきではないだけじゃないのかなー。仕様書のimpossibleは must not みたいに不可能にしないといけないって意味ではないよね。


そういうわけでfirefox(spidermonkey)の__parent__は、デバッグのためにあるもので、ソースコードを見ると

    if (pobj) {
        clasp = OBJ_GET_CLASS(cx, pobj);
        if (clasp == &js_CallClass || clasp == &js_BlockClass) {
            /* Censor activations and lexical scopes per ECMA-262. */
            *vp = JSVAL_NULL;
        } else if (clasp->flags & JSCLASS_IS_EXTENDED) {
            xclasp = (JSExtendedClass *) clasp;
            if (xclasp->outerObject) {
                pobj = xclasp->outerObject(cx, pobj);
                if (!pobj)
                    return JS_FALSE;
                *vp = OBJECT_TO_JSVAL(pobj);
            }
        }
    }

こうなってるのでスコープのオブジェクトに JSCLASS_IS_EXTENDED がついてないとアクセスできない。

JSCLASS_IS_EXTENDEDはeval第二引数permission deniedのときに見たとおり

XPCOMコンポーネントなどのXPCWrapperdNativeを通してアクセスされるオブジェクトは、spidermonkeyの中で内部的に生成されるクラスがJSExtendedClassになっている。

なので __parent__ で得られるのは、必ずXPCOMインスタンス等。スクリプトで生成されたオブジェクトが__parent__に入っていることはない。

objectの属してるactivation objectが__parent__に入ってて、それがstandard classだとnullになるってことかな。window以外に何が入ってる可能性があるのかがよくわかんない。xpcomインスタンスでscopeになりえるやつってなんだ?