フラッシュ プレーヤーのソース コードを直接見て、BoltClock の回答に追加の洞察を追加するためだけに、これを回答として投稿しています。この機能を具体的に提供する AVM コードを実際に見ることができ、C++ で記述されています。ArrayObject.cpp 内に次のコードがあります。
// Iterator support - for in, for each
Atom ArrayObject::nextName(int index)
{
AvmAssert(index > 0);
int denseLength = (int)getDenseLength();
if (index <= denseLength)
{
AvmCore *core = this->core();
return core->intToAtom(index-1);
}
else
{
return ScriptObject::nextName (index - denseLength);
}
}
返すべき正当なプロパティ (オブジェクト) がある場合にわかるように、それはScriptObject
クラス (具体的にはnextName()
メソッド) から検索されます。ScriptObject.cpp 内のこれらのメソッドを見ると、次のようになります。
Atom ScriptObject::nextName(int index)
{
AvmAssert(traits()->needsHashtable());
AvmAssert(index > 0);
InlineHashtable *ht = getTable();
if (uint32_t(index)-1 >= ht->getCapacity()/2)
return nullStringAtom;
const Atom* atoms = ht->getAtoms();
Atom m = ht->removeDontEnumMask(atoms[(index-1)<<1]);
if (AvmCore::isNullOrUndefined(m))
return nullStringAtom;
return m;
}
ここで人々が指摘したように、VM はハッシュ テーブルを使用していることがわかります。ただし、これらの関数には特定のインデックスが指定されているため、一見したところ、特定の順序付けが必要であることがわかります。
さらに深く掘り下げると (すべてのコードはここに掲載しません)、for in/for each 機能に関与するさまざまなクラスのメソッドが多数あり、そのうちの 1 つは、ScriptObject::nextNameIndex()
基本的にハッシュ テーブル全体をプルアップするメソッドであり、次の値が有効なオブジェクトを指している限り、テーブル内の有効なオブジェクトへのインデックスの提供を開始し、引数で提供された元のインデックスをインクリメントします。私の解釈が正しければ、これがランダムルックアップの背後にある原因であり、これらの操作で標準化/順序付けされたマップを強制する方法はないと思います。
ソース
Flash Player のオープン ソース部分のソース コードを入手したい方は、次の mercurial リポジトリから入手できます (github のような zip 形式のスナップショップをダウンロードできるので、インストールする必要はありません)。水銀):
http://hg.mozilla.org/tamarin-central - これは「安定版」または「リリース版」のリポジトリです
http://hg.mozilla.org/tamarin-redux - これは開発ブランチです。AVM に対する最新の変更は、ここで確認できます。これには、Android などのサポートが含まれます。Adobe はまだ Flash Player のこれらの部分を更新し、オープン ソース化しているため、現在の公式の優れたものです。
私が取り組んでいる間、これも興味深いかもしれません: http://code.google.com/p/redtamarin/。これは、AVM から分岐した (そしてかなり成熟した) バージョンであり、サーバー側のアクション スクリプトを記述するために使用できます。きちんとしたもので、AVM の仕組みについての洞察を与える情報がたくさんあるので、それも含めたいと思いました。