🎄
ENCA 19日目: `eval?.()` の direct eval 化(リジェクト)
direct eval とは
eval
函数を実行する際、参照される変数名が eval
そのままで実行される場合を direct eval と呼び、そうでない indirect eval と区別しています。direct eval はそのスコープでの実行となりますが indirect eval は別のコンテキストで実行されます(新しく <script>
タグが作られて実行されると考えるとわかりやすいかもしれません)。
globalThis.foo = "global foo";
{
const foo = "shadowed foo";
// direct eval
console.log(eval("foo")); // "shadowed foo"
// indirect eval
const indirectEval = eval;
console.log(indirectEval("foo")); // "global foo"
}
なぜこんなややこしい仕様になっているかというとガベージコレクションのためです。direct eval の場合は解析時に eval
函数が使われることがわかりますが indirect eval は検知できません。スコープ内の変数にアクセスできてしまうとガベージコレクションが出来なくなってしまいます。
JavaScript エンジンのガベージコレクションについては以下の記事が詳しいです。
eval?.()
の direct eval 化(リジェクト)
ES2020 に Optional Chaining が入りました。さて eval?.()
のように実行した場合、解析時に eval
が使われていることを検知することが出来ますが indirect eval として扱われていました。2020年7月にこれを direct eval に変更、もしくはいっそのこと SyntaxError
としてしまうかが議論されましたが、結果としてはいずれの変更も受け入れられずそのままとなりました。
Discussion