Posts tagged "javascript"

――なぜアレンさんはECMAScriptの仕様に関わるようになったのでしょうか。

 ECMAScriptに関わるようになったのは、私がマイクロソフトに勤めていた頃でした。当時は動的言語のテクニカルエキスパートをしていました。10年ほど前のこと、私のボスから「JavaScriptを知っているか?」とメールが来て「いや、知らない」と答えたところから、私とJavaScriptとの関わりが始まりました。

 調べていくなかで、JavaScriptがブラウザの中でどういう風に動いているか分かり「これはすごい言語だ、JavaScriptは21世紀で最も重要な言語に違いない」と思ったので、標準化に参加するようになりました。

#19 ES7 sideshow

mozaicfm:

#19 ES7 SideShow

Theme

第19回目の Side Show です。

@Constellation さんが語る JavaScript Engine (JSCore) での実装の裏話と、 WebAssembly についてお送りします。

なお、エピソード内で「何よりも ES6 module が欲しい」という要望を出していましたが、 @Constellation さんが、 実装に着手してくれました!! 楽しみに待ちましょう!!

Bug 147340 - [ES6] Implement ES6 Modules

Guest

Show Note

#19 ES7

mozaicfm:

#19 ES7

Theme

第19回のテーマは ES7 です。

今回は @Constellation さんをお迎えして、先日公開された ES6 をふまえ、次の仕様として議論が始まった ES7 について、 ブラウザのエンジンを実装する立場から見た、現状や懸念点などについて話を聞きながら、これから ECMAScript はどうなっていくのか、どうなっていくべきなのかについて議論しました。

Guest

Show Note

Webの高速化によって失われるもの

0-9:

このエントリはFrontrend Advent Calendar 2013 - Adventar 25日目の記事です。

最近asm.jsやPNaClやSPDYやHTTP2.0が話題になっていますが、その影で個人的に気になっていることがあります。

それはHackability

Hackabilityとはこの記事に詳しく書かれていますが、簡単に言うと「外部からの手の加えやすさ」(私の理解では)

最初に挙げた技術(asm.jsやPNaClやSPDYやHTTP2.0)は「Webの高速化」という点で大きな効果が期待されています。

しかし、同時に「これまでの技術に比べてHackabilityが低い」という点も持ち合わせています。
(asm.jsは素のJSとはいえ「元コードへアクセス出来ない」という点で既存の技術に比べると低いと考えています)


これらの技術が使われている場合、以下の様なことはこれまでより困難になります。

  • 「ちょっとJavaScriptコードを送り込んで動作を変える」
  • 「簡単に通信を覗いてどんな内容をやりとりしてるか見る」

これはビジネス的に歓迎できる部分もありますが、これまでWeb上の技術が「ビジネス的に問題がある」と言われつつHackabilityを守ってきたことを考えると大きな損失だと思っています。


もちろん、「コンパイル済みのJS」という点ではCoffeeScriptやTypeScript、JSX、HexeなどのAltJSも同じです。

しかし、これらAltJSがSourceMapで元コードを残せることに対して、asm.jsやPNaClは元コードを残すことが難しくなっています。
(「コンパイル時に最適化を切れば残せる」という話を聞きましたが、AltJSがSourceMap対応しても大きなペナルティが無いことに対して、最適化を切ることは速度的なペナルティがあるため実施される可能性は低いでしょう)


もちろんこれらの技術は高速化の意味合いが強く、すべてのWebコンテンツが使用する前提のものではありません。

ですが、これらの技術を使用することは、これまでWebがビジネス的な問題などを指摘されつつも保ってきたHackabilityを損なうものだということは意識して使ってほしいと思っています。


asm.jsとかPNaClとかLLVMに興味あったので調べて回ったら少しだけ理解できた話 - hdk_embeddedの日記

HTTP/2.0がもたらす Webサービスの進化(後半)

Array.reduceがようやく腹落ちした

0-9:

自分的「存在は知ってたけど使い道がわからなかったMethod」ランキング上位のArray.reduceがようやく腹落ちしたのでメモする

jQuery.extend的なコードをこんなかんじで書いてみた

function extend () {
    return [].slice.call(arguments).reduce(function (base, obj) {
        return Object.keys(obj).reduce(function (base, key) {
            return (base[key] = obj[key], base);
        }, base);
    }, {});
};

処理的には以下と同じような動作になる。

function extend () {
    var result = {};
    var args = [].slice.call(arguments);
    for (var i = 0, l = args.length; i < l; i++) {
        var arg = args[i];
        var keys = Object.keys(arg);
        for (var j = 0, k = keys; j < k; j++) {
            var key = keys[j];
            result[key] = arg[key];
        }
    }
    return result;
};

こんなかんじで使う

function hoge (option) {
    option = extend({
        'hoge' : 'base',
        'foo' : 'bar'
    }, option);
    // optionを使った処理
}
hoge({
    'hoge' : 'huga'
});

処理速度的にはあまり変わらない

for vs reduce · jsPerf

使い道がわからなかった理由は第2引数を知らなかったら

第2引数で初期変数が与えられるので「配列を処理して別の形で返す」事ができる

function ArrayToObject (array) {
    array.reduce(function (base, item) {
        return (base[item] = true, base);
    }, {});
};
ArrayToObject([1, 2, 3]);
// Object {1: true, 2: true, 3: true}

HTMLElementのdata attributeの使いどころ

0-9:

Twitterでアプリの状態をdata-*属性で管理するかJavaScriptの変数で管理するかの使い分けに関して質問を受けたので、まとめてみました。

個人的には以下の様な理由から、data属性はJSから参照する変数の初期値としてのみ使用し、JSから直接状態を保持するための変数としては使用しないほうがいいと思っています。

  • Objectを保持できない
    JSのObjectは.toStringされた結果が保持されるため、JSの内部状態をそのまま保持できません

  • DOMアクセスが有るため遅い
    これに関してはベンチマークをとったわけではないですが、JS内で完結する変数アクセスに比べると速度的なペナルティはあると思います
    (data-*もCSSから参照できるからそのへんの解決もいるし)

jQuery.fn.dataの実装はこれらの問題をある程度解決しているので、「HTMLElement毎の独自変数を保持したい」という場合にはjQuery.fn.dataかそれに近い実装を行うのがいいと思っています。

ただ、以下の様な理由がある場合にはdata属性で変数(状態)を保持したほうがいいと思います。

  • DOM経由で外部から参照したい
    具体的には「extension等で直接JSの変数が参照できない対象から内部の状況を触らせたい場合」を想定しています。

  • DOMごと状態をシリアライズしたい
    具体的には「任意のタイミングでelement.innerHTML経由で内部の状態も含めて書き出したい場合」を想定しています。

  • デバッガから参照させたい 具体的には「debuggerのelements tab等から内部状態を参照させたい」を想定しています。

JavaScript書くのに入れとくといいもの

0-9:

Chrome Canary

DevToolsも進化してるのでStableではなくCanaryを

Local Proxy

PCのみならDevToolsだけでもいいけど、スマホのWebView内解析とか考えるとLocal Proxyは必須

Windowsなら Fiddler (無料)
Macなら Charles (有料)
Macでお金払うのが嫌な場合 CocProxy for nginx (無料。CUI。Ruby版使うくらいならこちらを)
JS製が良くてソース読みたいなら Klepto (無料。GUI。不安定)

ソースの文字コード変更

ChromeでJS、CSS開くと日本語が化けるので、初期文字コードをUTF-8に変更
フォント設定の一番下を「Unicode (UTF-8)」に)

“This Frame” Context Menu

iframeの右クリックメニューに「このframeを新しいタブで開く」メニューを追加するChrome拡張

JSONView

JSONを直接開いた時にFormat、Syntax highlightしてくれるChrome拡張


以下手前味噌

contextmenu-source

右クリックメニューに「このページで読み込んでるJS、CSSのリンク」を追加するChrome拡張

source-editor

ソース表示画面にJS製のエディタ仕込んでコード修正できるようにするChrome拡張
(Syntax highlightも入るのでそのためだけでもおすすめ)

setIntervalで監視しつつコードを実行するときの注意点

0-9:

以下のコードがベース

var interval = setInterval(function () {
    // 前提条件
    if (!$('body').length) {
        return;
    }
    // 実行コード
    alert('ready!');
    // 監視停止
    clearInterval(interval);
}, 100);

このコードの問題点
「コード実行時に前提条件が満たされてても必ず100ms待ってしまう」

改善

var interval = setInterval((function () {
    // 前提条件
    if (!$('body').length) {
        return arguments.callee;
    }
    // 実行コード
    alert('ready!');
    // 監視停止
    if (interval) {
        clearInterval(interval);
    }
})(), 100);

このコードの問題点
「arguments.calleeを使っているので”use strict”環境下で動作しない」

改善

var interval = setInterval((function checkReady () {
    // 前提条件
    if (!$('body').length) {
        return checkReady;
    }
    // 実行コード
    alert('ready!');
    // 監視停止
    if (interval) {
        clearInterval(interval);
    }
})(), 100);

このコードの問題点
「古いIEはfunction式の動作が標準的でない」
(スマホだけを考えるならこれでもOK)

改善

var interval = setInterval(checkReady, 100);
checkReady();
function checkReady () {
    // 前提条件
    if (!$('body').length) {
        return;
    }
    // 実行コード
    alert('ready!');
    // 監視停止
    if (interval) {
        clearInterval(interval);
    }
}

基本的にはこのコードでOK
パフォーマンス(setIntervalの呼び出しコスト)が問題になる場合以下
(ただし、この形式でパフォーマンスが問題になる場合、先に監視間隔を見直すこと)

// スコープの明示のためにここで宣言
var interval;
if (checkReady()) {
    return;
} else {
    interval = setInterval(function () {
        if (!checkReady()) {
            return;
        }
        // 監視停止
        clearInterval(interval);
    }, 100);
}
function checkReady () {
    // 前提条件
    if (!$('body').length) {
        return false;
    }
    // 実行コード
    alert('ready!');
    return true;
}

それ以外に注意すること

  • ifのブロックは省略しない

デバッガ上で条件文内にbreakpointが貼れないから
(この問題がなければ省略して問題ない)

  • JSコンパイラの動作

Closure Compilerは以下の様な圧縮をするので注意

(function hoge () { alert(1); })();
// (function () { alert(1); })()
// OK
// functionの名前に指定しているhogeは使用していないので、削除されても問題ない

(function hoge () { alert(hoge); })();
// (function hoge () { alert(hoge); })()
// OK
// functionの名前に指定しているhogeは使用しているが、削除されていないので問題ない

var huga = (function hoge () {})(); alert(huga.name);
// var huga=function(){}();alert(huga.name);
// NG
// functionの名前に指定しているhogeを使用しているが、削除されているので動作が変わっている

近況

xkansan:

  • XMLHttpRequest (XHR) の結果を Document として受け取る場合に、 xhr.response.URLが GM_xmlhttpRequest で言うところの finalUrl 相当の値を返すように(仕様上は)なっている、という話をこれまで何回か書いてきたのだけれど、気がついたら Editor’s Draft だけでなく Working Draft にも反映されていた。
    • これは XMLHttpRequest Living Standard にも同じく反映されている。
    • そのこと自体を喜ばしく思う一方で、現時点ではどのブラウザもこの仕様を反映してはいないようだ。
  • というわけで手始めに Firefox にバグとして報告して、ついでにパッチも書いた。Bug 859095
    • ただしこれまでブラウザ拡張では xhr.response.URL が cross origin へのリクエスト時でも same origin の URL を返すことを利用して same origin の Document を読み込んだのかを判定する、ということがそれなりに行われてきた(らしい)ので、Bug 859095 による挙動の変更を受け入れても大丈夫かどうかを Mozilla 側で判断している、というのが近況。
    • このバグの中で意見を求められている Jonas さんは今 Boot2Gecko まわりの作業で忙しいようなので、結論が出るまでまだ時間がかかりそう。
  • はやく xhr.response.URLが仕様どおりの値を返すようになるといいと思っている。
    • というのは、仕様どおりの値を返すようになれば XHR のリクエストが別 origin にリダイレクトしたかどうかを判定できるようになるので、 jQuery Mobile を使っているドメインにオープンリダイレクタがあったら XSS の問題が発生する (http://subtech.g.hatena.ne.jp/mala/20110711/1310391177) だとか、Rails の Turbolinks (https://github.com/rails/turbolinks/issues/195) の様な問題を、オープンリダイレクタがある場合も含めて JavaScript 側で対処できるようになると考えているからだ。
    • 現状では、オープンリダイレクタとリダイレクトの情報を提供しない壊れた API を掛け合わせて最強の XSS をつくろう、といった風になってしまっているので、そこは早く XHR の実装を仕様に合わせて解決させていく方がいいのでは、と思っている。
“HTML や XML のようなマークアップを発展させ拡張可能な UI を作る技術は、
WPF から Flex まで星の数ほどある。中でも Web Components は XBL という技術を先祖にもっている。
10 年以上前、Mozilla が XUL のお供に作った XML ミタメ定義言語(のようなもの)が XBL だ。
ただ XBL は多機能すぎ、また XML に傾倒しすぎていた。
そこで XBL を簡素化し、10 年来のウェブの変化や JavaScript の隆盛を踏まえ
今風に再発明したものが Web Components である。
API は新しく仕切りなおされたため、先祖の面影を伺うことはほとんどできない。
でも Web Components 関連標準の謝辞は XBL を参照しているし、Shadow DOM のコンセプトも XBL に由来する。”

始まったばかりとはいえ Polymer プロジェクトの影響は大きい。 その影響で Web Components は仕様も実装も大きく磨きがかかった。

たとえばあるとき Polymer の polyfill をネイティブ実装に切り替えて デモアプリを動かしたところ表示が乱れ、更にはブラウザがクラッシュした。 ページロードが異常に遅いなんて問題もみつかった。 実際のアプリケーションを通じて初めてみつかるエッジケースの数々を Polymer は暴きだし、 私や近隣の同僚は慌ててそれを直した。Polymer の実装が進むたびにそんなバグがやってくる。私達はそれを直す。

また標準で定義された API の不備不足も沢山みつかり、W3C のメーリングリストやバグトラッカーを賑わしている。 頑張って定義した複雑な挙動があっさりダメだしされたり、逆に必要だと思っていた API が実は全然いらなかったり。 実際のユースケースを元にした苦情だけに説得力がある。

ブラウザのダメさを回避するのではなくブラウザを直す。仕様も直す。 ここに従来のフレームワークと Polymer の違いを見ることができる。

RDocの脆弱性情報に見るjQueryの安全な使い方

0-9:

RDocの脆弱性情報

2013-02-06に以下の脆弱性情報が公開されました。

RDoc で生成した HTML ドキュメントにおける XSS 脆弱性 (CVE-2013-0256)

これはRDocの脆弱性情報ですが、実際にはdarkfish.jsというファイルの修正のみでありJSの問題であることがわかります。

問題のdarkfish.jsを確認すると該当の処理は「var anchor = window.location.hash.substring(1);から取得した値を$(“a[name=” + anchor + “]”);に渡した」処理であったことがわかります。
(このファイルが脆弱性情報のファイルと同じかは確認してないですが、ファイル名とコードから同一と判断しました)

修正方法としては$(“a[name=” + anchor + “]”)でのセレクター埋め込みをやめて$(“a[name]”).eachのeach内で要素と変数を比較するようにした($(this).attr(“name”) == anchor)なっています。

何が問題だったのか

外部から受け取った値(location.hash)を$(“a[name=” + anchor + “]”)に渡すことでXSSが可能になっています。

これは作者が$()で要素の選択のみを想定していたはずが、意図せずに要素の生成まで出来てしまうことが原因です。

この問題は「location.hashでページ内の要素をJSで指定する」場合の実装に多く存在しており、jQueryを使ったサイトで脆弱性がある場合高い頻度で報告されます。

jQueryにおけるXSSを引き起こしやすい問題について - 金利0無利息キャッシング – キャッシングできます - subtech

どう回避すればいいのか

RDocの脆弱性情報では変数をセレクターに埋め込むことをやめて変数比較にしていますが、jQueryを使う場合には以下のようなコードでも回避することが可能です。

  1. 要素の選択系APIを使う

    $(“a[name]”).filter(“[name=”+anchor+”]”)

$()は「要素の生成」と「要素の選択」両方の機能を持っているため「意図しない要素の生成」が発生しますが、.filterや.findは「要素の選択」の機能しか持っていないため「意図しない要素の生成」が発生しません。
(ただし、極端にブラウザのリソースを奪うことはできる可能性があるので、それが問題になる場合は次の回避策を使ってください)

  1. functionを使って要素を選択する

    $(“a[name]”).filter(function () { return $(this).attr(“name”) === anchor })

.filterは引数にfunctionを受け取り、その中でtrueを返した要素を選択する機能があるため、この機能を使うことで意図しない要素の生成が発生しません。

  1. $()に渡す内容を制限する

    $(“a[name=” + anchor.replace(/\W/g, ”) + “]”)

anchorの内容を[a-zA-Z0-9_]に制限することで意図しない要素の生成を回避出来ます。
(ただし、RDocのname属性が全て\wで記述されているかは確認しています)

そもそもの問題点

そもそもの問題点として、コード内で文字列を組み立てて外部のシステムに渡す構成自体が安全ではありません。

  • SQLインジェクション(SQL文字列に変数を埋め込む場合に多く発生)
  • コマンドインジェクション(コマンドライン文字列に変数を埋め込む場合に多く発生)
  • XSS(html文字列に変数を埋め込む場合に多く発生)

システム的に文字列で値をやり取りすること自体はやむを得ない場合もありますが、こういったコードを書く場合は常にインジェクション系の問題が発生しないか注意してコードを書く必要があります。

類似問題

今回の脆弱性情報とか無関係ですが、同じようにlocation.hash経由でよく指定される内容として「サーバサイドのファイル名」があります。

これは以下の様なコードで、やはり脆弱性があります。

$.get(location.hash.substring(1), function (html) {
    $('body').html(html);
});

古い(XHR level2をサポートしていない)ブラウザであれば、上記のコードで取得できるのは同じドメイン上のファイルのみとなるため、同じドメイン上に問題のあるファイルが存在しない場合安全ですが、XHR level2をサポートしているブラウザであれば上記コードでは外部サーバのデータを取得することが可能なため危険なコードとなります。

この問題はlocation.hashを「ファイルパスでしか使用できない文字列に制限する」ことで回避可能ではありますが、ChromeやIEはロングIPがサポートされていることと、スキーマの省略をできるので文字列制限だけでは回避が難しい問題があります。

// XMLHttpRequest cannot load http://192.168.0.1/.
$.get('//3232235521', function (html) {
    $('body').html(html);
});

IPアドレス - Wikipedia
The Sexy Assassinで紹介されてるCSS HTML Attribute Readerがどこまで危険か検証してみた

まず、外部から任意のファイルを指定してのアクセスできる構成はできるだけ避けるほうが無難ですが、もしそういう構成をとらざるをえない場合以下の点に注意してください。

  • アクセスできるディレクトリを指定する
    アクセスできるディレクトリを「/html/」等の文字列を追加することでschemeを省略したURLや同じドメイン上の想定していないディレクトリへのアクセスを回避出来ます。また、アクセスできるディレクトリ以下には実際に使用するhtml以外のファイルは存在しないようにしましょう(ユーザがファイルをアップできないように)。
  • .replace(/.+/g, ‘.’)を行う 「../」と言った方法で指定ディレクトリ外へアクセスされることを制限します。これに関しては単純に.replace(/../g, ”)といったコードでは「../」で回避できてしまうことに注意してください。

この問題は古いjQuery Mobileでも存在した問題で、元々安全に実装するのが難しい構成です。

可能であればファイル名を\wに制限し、以下の様な実装をおすすめしますが、この構成でもサーバ上の実装によっては危険な状況になる場合もあるので注意してください。

$.get('/html/'+(location.hash.replace(/\W/g, ''))+'.html', function (html) {
    $('body').html(html);
});

X-Content-Type-Options: nosniff の効果

swdyh:

Heads up: nosniff header support coming to Chrome and Firefox https://github.com/blog/1482-heads-up-nosniff-header-support-coming-to-chrome-and-firefox

ChromeとFirefoxでnosniffってどういうことなんだろうと思って少し調べた。

IE8から、X-Content-Type-Options: nosniff があった場合は、ファイルの中身を自動判別する機能が無効になる。htmlじゃないものが自動判別でhtmlだと誤判別されて表示されることで起こるXSSを防ぐことができる。

Internet Explorer 8 のセキュリティ Part VI: Beta 2 の更新項目 http://msdn.microsoft.com/ja-jp/ie/dd218497.aspx

IE9から、X-Content-Type-Options: nosniff があった場合は、scriptが参照する応答でContent-Typeが以下の場合でない場合に読み込まない。

application/ecmascript
application/javascript
application/x-javascript
text/ecmascript
text/javascript
text/jscript
text/x-javascript
text/vbs
text/vbscript

スタイルシートはtext/cssでない場合に読み込まない。

MIME 処理の変更: X-Content-Type-Options: nosniff http://msdn.microsoft.com/ja-jp/library/ie/gg622941%28v=vs.85%29.aspx

ChromeとFirefoxのnosniffサポートという話は、IE9から加わった効果のことだった。GithubやGistのrawはtext/plainでnoniffをつけるから、Githubのアドレスを直接参照するスクリプトやスタイルシートは、ブラウザによっては動かなくなるよという話。

手元のChrome(28.0.1500.6 dev)だとjsはブロックするけど、cssはブロックしなかった。Firefox(Firefox 21 beta)はまだどちらもブロックしなかった。

GithubやGistのjsやらcssを直接参照するのは、ブラウザ次第で動かなくなるし、そもそもGithubの負荷になって迷惑になるのでやめましょう。

Chrome APIに関するメモ

0-9:

chrome.experimental.record - Google Chrome

名前からSelenium的な「ユーザの動作を記録して再生する」APIかと思ったが、「別プロセスでChromeを起動して動作記録を取る」APIのよう。

Windows、Mac、Stable、Dev共に動作しなかったので詳細不明(別プロセスのChromeの起動に失敗してるっぽい)

chrome.debugger - Google Chrome

DevToolsの内容を外部から操作できるAPIだが、「DevToolsを起動中はAPI経由での接続ができない」という制限があるためあまり実用的ではない。
(remove debugger用の通信プロトコルを叩けるようにしたAPIのようなので、元々1ページに1接続で十分な想定だったんだろう)

ドキュメントには今後DevToolsを起動中でもAPI経由で接続できるようになるような記述があるので、その点が修正されれば色々と面白いことが出来そう。
(SourceのLiveEditも触れるようになっているっぽい)

chrome.devtools.panels - Google Chrome

DevToolsの既存のパネル上に要素を配置できるAPI。

ただし、このAPIが呼ばれるコード内からは、上記chrome.debugger APIにアクセス出来ないのであまり実用性は高くない。

chrome.socket - Google Chrome

Windows 7環境ではsocket.accept周りがおかしい気がする。
(何回か接続、切断を繰り返すとacceptがcallbackされなくなる。acceptを取りこぼしてる感じ。Macでは正常。Stable, Dev, Canaryで再現)
まだ、socket.acceptはexperimentalなので正常版では直るのかな?

chrome.socket.connectでDNSの名前引きに失敗した場合、callbackに-105が渡される。-3が渡されることもあるけど、こちらは何かわからない。

disconnect、destroyは両方呼び出さないとちゃんと切断されなかったので両方呼び出しているが、socketの使い回しとかするのであればちゃんと呼び分けたほうがいいのかもしれない。

chrome.socket.listenは同じポートで複数回呼び出すとcallbackに0以外を渡すので確認する。

chrome.socket.acceptはcallback内でエラー処理が終わったら、即同期的に再度chrome.socket.acceptを呼び出す。
callbackを待たずに再度chrome.socket.acceptを読んだ場合は-2が返る。
(-2はエラー処理ではなく無視していいと思う)
-2と0以外の値でcallbackされた場合、エラーとして処理する。

chrome.socket.setNoDelayはあってもなくても動作は変わらない?Proxy作成時にブラウザと通信するsocketには有効にしてみた。
(特に変わった感じはなかった)

chrome.socket.readはまずenv.data.byteLengthを見てデータが読めたかどうか確認する。それ以上データが有るかどうかは読み込んだデータ内容を見て判断する。
サーバがデータを送らないのにchrome.socket.readするとcallbackが呼ばれずに延々待たされることになるので注意(当然だけど)

chrome.socket.listenの第4引数(backlog)は「クライアントが接続してきた場合、backlog数分だけ待たせておく(それ以上はエラーにする)」数。ただ、現状有効なのか若干疑問(動いてないような?。特にWindows環境)

昔々、ウェブプログラマによく知られた JavaScript のメモリリークパターンがあった。 それは JavaScript と C++ をまたいだ循環参照を作るというもの。 典型的にはイベントハンドラの関数がクロージャをつくるときに起きた。

var target = document.getElementById(“t”);
target. { // This closure refers |target|.
target.innerHTML = “I’m leaked!”;
};

(中略)

このとき、素朴な実装だと JavaScript の GC は C++ 側の参照構造を知らず、 C++ は JavaScript 側の参照構造を知らない。 いくつかの古いブラウザでは、この循環参照がメモリリークにつながった。 もっとも今は昔。最近のブラウザにこの問題はない。みなそれぞれに直っている。

WebKit/V8 の場合、一部の参照を弱参照にすることで循環を絶ち、問題を回避している。 具体的には C++ のイベントハンドラ(=C++ オブジェクト)から 対応する JavaScript のイベントハンドラ(=関数)への参照が、弱参照としてマークされている。