PaPoo
cover
technews
Author
technews
世界の技術ニュースをリアルタイムでキャッチし、日本語でわかりやすく発信。AI・半導体・スタートアップから規制動向まで、グローバルテックシーンの「今」をお届けします。

JavaScriptを“安全な別室”に追い出す? ShadowRealmが目指す世界

記事のキーポイント

本文

CSS-Tricksの記事「Soon We Can Finally Banish JavaScript to the ShadowRealm」は、タイトルからしてかなり遊び心があります。
でも中身はちゃんと真面目で、JavaScriptの実行環境を理解するうえでかなり面白い話です。

結論からいうと、この記事が紹介している ShadowRealm は、JavaScriptを「別世界に追放する」ための仕組みではなく、​他のコードに干渉されたくないコードを、きれいに隔離して動かすための新しい仕組みです。

JavaScriptは「単一スレッド」…だけど話はそれだけじゃない

JavaScriptはよく「single-threaded」と説明されます。
これはざっくり言えば、​1つの実行の流れを順番に処理する言語だという意味です。

ただ、ここでややこしいのは、​JavaScriptアプリ全体を見ると、実は複数のthreadを使えることです。
その代表例が Web Worker です。これは、JavaScriptを別のthreadで動かせる仕組みです。

なので、記事では「JavaScriptはsingle-threaded」と言うより、​JavaScript realm が single-threaded だと考えるほうが正確だと説明しています。
この言い方、かなりしっくりきます。
“言語そのもの”と“動かす場所”を分けて考えると、だいぶ理解しやすくなるからです。

realmって何?

realmとは、​JavaScriptコードが実行される環境のことです。
たとえばブラウザのタブは1つのrealmですし、Web Workerも別のrealmです。
さらに、別オリジンのiframeも、それぞれ別のrealmになります。

ここで重要なのは、​realmごとに global object が別だという点です。
ブラウザなら、たいてい Window がそれにあたります。

つまり、同じページの中にiframeがあっても、外側のページと内側のiframeは別の世界です。
見た目は同じブラウザの中にあるのに、JavaScriptから見ると「住んでいる部屋が違う」という感じですね。

記事では、次のような違いを示しています。

このへん、JavaScriptの世界は本当に「見た目が同じでも別人」みたいなことが多く、初学者にはなかなかしんどいです。
でも逆に言えば、​この“別世界感”こそが隔離の基本なんですよね。

なぜ隔離がそんなに大事なのか

JavaScriptは長年、​global scopeの汚染に悩まされてきました。
global scope とは、どこからでも見える“共有スペース”みたいなものです。

ここにいろんなコードが勝手に値や関数を置くと、次のような問題が起きます。

特に現代のWeb開発は、
フレームワーク、ライブラリ、polyfill、解析ツール、広告など、​自分で完全にコントロールできないコードを大量に読み込むことがあります。

そうなると、「このコードだけきれいな部屋で動かしたい」という需要が出てくるのは当然です。
これはかなり現実的で、実務的な話だと思います。

ShadowRealmは何が新しいのか

そこで登場するのが ShadowRealm です。
名前がもう強い。正直、かなりかっこいいです。

ShadowRealm は、​隔離専用の新しい realm です。
ポイントは、​自分専用の global object と built-in objects を持つけれど、別threadは持たないこと。

つまり、ShadowRealm の中で動かすコードは:

という性質を持ちます。

これは Web Worker とはかなり違います。
Web Worker は並列処理向きですが、ShadowRealm は並列化のためではなく、隔離のためにある、というのが面白いところです。

個人的には、ここがこの提案の一番おいしい部分だと思います。
Web Worker は「重い処理を別スレッドに逃がす」道具としては便利ですが、​単に安全に隔離したいだけなのに、スレッド間通信の手間まで背負うのは大げさなんですよね。
ShadowRealm はその不満にかなり素直に応えています。

どう使うのか

記事では、ShadowRealm のAPIはかなりシンプルだと説明されています。

const shadow = new ShadowRealm();

これで ShadowRealm を作ります。

たとえば外側の realm にこんな関数があったとしても、

function globalFunction() {}

ShadowRealm の中からは見えません。

shadow.evaluate('globalThis.globalFunction'); // undefined

逆に、ShadowRealm の中で関数を定義しても、外側には漏れません。

shadow.evaluate('function globalFunction() {};');
globalThis.globalFunction; // undefined

要するに、​外と中はかなりきれいに分離されるわけです。

この“きれいさ”は、地味だけどかなり大事です。
現場で本当に欲しいのは、壮大な魔法よりも「余計なものが入ってこない、予測しやすい環境」だったりしますから。

ただし、完全な安全地帯ではない

ここは誤解しやすい点ですが、ShadowRealm は真のセキュリティ境界ではないと記事は明言しています。
つまり、「これに入れたら絶対安全」という意味ではありません。

その代わり、​integrity boundary だと考えるのがよい、という説明です。
これはざっくり言うと、​**外から直接いじられにくい“整合性の境界”**みたいなものです。

中のコードは外のコードに直接干渉しにくい。
でも、完全に別世界として孤立していて、何も影響し合わないわけではない。
このあたりは、過信しないのが大事だと思います。

何に使えそうか

記事では、ShadowRealm の用途として次のようなものが挙げられています。

これ、かなり現場目線で便利そうです。
特にテストは相性がよさそうです。
「前のテストが残した何か」が次のテストに影響する、あの地味にイライラする問題を減らせるなら、かなり嬉しい。

まだ未来の話

重要なのは、この記事時点では ShadowRealm はまだ提案段階だということです。
ES-262 standardにも、ブラウザにも、まだ実装されていないとのことです。

つまり、今すぐ使える実用機能というより、​JavaScriptの将来像のひとつとして見るのが正しいです。

とはいえ、こういう提案が出てくること自体が面白いです。
JavaScriptは長く「雑に広がってしまった世界」を抱えてきた言語なので、今になって“隔離”をちゃんと考えるのは、むしろ自然な進化だと思います。

まとめ

ShadowRealm は、JavaScriptに「もうひとつの部屋」を用意する提案です。
ただしその部屋は、ただの別室ではなく、​外の散らかりに影響されず、外にも余計なものをばらまかないための部屋です。

Web Worker ほど大げさではなく、iframe ほど重くもない。
それでいて global scope の汚染を避けやすい。
このバランス感覚はかなり魅力的だと思います。

もし将来これが標準化されれば、JavaScriptの「ごちゃごちゃしやすさ」に対する、かなり実用的な解決策になるのではないでしょうか。


参考: Soon We Can Finally Banish JavaScript to the ShadowRealm | CSS-Tricks

同じ著者の記事