» Mozilla Hacks ブログ翻訳

Firefox 4 Beta 2 リリース – CSS 3 トランジションに対応

原文: Firefox 4 Beta 2 is here – Welcome CSS3 transitions (2010/07/27 公開)

以前お伝えしたように、Firefox 4 ではベータ版の更新が従来より頻繁に行われるようになりました。その結果、Beta 1 の公開からわずか 3 週間で Beta 2 が公開されました。

Beta 1 には既に多くの新機能が含まれていました (Beta 1 の機能一覧)。今回の新しいベータ版には、どのような Web 開発者向け新機能があるのでしょうか?

パフォーマンスと CSS3 トランジション

Beta 2 で追加された主な Web 開発者向け機能は、パフォーマンスの向上CSS3 トランスフォーム内の CSS3 トランジションの 2 つです。

上の動画は YouTube でホストされています。HTML5 の video タグが有効な場合は、それが使用されます (詳細はこちらをご覧ください)。YouTube 動画は こちら でご覧いただけます。

パフォーマンス: この新しいベータ版では、新しいページ構築メカニズムとして Retained Layers (留保レイヤー) が導入されています。このメカニズムが有効になっていると、動的コンテンツが含まれる Web ページの表示速度が大幅に向上し、スクロールも相当スムーズになります。また、GPU を使用して Web ページの一部のレンダリングと構築を行うハードウェアアクセラレーションも引き続き実装を進めています。

CSS3 トランスフォーム内トランジション: Web 開発者にとって最も大きな変更は、おそらく CSS3 トランスフォーム内の CSS3 トランジションでしょう。

CSS3 トランジションを使用すると、CSS プロパティの変更をすぐに適用する代わりに、アニメーションできるようになります。詳細については こちらのドキュメント をご覧ください。

この機能は Beta 1 で既に使用可能でしたが、Beta 2 ではトランスフォームの中でトランジションを使用できます。

CSS3 トランスフォームでは、あらゆる HTML 要素に対してトランスフォーム (拡大縮小、移動、歪み) を定義できます。また、トランジションを使用してこれらのトランスフォームをアニメーションできます。

このボックスが見えますか? マウスをこのボックスの上に乗せると、その位置 transform: rotate(5deg); がスムーズなアニメーションで transform: rotate(350deg) scale(1.4) rotate(-30deg); のようにトランスフォームします。
#victim {
  background-color: yellow;
  color: black;
 
  transition-duration: 1s;
  transform: rotate(10deg);
 
  /* Prefixes */
 
  -moz-transition-duration: 1s;
  -moz-transform: rotate(5deg);
 
  -webkit-transition-duration: 1s;
  -webkit-transform: rotate(10deg);
 
  -o-transition-duration: 1s;
  -o-transform: rotate(10deg);
}
#victim:hover {
  background-color: red;
  color: white;
 
  transform: rotate(350deg) scale(1.4) rotate(-30deg);
 
  /* Prefixes */
 
  -moz-transform: rotate(350deg) scale(1.4) rotate(-30deg);
  -webkit-transform: rotate(350deg) scale(1.4) rotate(-30deg);
  -o-transform: rotate(350deg) scale(1.4) rotate(-30deg);
}

CSS3 トランジションには、WebKit ベースのブラウザ (Safari および Chrome)、Opera、そして現在では Firefox が対応しています。対応していないブラウザでも表示には影響ありません (アニメーションはしませんが、スタイルは適用されます)。つまり、今すぐ使い始めることが可能なのです。

デモ

トランスフォーム中の CSS3 トランジションと、ハードウェアアクセラレーションをお見せする 2 つのデモを作成しました (スクリーンキャストについては、上の動画をご覧ください)。

A warm HTML5 page このデモには 5 つの動画があります。動画は、サムネイル内では白黒表示 (SVG フィルタを使用)、実サイズになると (クリックされると) カラー表示になります。CSS トランジションにより「渦巻き」効果が適用されます。動画の上にマウスを乗せると、クエスチョンマーク (?) のボタンが現れます。それをクリックすると動画の詳細が表示され、別の SVG フィルタ (feGaussianBlur) が適用されます。

London Project このページには 2 つの動画があります。左上の動画は SVG コントロール付きの円形の動画 (SVG クリップパスを使用) です。メインの動画はクリックできます (動画が拡大されます)。動画に重なっている文字もクリックでき、クリックすると、CSS トランジションを使用して動画の裏側に移動できます。

CSS makes U sick このページは、画像、videocanvas 要素のシンプルな一覧です。それらをクリックすると、トランジションとともに CSS トランスフォームがページ自体に適用されます。白い要素はクリックできます (動画を再生するか、WebGL オブジェクトを表示します)。ハードウェアアクセラレーションと WebGL に対応したブラウザを使って見ることお勧めします。Windows で Firefox をお使いの場合は、Direct2D を有効にする必要があります

クレジット

Creative Commons の動画

マルチカラー・クラウド効果 (MIT ライセンス)

Firefox 4 Beta 1 リリース – Web 開発者注目の新機能を紹介

原文: Firefox 4 beta 1 is here – what’s in it for web developers? (2010/07/01 公開)

Mozilla は本日 [2010/07/07]、Firefox 4 の初めてのベータ版を公開 し、Firefox 4 の最終版に向けて大きな一歩を踏み出しました。今回のベータ版は、これまでの他のリリースとは異なる扱いをすることにしました。従来のベータ版はマイルストーン的なリリースでしたが、今回は、ベータプログラム期間中、より頻繁にアップデートを提供する予定です。このため、ベータ版をダウンロードして使い始めたテスターには、数か月といった長い間隔ではなく、2 週間から 3 週間ごとにアップデートが届きます。これにより、皆さんからのフィードバックにすばやく応えるとともに、修正点や変更箇所をより早期にテストしてもらえると Mozilla では考えています。そしてその結果、非常に品質の高い製品をリリースすることができるはずです。

初めに、フィードバックについて説明したいと思います。今回のベータ版には 2 通りのフィードバック提供方法があります。

Feedback ボタン – 上のスクリーンショットに見えているのは、ベータ版に含まれている「Feedback」と呼ばれるアドオンです。これは、ブラウザウィンドウの右上に大きな Feedback ボタンを追加し、テスターが気に入った、もしくは気に入らない機能について、すばやく簡単にフィードバックできるようにするものです。私たちはベータ期間中にここから送信されたフィードバックに目を通しますので、ぜひコメントを残してください。このアドオンには、よく使用されるメニュー項目パスワードの使用状況 など、テスターがどのように Firefox を活用しているかを調査する Test Pilot も統合されています。開発チームでは、このベータ期間を通じて、優れたブラウザを作り上げるために必要な、プラットフォームパフォーマンスなどの興味深いデータを測定するためにも Test Pilot を使用する予定です。通常の Test Pilot と同様に、テスターが知らないうちにデータが収集されるようなことはありません。収集されたデータがお使いのコンピュータから Mozilla へ送信される際には、必ず確認が行われます。そしてそれらのデータは非常に厳格な プライバシーポリシー に従って扱われます。

もしあなたが Web 開発者なら、このベータ期間は特に役立つことでしょう。Firefox 4 Beta 1 には、以下で解説するような、Firefox 3.6 にはなかった数多くの新機能が含まれています。このベータ期間を通じて機能の追加や修正を行っていくため、あなたのフィードバックは大変重要です。ぜひ時間を取ってベータ版をダウンロードして試してみてください。可能であれば常用して、継続的な使用によって何か変わることがあるかを確認してください。

パフォーマンス

Firefox 4 には、Firefox 3.6 以降に行われた数多くのパフォーマンスの向上の成果が含まれています。あなたは Web 開発者として、全体的なパフォーマンスの大幅な向上に気付くのではないでしょうか。

DOM とスタイリングのパフォーマンス向上 – DOM とスタイル解決のエンジンに大規模な改良が行われ、複雑な CSS ルールやセレクタマッチングを使用しているページが、一般的により高速かつ適切に表示されるようになりました。(Zimbra パフォーマンステストスイートの一部テストでは、2 倍程度の堅実なパフォーマンス向上が確認できています)

ページ読み込み処理中の I/O 削減 – Firefox 3.6 以降目覚ましい改良が行われている大きな分野のひとつが、メインの UI スレッドから多くの I/O を削減すること です。これは例えば、ブラウザの履歴に基づいたリンクの色付けを行う際、履歴の参照を別スレッドで行うようにして、メインスレッド上で HTTP キャッシュへの同期的なデータの書き込みを行わないようにするといったことが挙げられます。たったこれだけでも、他のどのような対策よりも、ブラウザの全体的な体感速度を向上させることができたのです。

JavaScript – Beta 1 には新しい JägerMonkey の開発成果は含まれていませんが、JavaScript エンジンにもまた大幅な高速化が行われました。JägerMonkey の開発はかなり進んでおり、ベータ期間中に反映されていきますが、既に 良い結果が出ています

レイヤーを通じたハードウェアアクセラレーション – 今回のベータ版では、ハードウェアアクセラレーションへの優秀な対応が行われました。例えば、HTML5 ビデオを見ているときに全画面表示に切り換えると、Mac と Linux では OpenGL を、Windows では DirectX 9 を使用することで、ビデオの描画が加速します。(Gecko レイヤー の開発作業を拡大しながら、このアクセラレーションを必要に応じてページ内コンテンツにも適用していく予定です。)

D2D を通じたハードウェアアクセラレーション – Windows 7 もしくはサービスパックが導入された Windows Vista では、D2D が有効になったレンダリングに完全対応 しています。これはあらゆる種類のレンダリングに相当のパフォーマンス向上をもたらす可能性を秘めており、IE の開発チームも IE9 に向けて取り組んでいるようです。これは今回のベータ版では初期設定で有効になっていませんが、簡単に 有効にして 試してみることができます。D2D 対応に関して私たちがこれまでに見てきた最高のデモは、実のところ IE Flying ImagesIE Flickr Explorer です。Firefox は実際、ほとんどの場合 IE9 のプレビュー版よりも、これらのデモをうまく実行することができます。

プラグインのプロセス分離を Mac 版にも実装 – プラグインのプロセス分離は、数週間前に 3.6 の Windows 版と Linux 版には実装されましたが、今回 Mac 版にも実装されました。プラグインのプロセスを Firefox 本体と分離することで、安定性や応答性を向上させるとともに、メモリ使用量を削減できます。Mac OS X では、10.6 Snow Leopard で動作する Flash Player 10.1 のプロセスを分離させる対応が行われています。(10.6 のみ対応しており、Firefox と個別プラグインの両方についてイベントモデルに対する変更が必要となります。)

HTML5 対応

Firefox は 早くから HTML5 への優れた対応 を行っており、今回のベータ版はそれをさらに拡大していきます。

HTML5 フォーム – 多くの HTML5 フォーム機能 への対応が製品へ反映され始めました。かなり高い 実装基準 が掲げられていますが、ベータ期間に合わせて、さらに多くのフォーム機能が追加される予定です。

HTML5 セクション<article> <section> <nav> <aside> <hgroup> <header> <footer> といった HTML5 セクションに対応しました。

WebSockets – 今回のリリースには、仕様のバージョン -76 に基づく WebSockets への対応が含まれています。

HTML5 履歴pushStatereplaceState といった、新しい HTML5 の履歴項目にも対応しました。これらは Web アプリケーションの構築を容易にする非常に重要な機能であり、サイト間を移動する際のプライバシーを向上させられるという点でも非常に重要です。

HTML5 パーサ – Firefox 4 は、HTML5 仕様の最重要部分を占める HTML5 パースアルゴリズムに完全に対応した初めてのブラウザです。このパーサのおかげで、例えば SVG や MathML を HTML コンテンツへ直接埋め込む ことが可能となりますが、それと同時に、マークアップが間違っていたとしても、別々のブラウザが同じ挙動が示すことを Web 開発者に保証するものとなります。これは HTML5 仕様の中で最大の相互運用性に関する部分に含まれ、開発者に多大な恩恵をもたらすことから、他のブラウザもこの取り組みに追従してくれることを Mozilla では期待しています。

そしてもちろん、Firefox 4 は、Canvas (D2D ハードウェアアクセラレーションを含む)、ビデオ、その他多くの HTML5 技術に対応しています。

HTML5 ビデオ

WebM 対応 – この分野におけるこれまでで最大の変更点は、WebM 形式 への対応です。HTML5 対応 YouTube のベータ版 に登録すると、WebM 形式の動画が美しくスムーズに再生されるはずです。

その他の今後実装予定のインタフェース – ベータ期間を通じて、JavaScript による動画の全画面表示 API や buffered 属性への対応の追加、autobuffer 属性の preload への改称といった作業が行われます。

ストレージと ファイル API

IndexedDB – Firefox 4 Beta 1 には、新しい IndexedDB ストレージ標準 に関する非常に初期の開発成果も含まれています。仕様がまだ確定しておらず流動的であることから、オブジェクトはプライベート名前空間を付けた window.moz_indexedDB となっています。これは非常に複雑な仕様なので、追って詳しいブログ記事を投稿します。

ファイル API の URI 対応 – ファイル API 内部における URI 対応の初期実装が行われています。これは、ファイル全体をメモリに読み込むことなく、画像や動画など大量のデータをファイル API で処理できるようになったということです。また、<image><video> 要素で、プライベートなファイル API URL を参照して、プレビューや操作を行うこともできます。

FormData – ファイル API やその他のソースから複雑なデータを非常に簡単にサーバへ送信できるようにする FormData メソッドにも対応しました。

アニメーションとグラフィックス

SMIL – SVG アニメーション (SMIL) に対応しました。ベータ版をお使いの方は、David Dailey が作成したこのページにある美しいサンプルの数々 をぜひ見てみてください。

あらゆるところで SVG を – ベータ期間の後半で、通常の画像や CSS 背景画像として SVG を使用できるようにする予定です。開発作業の大半は完了していますが、まだ反映はされていません。

CSS トランジション – 今回のベータ版には CSS トランジション のほぼ完全な実装が含まれており、-moz 接頭辞の付いたプライベート名前空間で使用できます。大きな作業でまだ残っているのは、変形やグラデーションのアニメーションだけです。(グラデーションについてはワーキンググループからのフィードバックを待っている段階で、トランジション関連のソースコードそのものはレビューが進められています。)

WebGL – 今回のベータ版では、初期設定でまだ有効になっていませんが、WebGL 対応の強化が行われています。(Vlad の以前のブログ記事 に有効にする方法が書かれています。) WebGL の仕様はバージョン 1.0 の公開に向けて策定中であり、Chrome、Safari そして Firefox で実装が進められています。Mozilla では Firefox 4 にこの機能を含めたいと考えていますが、最終決定は仕様の安定性やグラフィックスドライバの対応状況に左右されるでしょう。WebGL は Mac では非常に快適に動作するはずです。ATI や NVIDIA 製のドライバが搭載された Windows パソコンでも快適に動作します。しかし、Intel 製ドライバ搭載のパソコンでは、Intel によるドライバ対応が良くないために問題が見られるでしょう。(この記事の筆者もそうです) また Linux では、ドライバごとの対応に大きな差があるため、より複雑な状況です。NVIDIA 製ドライバ搭載のパソコンでは動作しますが、他のドライバではうまく動かない場合があります。それでも、Linux での多くの問題を修正するための取り組みは続けられています。

CSS

リサイズ可能な textarea 要素 – テキストエリアが初期設定でリサイズ可能になりました。-moz-resize プロパティを使えば初期設定を変更することができます。

新しい -moz-any セレクタ-moz-any は、巨大で複雑なセレクタを非常に小さなものに置き換えられるようにする強力なセレクタです。サンプルは こちらの記事 をご覧ください。

新しい CSS3 calc() – 今回のベータ版には、新しい CSS3 calc() 値の対応が含まれています。これは、割合と絶対値の組み合わせを含むサイズ指定を可能にするもので、開発者から高い評価を受けています。サンプルは CSS3 calc() に関する記事 をご覧ください。

背景画像の部分選択 – 新しい -moz-image-rect セレクタを使用して、背景画像の一部だけを選択して表示させることが可能になりました。

-moz-background-size 対応の削除-moz-background-size プロパティは、最終的な background-size という名前に改称されました。今後 -moz-background-size は使用できません。

DOM とイベント

入力イベントにおけるタッチ操作の検出 – 入力イベントがマウス操作によるものかタッチ操作によるものかを event.mozInputSource で調べられるようになりました。

範囲の境界長方形の取得 – Range オブジェクトに getClientRects()getBoundingClientRect() メソッドが追加されました。

任意の要素上のマウスイベントの捕捉 – Internet Explorer 由来の setCapture()releaseCapture() API への対応が追加されました。

document.onreadystatechange への対応document.onreadystatechange に対応しました。

セキュリティ

コンテンツセキュリティポリシー – 今回のベータ版には コンテンツセキュリティポリシー (CSP) への対応が含まれています。CSP を使えば、ブラウザがコンテンツを読み込む際に許容されることを、サイト管理者が制御できます。CSP は、クロスサイトスクリプティング (XSS) やクロスサイトリクエストフォージェリ (XSRF) 攻撃のリスクを緩和するために作成された仕様です。自動報告機能もあり、他のブラウザに影響を及ぼすおそれのある問題の報告をサイト管理者が受け取ることができます。

最後に

以上が Firefox 4 Beta 1 の概要です。ベータ期間中、さらにいくつかの機能が追加される予定ですが、実際に実装されたらこのブログ [Mozilla Hacks] でお知らせします。それらの機能の一部については、より掘り下げた詳しい情報を提供します。当然のことながら、ベータ期間を通じてパフォーマンス向上作業も継続します。ぜひあなたもベータ版をテストして、コメントがあればここ [原文記事] に投稿するか、組み込みのフィードバック機能で報告してください。

それでは、新機能満載のベータ版をお楽しみください!

Firefox 4 の Indexed Database API を先取り紹介

訳注: 本文において IndexedDB と書かれている技術仕様の正式名称は Indexed Database API です。名前にスペースを含めることが議論により決定しています。

localStorage では単純なクライアントサイドのキーと値のペアを保存することができますが、これだけではまだウェブアプリケーションのための構造的でインデックスされたデータストレージの需要を叶えるものではありません。Mozilla では構造的ストレージとインデックスのための API である IndexedDB をサポートし、数週間以内にテストビルドをリリースする予定です。IndexedDB は、WebDatabase API という、SQLite のサブセット言語を用いる、いくつかのブラウザに実装されている API と比較することができます。Mozilla はこちらのポストに書かれているいくつかの理由により WebDatabase をサポートしないことを決定しています。

訳注: この経緯は「ブラウザ上のデータベースに関して」という記事に詳しいです。

IndexedDB と WebDatabase を比較するために、これらの仕様の非同期 API をほぼ網羅する4つの例を紹介します。これを読むとテーブルのある SQL ストレージ (WebDatabase) とインデックス付き JavaScript オブジェクトストレージ (IndexedDB) の違いがとてもよく分かるでしょう。同期バージョンの API は Worker スレッドからしか使うことができません。Worker スレッドはまだ全てのブラウザでサポートされているわけではないため、ここでは同期 API のことは話しません。IndexedDB のコードは、Mozilla が W3C WebApps ワーキンググループ (WG) に提出し、今のところ良いフィードバックを貰えている提案をベースとしています。両 API のコードは簡単のためにエラー処理などはしていませんが、もちろんみなさんが実用で使うときは忘れないようにしましょう。

訳注: Mozilla の提出した API 改正案はまだ2010年6月1日現在の Indexed Database API 仕様草案には反映されていませんが、Google Chrome チームの数人からの同意もあり、ほぼそのまま採用されると思われます。

キャンディー屋さんとお客さん (kids ということにします) の例を考えてみましょう。candySales という欄は、一人のお客さんへのあるキャンディーの売り上げを表しています。

例 1 – データベースを開いてセットアップする

最初の例は、データベースを開く方法を示します。データベースを開くときにバージョンをチェックし、必要なテーブルやオブジェクトストアを作り、正しい バージョン番号をセットします。WebDatabase はバージョンを厳しく処理し、開こうとしているデータベースのバージョンと違うものだった場合はエラーを出します。IndexedDB は単に呼び出す人がバージョン管理できるようにするだけです。バージョン管理に関してはまだ WG でも議論中なので注意してください。

WebDatabase

var db = window.openDatabase("CandyDB", "",
                             "My candy store database",
                             1024);
if (db.version != "1") {
  db.changeVersion(db.version, "1", function(tx) {
    // はじめてのユーザー。データベースを初期化。
    var tables = [
      { name: "kids", columns: ["id INTEGER PRIMARY KEY",
                                "name TEXT"]},
      { name: "candy", columns: ["id INTEGER PRIMARY KEY",
                                 "name TEXT"]},
      { name: "candySales", columns: ["kidId INTEGER",
                                      "candyId INTEGER",
                                      "date TEXT"]}
    ];
    for (var index = 0; index < tables.length; index++) {
      var table = tables[index];
      tx.executeSql("CREATE TABLE " + table.name + "(" +
                    table.columns.join(", ") + ");");
    }
  }, null, function() { loadData(db); });
}
else {
  // はじめてのユーザーではない。初期化しなくていい。
  loadData(db);
}

IndexedDB

var request = window.indexedDB.open("CandyDB",
                                    "My candy store database");
request.onsuccess = function(event) {
  var db = event.result;
  if (db.version != "1") {
    // はじめてのユーザー。データベースを初期化。
    var createdObjectStoreCount = 0;
    var objectStores = [
      { name: "kids", keyPath: "id", autoIncrement: true },
      { name: "candy", keyPath: "id", autoIncrement: true },
      { name: "candySales", keyPath: "", autoIncrement: true }
    ];

    function objectStoreCreated(event) {
      if (++createdObjectStoreCount == objectStores.length) {
        db.setVersion("1").onsuccess = function(event) {
          loadData(db);
        };
      }
    }

    for (var index = 0; index < objectStores.length; index++) {
      var params = objectStores[index];
      request = db.createObjectStore(params.name, params.keyPath,
                                     params.autoIncrement);
      request.onsuccess = objectStoreCreated;
    }
  }
  else {
    // はじめてのユーザーではない。初期化しなくていい。
    loadData(db);
  }
};

例 2 – お客さんをデータベースに保存する

この例では何人かのお客さんをテーブルやオブジェクトストアに保存します。また、WebDatabase では SQL injection のリスクを処理しなければいけないことを示します。WebDatabase では明示的にトランザクションを使わなければいけませんが、IndexedDB ではトランザクションは、たった一つのオブジェクトストアがアクセスされた場合に自動的に作られます。IndexedDB ではトランザクションのロックはオブジェクトストア毎です。さらに、IndexedDB では JavaScript のオブジェクトを挿入できますが、WebDatabase では特別にコラムを作らなければいけません。どちらの場合もコールバックで挿入 ID を得ることができます。

WebDatabase

var kids = [
  { name: "Anna" },
  { name: "Betty" },
  { name: "Christine" }
];

var db = window.openDatabase("CandyDB", "1",
                             "My candy store database",
                             1024);
db.transaction(function(tx) {
  for (var index = 0; index < kids.length; index++) {
    var kid = kids[index];
    tx.executeSql("INSERT INTO kids (name) VALUES (:name);", [kid],
                  function(tx, results) {
      document.getElementById("display").textContent =
          "Saved record for " + kid.name +
          " with id " + results.insertId;
    });
  }
});

IndexedDB

var kids = [
  { name: "Anna" },
  { name: "Betty" },
  { name: "Christine" }
];

var request = window.indexedDB.open("CandyDB",
                                    "My candy store database");
request.onsuccess = function(event) {
  var objectStore = event.result.objectStore("kids");
  for (var index = 0; index < kids.length; index++) {
    var kid = kids[index];
    objectStore.add(kid).onsuccess = function(event) {
      document.getElementById("display").textContent =
        "Saved record for " + kid.name + " with id " + event.result;
    };
  }
};

例 3 – お客さんの一覧を表示する

この例では kids テーブルと kids オブジェクトストアに保存されたお客さんを表示します。WebDatabase は全部の列を取得した後でコールバックメソッドに result set オブジェクトを渡します。一方、IndexedDB は結果を取得するごとに cursor handler を渡すので、結果が速く返ってくることになります。この例では示されていませんが、cursor.continue() を呼ばないことで繰り返しを止めることができます。

WebDatabase

var db = window.openDatabase("CandyDB", "1",
                             "My candy store database",
                             1024);
db.readTransaction(function(tx) {
  // テーブル全体を検索
  tx.executeSql("SELECT * FROM kids", function(tx, results) {
    var rows = results.rows;
    for (var index = 0; index < rows.length; index++) {
      var item = rows.item(index);
      var element = document.createElement("div");
      element.textContent = item.name;
      document.getElementById("kidList").appendChild(element);
    }
  });
});

IndexedDB

var request = window.indexedDB.open("CandyDB",
                                    "My candy store database");
request.onsuccess = function(event) {
  // オブジェクトストア全体をまわる
  request = event.result.objectStore("kids").openCursor();
  request.onsuccess = function(event) {
    var cursor = event.result;
    // cursor が null なら終了
    if (!cursor) {
      return;
    }
    var element = document.createElement("div");
    element.textContent = cursor.value.name;
    document.getElementById("kidList").appendChild(element);
    cursor.continue();
  };
};

例 4 – キャンディーを買ったお客さんを列挙する

この例ではキャンディーを買ったお客さんと、どれだけのキャンディーを買ったのかを表示します。WebDatabase では単に LEFT JOIN したクエリを使えば簡単にできます。IndexedDB は今のところ別々のオブジェクトストアをまたいだ JOIN をする API がありません。そのため、この例では kids オブジェクトへの cursor と candySales オブジェクトストアの kidId インデックスへのオブジェクト cursor を開き、手動で JOIN をしています。

WebDatabase

var db = window.openDatabase("CandyDB", "1",
                             "My candy store database",
                             1024);
db.readTransaction(function(tx) {
  tx.executeSql("SELECT name, COUNT(candySales.kidId) " +
                "FROM kids " +
                "LEFT JOIN candySales " +
                "ON kids.id = candySales.kidId " +
                "GROUP BY kids.id;",
                function(tx, results) {
    var display = document.getElementById("purchaseList");
    var rows = results.rows;
    for (var index = 0; index < rows.length; index++) {
      var item = rows.item(index);
      display.textContent += ", " + item.name + "bought " +
                             item.count + "pieces";
    }
  });
});

IndexedDB

candyEaters = [];
function displayCandyEaters(event) {
  var display = document.getElementById("purchaseList");
  for (var i in candyEaters) {
    display.textContent += ", " + candyEaters[i].name + "bought " +
                           candyEaters[i].count + "pieces";
  }
};

var request = window.indexedDB.open("CandyDB",
                                    "My candy store database");
request.onsuccess = function(event) {
  var db = event.result;
  var transaction = db.transaction(["kids", "candySales"]);
  transaction.oncomplete = displayCandyEaters;

  var kidCursor;
  var saleCursor;
  var salesLoaded = false;
  var count;

  var kidsStore = transaction.objectStore("kids");
  kidsStore.openCursor().onsuccess = function(event) {
    kidCursor = event.result;
    count = 0;
    attemptWalk();
  }
  var salesStore = transaction.objectStore("candySales");
  var kidIndex = salesStore.index("kidId");
  kidIndex.openObjectCursor().onsuccess = function(event) {
    saleCursor = event.result;
    salesLoaded = true;
    attemptWalk();
  }
  function attemptWalk() {
    if (!kidCursor || !salesLoaded)
      return;

    if (saleCursor && kidCursor.value.id == saleCursor.kidId) {
      count++;
      saleCursor.continue();
    }
    else {
      candyEaters.push({ name: kidCursor.value.name, count: count });
      kidCursor.continue();
    }
  }
}

IndexedDB は基本的にデータベースのプログラミングモデルを簡単にし、幅広いユースケースに使えます。WG はこの API を、ライブラリでラップできるようにデザインしました。例えば CouchDB のようなスタイルの API を上に重ねたりする余地は十分にあります。WebDatabase のような SQL ベースの API を IndexedDB 上に作ることも十分に可能です。仕様がまだ凍結していないこともあり、Mozilla は IndexedDB へのフィードバックを熱心に集めています。遠慮なくコメントしたり Rypple で匿名投稿してください。

高速な JavaScript とオーディオ:ブラウザ上での音声合成

David Humphrey のファンでない限り、Firefox上でオーディオ操作を実現するという彼が成し遂げた仕事のことを、あなたは知らないかもしれない。
彼は多くのデモを投稿し、Firefox 上での JavaScript の進歩を促してきた(バイナリ配列、トレーシングベースの超高速なFFT解析など)
以下は、彼の投稿の中で、私が最も気に入っているものだ。

随分前から私が気に入っているデモは、この実験を始めて以来、ずっと私が待ち続けてきたものだった。以前、私はこう書いた。自分達が成し遂げた仕事が、多くのWebのアクセシビリティに関するトラブルを解決することになるだろう。
数週間前、私は irc で、JavaScript 上でテキストをスピーチエンジンに出力するような仕組みを、誰かが作ってみるべきだと言った。そして今、私たちは完成したコードを手にしている。Yury は黙って、flite エンジンベースのそれを開発してみせたのだ。
これを実行するときには、ぜひこのことを思い出してほしい。あなたが目にしているのは、いかなるプラグインも使わず、ブラウザだけで動いている処理だということを。これは全て JavaScript だけでできているのだ。

David Humphrey による Web Audio Data API (テキストスピーチのデモ)

Firefox における WebSockets

WebSockets の要点:低い複雑性、小さなレイテンシ、Web 開発者のためのとてもシンプルな API を持った双方向の通信方式。

WebSocket の特徴をもう少し詳しく説明した後、Firefox 上に実装するのかどうか、そしてそれはいつ頃になるのかについて話をしてみよう。

低い複雑性

HTTP のようなハンドシェイクから始まる WebSocket プロトコルは、テキストパケットを相互に送受信するための、比較的シンプルなモデルを持っている。プロトコルは極めて簡素だ。多重通信やバイナリデータはサポートせず、一度コネクションが確立すると、実際のデータ転送コストはとても低くなる。

ただし、多重通信やバイナリデータもサポートすべきと考える人たちもいる(彼らが正しいかもしれない)。それが複雑性を高めることは明白だが、それに見合うケースだってありうる。これについては後述する。

双方向通信

WebSocket の主な特徴に、シンプルな相互通信のサポートが挙げられる。
サーバはクライアントへの更新情報を、クライアントはサーバへの更新情報を、各々容易に送ることができる。
以前から開発されてきた Comet によるアプリケーションの多くはこのモデルにより、ずっとシンプルで高速になるだろう。プロトコルと API が直接にそれをサポートしているためだ。

相互通信を可能とする一方で、HTTP による same-origin モデルの制約は受ける。
つまり、ブラウザに対して任意のサイトの任意のポートに接続するような能力を、WebSocket が与えることはない。

要するに、WebSocket は HTTP のセキュリティモデルを備えた TCP といったところだ。

低いレイテンシ

実のところ、これが WebSocket 最大の利点だ。少量のデータを送るコストがとても小さいことが鍵だ。
現在でも Comet を用いれば相互通信が可能だが、そこではわずかなデータを送るために、大きなオーバーヘッドが必要となっていることも多い。

スケールの感覚を理解してもらうために、少々間接的な話をしてみよう。Google Wave では、キー入力にあわせたリアルタイム通信に挑戦している。そのため、キーストロークごとに数 KB のオーバーヘッドが発生している。原因は、TCP通信の開始(startup)、接続の裂け目(teardown)、たった数 byte であるべき時にも必ず含まれる HTTP メッセージヘッダが送信されるからだ。

私自身は挑戦したことはないが、こう推測している。もしあなたが Quake を HTTP Comet で実装すれば、その応答性は貧弱なものになるだろう。これこそが、WebSockets が本当に力を発揮する分野だ。

シンプルなAPI

開発者が WebSocket で用いる実際の API は比較的シンプルなものだ。メッセージを送信することができ、メッセージを取得することができる。ソケットがオープンしたとき、クローズしたとき、エラーが起きたときにイベントを取得する。JavaScript とバックエンドのライブラリにはまだ、今後機能が追加されるのは間違いないだろう。

(こう聞くと複雑な問題は後回しにしているようだが、実のところこれが、他のブラウザ関連の標準で目にしてきた成功への道なのだ。まずはみんなが試してみられる比較的単純なものを作る。そして何が遅いのか、何が進歩を妨げるのかを理解したら改良を繰り返していくのです。)

いつFirefox に実装されるのか

次期バージョンの Firefox で、ぜひとも WebSockets に対応したい。多くの人たちも、私たちがそうするのを望んでいる。

素晴らしい Wellington Fernando de Macedo (最も素晴らしい貢献者の一人)によって書かれた最初のテストパッチのセットは、2009年4月に最初にサブミットされた。それから、私たちはパッチをあてることと、変更された仕様への対応とを繰り返し続けている。

不運にも、仕様自身がまだ改訂中だ。
WebSockets は Chrome 4に搭載され、Chrome 5 にもそのまま変更なしに含められる予定だと Chrome 開発者に聞いている。
本当に不運なことに、Google が Chrome に採用したバージョンは、現在のドラフトを反映できていない。
WebSocket 接続をどのように開始するのかを決めるハンドシェイク方法が変更されている。これはサーバ上のセキュリティを大きく改良するためのものだ。

まだ多くの進行中の議論がある。圧縮機能の統合をどうするか、(バイナリを文字列にエンコードするのでなく)バイナリデータの直接サポートについて、多重通信をサポートすべきか否かについて、そして、その他の多くの課題について。

WebSocket はまだ広く使われておらず、Chrome の仕様追従速度も Firefox と大差ない。より新しい仕様のドラフトが通過したら、Chrome と Firefox が共に新しいバージョンの仕様を同時期にサポートするようになれば望ましいと考えている。

簡潔にまとめると:WebSocket の前途は素晴らしいものだから、私たちはそれに対応したい。しかし、それが十分に安定、安全なものなのか私たちは見定める必要がある。
コードが問題なのではない。私たちはそれを以前から持っている。数億人の人々に対してソフトウェアをリリースするために、プロトコルが「十分に完成されている」のか、コンセンサスがあるか否かが重要なのだ。

Account Manager プロジェクトに参加するには

Account Manager についての最 初に投稿された記事以来、数週間が経ち、私たちは多くのフィードバックを受け取った。人々により深くプロジェクトに関わってもらうための幾つかの 機会を提供できる。これは次のようなものだ。
Account Manager 会議か IIW に参加

私たちは Account Manager 会議を、5/21(金)に、Mozilla のMountain View Headquarters で開催する。この会議 は、最終決定に向けて準備を進めているド ラフト仕様に対して、あなたがフィードバックする素晴らしい機会になるだろう。もしあなたが Web 開発者、システム管理者、プロトコルやセキュリティの専門家なら、こちらか ら返信をお願いしたい。

会議は午後1時から4時まで、その後に懇親会。くだけた雰囲気とドリンクとスナックが用意される中で、他の Mozilla 開発者と会う機会になる。

私たちは次週の Internet Identity Workshop (IIW)に参加する予定だ。もしあなたが、Account Manager talk を覗きに IIW に参加するなら、こちらに来て、声をかけてほしい。

ブラウザ対応サイトの登録

他に協力してもらう方法としては、あなたのサイトに Account Manager による登録機能を追加することだ。

Account Manager の最新版のアドオンは、基本的な登録フローへのサポートを追加しているが、Web 開発者コミュニティがこの点をどう思うかについて、私たちは強い関心を持っている。あなたの必要としているのは、次の通り。

あなたの AMCD の中の username-password-form プロファイルに、少々のデータ(snippet)を追加する。

"register": {
    "method": "POST",
    "path": "/register-endpoint",
    "id-type": "email"
}

次に、ユーザIDとパスワードを POST パラメータで受け取るような登録エンドポイント(/register-endpoint)にメソッドを追加する必要がある。あなたのメソッドは、 ID とパスワードが OK ならばステータス 200を、さもなくば JSON の断片(詳細とサンプルは仕様を参照)とステータス 400を返す必要がある。

あなたは自身のコンテンツを新しいモデルを受け入れるように変更する必要がでてくるかもしれない。あなたのサイトがステータス 200を返した後、これは有効なユーザ名とパスワードのペアである と期待できる。しかしながら、この時点では無効なアカウントして登録する場合もある。追加情報が必要だったり、captcha を入力させたり、メール認証を求める必要があれば、それが確認されるまでアカウントは無効なままにする必要がある。

CSRF 対策への取り組み

コミュニティからのフィードバックをベースに私たちは幾つかの CSRF 攻撃防御の可能性を調査してきた。CSRF トークンサポートを追加することで、この最新の提案はヘッダに力を与え、同じ処理をより少ないリクエストでセッションクッキーなしに行うことを達成した。
興味を持たれたら、私達のフォー ラムで議論に参加してください。

オンラインでの参加

私たちのオンラインコミュニティに参加し、Account Manager 特集ページに 訪れ、メーリングリストやフォーラムに参加登録し、多くのことを学んでほしい。

もし、あなたがあなたのサイトを Account Manager に対応させるのであれば、そのサイトを、Account Manager サポート済みサイトとして wiki ページに追加してください。

Firefox、YouTube と WebM

今日発表された Mozilla の VP8 コーデック対応 に関する重要な点を 5 つ挙げておきます。

1. Google はオープンソースでロイヤリティフリーという条件で VP8 を公開します。VP8 は、Google が On2 の買収によって手に入れた高品質な動画コーデックです。VP8 コーデックは Theora よりもビットごとの品質において大幅な向上が見られ、H.264 と同程度の再生品質です。

2. VP8 コーデックは、Vorbis 音声コーデックと Matroska コンテナ形式のサブセットと組み合わされて、WebM と呼ばれる Web 上でのオープンビデオの新規格となります。このプロジェクトの詳細は、新たに開設された http://www.webmproject.org のサイトでチェックできます。

3. Mozilla では、Firefox に WebM 対応を追加します。今日から、Firefox 4 のプレアルファ版に WebM 対応を組み込んだ 初期段階のナイトリービルド をダウンロードできます。WebM は Google Chrome や Opera にも統合されます。

4. YouTube のすべての動画は WebM に変換されます。今日の時点でおよそ 120 万もの動画が WebM 形式で公開されており、過去の動画についても順次変換作業が行われます。

5. WebM は、Google やその他の企業だけでなく、多くのパートナーに支持されています。Brightcove などのコンテンツプロバイダーも、完全な HTML5 動画ソリューションの一部として WebM 対応を表明しています。ハードウェアベンダー、エンコーディングプロバイダー、その他動画関連企業がすべて WebM のパートナーに名を連ねています。Adobe でさえも Flash で WebM に対応します。ブラウザ市場におけるシェアと道義的なリーダーシップを持つ Firefox と、膨大な動画を提供する YouTube は、今回発表されたソリューションにおいて最も重要なパートナーですが、それはこの動画の巨大なエコシステムにおいて、ほんの一部に過ぎません。

私たちは、Google が Mozilla とともにオープンビデオの対応へ加わってくれたことに大変興奮しています。Google は、オープン Web と W3C ロイヤリティフリーのライセンス条項に一致する条件で VP8 の技術を公開してくれました。そして、最も重要なのは、世界最大の動画共有サイトにおいて、完全なオープンビデオ技術への対応に取り組まれているということです。これは、動画の展望を変えるきっかけとなるでしょう。さらに、Google 以外の動画サイトにおいても、ユーザ数を拡大し Web 技術を進化させている一連のブラウザとの互換性を確保することは言うまでもなく、同等のサービスを保ちながら動画技術の今後の進歩に付いていくためには様々な作業が必要となりますが、この技術はその基準を変えることにもなるはずです。

Mozilla では、Web 上での動画を、Web の他の技術と同様に迅速に進化させたいと考えてきました。それには、元となるオープン技術の基礎が必要でした。Theora は良いスタート地点でしたが、VP8 はさらに優れています。動画の革新を精力的に推し進めようとする私たちの取り組みに期待してください。Mozilla はこれまでの Web の歴史のように、端から中央に向けて、多くの小さな革命が組み合わさってそれぞれの要素の合計よりも大きなものとなるように、革新を行っていきます。VP8 はそのパズルのピースであり、HTML5 もまた別のピースなのです。このブログ [Mozilla Hacks Blog] を購読されている方は、今後さらに 他のピースの出現 を目にすることになるでしょう。Web はますます多くの技術に支えられており、Firefox はその先頭に立っています。私たちは HTML5 を越えて、Web があるべき次の場所へ、道を切り拓いていきます。

今日は素晴らしい変革の日です。明日もまた、新たな革新が生まれるはずです。

Firefox 4 の HTML5 パーサ – インライン SVG、スピード、などなど

この記事は Firefox の新しい HTML5 パーサを開発している Henri Sivonen によるゲスト記事です。HTML パーサはブラウザの中でもとくに複雑で繊細な部品のひとつです。HTML パーサは HTML ソースを Web ページに変換する部分を制御しますが、その部分を変更するのは稀ですから、充分なテストが必要になります。Gecko の開発が始まったのは 1990 年代終わりですが、大部分は再構築されています。しかし、HTML パーサは「オリジナル」なものとして残り続けている部分のひとつです。新しい HTML5 パーサは従来のパーサを置き換え、HTML5 への準拠はもちろん、スピードやその他の新しい機能をもたらします。

Gecko の HTML パーサを置き換えるプロジェクトが始まったのは1998年で、これまでかなり長くの期間行われています。そしてついに先日、新しいパーサが trunk ビルドにおいてデフォルトで有効になりました。つまり、ナイトリービルド をダウンロードするだけで、なにも設定を変更する必要なく新しいパーサを試せるのです。

訳注: Firefox 3.6 にも、バージョンは古いですが HTML5 パーサが搭載されています。設定を変更することでテストが可能です。

新しい HTML5 パーサには、主に4つの改良点があります。

  • SVG と MathML をインラインで HTML5 ページに埋め込めます。XML 名前空間は必要ありません。
  • パース処理は Firefox のメイン UI スレッドの外で行われます。これにより、全体的にブラウザのレスポンスが向上します。
  • 新しいパーサは innerHTML の呼び出しを 20% ほど高速化します。
  • 新しいパーサによって、古いパーサに関係する数多くのバグ が一掃されました。

Firefox Nightly もしくは他の HTML5 対応ブラウザで次の HTML5 デモ をご覧ください。次のように見えるはずです。

図: HTML5 対応ブラウザでは HTML 文書中にインラインで SVG, MathML を記述できる

HTML5 パーサとは

Gecko の HTML5 パーサは、HTML5 の構文解析アルゴリズム に基づき、バイトストリームを DOM ツリーに変換するものです。

HTML5 は HTML の実装者に対し、構文解析処理をを定義する初めての仕様になります。HTML5 より前の HTML 仕様では、バイトストリームを DOM ツリーに変換する処理について触れることはありませんでした。また、HTML5 より前の HTML は理論上、SGML の上に定義されるものでした。ですから、valid な HTML 文書のソースと DOM の関係は暗黙的ですが存在していました。しかし、invalid な文書の構文解析についてはうまく定義されていませんでした (Web 上のコンテンツの多くが、valid な HTML4 ではありません)。また、理論的には SGML の構文も HTML で使えるはずですが、実際に利用できるものはそのうちの一部でした。有名なブラウザーが、すべての SGML 構文を実装しなかったのです。

適切な仕様が存在していなかったことにより、ブラウザ開発者はその隙間を自分たちで埋めることになりました。挙動の互換性を保つため、大きなマーケットシェアを持つブラウザ (Mosaic, Netscape, IE など) をリバースエンジニアリングすることもありました。結果、ドキュメント化されていない共通ルールと、挙動の違いが生まれてしまいました。

HTML5 の構文解析アルゴリズムは、HTML を利用するブラウザやその他のアプリケーションについて、詳細な挙動を標準化するものです。設計上、HTML5 の構文解析アルゴリズムは現在の HTML コンテンツを処理することも可能ですから、アプリケーションは古いコンテンツのために古いパーサをメンテナンスし続ける必要はありません。Gecko の trunk ナイトリービルドにおいて、HTML5 パーサは text/html で送出されたすべてのコンテンツに利用されます。

何が今までと違うのか

HTML5 の構文解析アルゴリズムは字句化 (tokenization) とツリー構築 (tree building) というふたつのパートから構成されます。字句化はソースストリームをタグやテキスト、コメント、要素中の属性などに分割つする処理です。ツリー構築はそれらの情報を受け取り DOM ツリーを構築する処理になります。HTML5 構文解析アルゴリズムの字句化パートは、これまでの Gecko の挙動よりも Internet Explorer に近いものとなっています。Internet Explorer は大きなマーケットェアを持っているので、Web サイトの多くが IE のトークナイザで壊れないようにテストされていたと言えるのです。一方、ツリー構築の部分は WebKit の挙動に近いものとなっています。ですから、HTML5 以前は WebKit が最も妥当なツリー構築手法を提供していたのです。

さらに、HTML5 パーサはネットワークストリームの構文解析をメインスレッド外で行います。これまで、ブラウザはほとんどのタスクをメインスレッドで行ってきました。このメインスレッド外での構文解析という大きな変更は、古い Gecko の HTML パーサよりもメンテナンス性の高い HTML5 パーサのコードベースによって実現できました。

Web 開発者に関係する新機能

これまで話したことは、主にブラウザ開発者の興味をひくものだったでしょう。HTML5 パーサで注目すべき点は、パーサが変更されたことに気づかないところです。

しかし、Web 開発者にとって大きな機能がひとつあります。インライン MathML とインライン SVG です。HTML5 の構文解析によって、MathML と SVG は XML を必要とせず、Web のメインファイルフォーマットである HTML で利用可能になったのです。

つまり、洗練されたタイポグラフィで数式を HTML 文書で表示させたいとき、文書を XHTML に作り直すことや、整形式の XHTML を出力するよう Web サイトを管理するソフトウェアを修正する必要もありません。たとえば、次の二次方程式をそのまま HTML に埋め込むことができます。

x=b&PlusMinus;b24&InvisibleTimes;a&InvisibleTimes;c2&InvisibleTimes;a

同様に、XHTML に作り直すことなく、スケーラブルな画像を SVG からインラインで HTML に埋め込むことができます。最近は画面の大きさや解像度が多様になっていますから、画像を様々なズームレベルで鮮明に表示させることが重要になっています。SVG 画像はこれまでも object などから参照させることで HTML 文書中に表示できましたが、SVG をインラインで直接埋め込むことが便利な場合もあるでしょう。たとえば、注意を促すアイコンを外部ファイルから参照するのではなく、インラインで埋め込んでみましょう。

<svg height="86" width="90" viewBox="5 9 90 86" style="float: right;">
  <path stroke="#F53F0C" stroke-width="10" fill="#F5C60C" stroke-linejoin="round" d="M 10,90 L 90,90 L 50,14 Z"/>
  <line stroke="black" stroke-width="10" stroke-linecap=round x1="50" x2="50" y1="45" y2="75" />
</svg>

文書の先頭に <!DOCTYPE html> と記述し、上記のコードを埋め込んでください。新しいナイトリービルドで数式と警告マークが現れるはずです。

基本的に、MathML や SVG の XML ファイルがある場合、それをそのまま HTML ソースに貼りつけるだけで構いません (ただし、XML 宣言や DOCTYPE は取り除いてください)。ただし、注意点が2つあります。ひとつは、コードに名前空間接頭辞をつけることはできません。svg:svgmath:math と書くことはできません。もうひとつは、XLink を利用する場合、その名前空間接頭辞は xlink でなければいけません。

上記の MathML と SVG の例で見られるように、インライン MathML やインライン SVG はより HTML ライクで、XML 中に書いたものよりも煩雑ではありません。名前空間の宣言や属性周りの不必要な引用符が省略されています。しかし、引用符を省略してもタグは XML トークナイザではなく HTML5 トークナイザによって処理されるので、これでも動作するのです。名前空間宣言がなくても問題ありません。HTML5 のツリービルダは MathML や SVG らしい要素について、名前空間宣言を利用しないからです。代わりに、<svg> が現れるとその要素には DOM 上で SVG 名前空間が割り当てられ、同様に <math> にはMathML の名前空間が割り当てられます。また、MathML の例でお分かりかもしれませんが、これまで HTML でサポートされていない名前文字参照が利用されていますね。

Web 制作者むけに、インライン MathML とインライン SVG の構文解析についてまとめてみました。

  • <svg></svg> には DOM 上で SVG の名前空間が割り当てられます。
  • <math></math> には DOM 上で MathML の名前空間が割り当てられます。
  • foreignObjectannotation-xml (あまり重要ではありませんが) はネストした HTML スコープを開始します。ですから、SVG や MathML, HTML をその要素内で利用することが可能です。
  • パーサは大文字と小文字を修正します。ですから <SVG VIEWBOX=’0 0 10 10′> といったソースも HTML 中では動作します。
  • DOM メソッドと CSS セレクタは大文字と小文字を区別します。ですから DOM の呼び出しや CSS セレクタを利用する際は自分で正規化した表記を利用する事になります。SVG ではいくつかの構文が camelCase で定義されているので、たとえば viewBox と書く必要があります。
  • MathML や SVG 要素内で <foo/> という構文が現れた場合、その foo 要素はすぐに閉じられます。これは HTML 要素内の処理とは異なっています。
  • 属性は HTML 要素内と同じように字句化されます。ですから、HTML 要素内と同じ条件で引用符の省略などが行えます (引用符の省略は、値が空ではなく、また空白文字や ", , `, <, =, > を含まないときに可能です)。
  • 注意: 上記の2項目は、古い HTML の字句化と互換性を持たせる点でうまく組み合わせられない場合があります。たとえば、最後に書いた属性の引用符を省略したい場合、タグを閉じるスラッシュの前にはスペースが必要です。つまり、<circle fill=green /> は OK ですが <circle fill=red/> は NG です。
  • xmlns から始まる属性は名前空間の指定に何ら意味を持ちません。ですから、xmlns を利用する必要はありません。
  • XLink 名前空間に属する属性には xlink という接頭辞を利用しなければいけません (例: xlink:href)。
  • 要素名に接頭辞やコロンを含めることはできません。
  • SVG の script 要素の内容は XML で字句化されたように処理されます。HTML の script 要素と同じように処理されるわけではありません。
  • SVG や MathML の要素に開いた <![CDATA[]]> セクションがある場合、その中身は XML と同じように処理されます。これを利用し、text/html 中の SVG や MathML をサポートしない古いブラウザで、テキストが現れないようにすることができます。
  • MathML の名前文字参照は文書中すべてで利用できます (HTML コンテンツ内でももちろん使えます)。
  • (理由は分かりませんが)、SVG の断片を HTML に記述したり、MathML 意外の目的で <math> タグを記述した古いコンテンツに対応するため、HTML 要素を SVG 要素の子要素として (foreignObject なしで) 記述すると、その場で SVG/MathML コンテクストから抜け出してしまいます。これにより、typo によって驚くような挙動に出くわすことがあります。

JägerMonkey による JavaScript パフォーマンス向上

2008 年 08月、Mozilla は TraceMonkey を導入しました。私たちが Firefox 3.5 に搭載したこの新しい JavaScript エンジンは、次世代の Web ブラウザと Web アプリケーションを構築する新時代のパフォーマンスを実現するものとして歓迎されました。私たちが新しいエンジンを公開して間もなく、Google は V8 を搭載する Chrome を公開しました。Apple もまた、Safari に独自のエンジンを導入し、Opera も最新のベータ版ブラウザに新しいエンジンを搭載しています。

これらの新エンジンが登場した結果、新しい種類のアプリケーションが登場するのを目の当たりにすることになります。Processing を Web で実現してみる人もいれば、リアルタイムオーディオ編集ゲーム など、様々なものが試されるようになりました。(他にも Canvas デモリスト で紹介したものもご覧ください)

このようなアプリケーションと JavaScript エンジンの関わりについて、私たちは Mozilla で 2 つのことが分かっています:

  1. ある種のコードスタイルでは、私たちの Tracing による手法では上手く高速化できないことがある。(例えば前述のファミコンエミュレータでは、私たちのエンジンでは上手く高速化されませんが、これは主に長大な switch 文に起因しています)
  2. 「Trace 上にいる」(後述します) 限りにおいては、TraceMonkey は他のすべてのエンジンに勝っている。

Mozilla のエンジンは他のエンジンとは根本的に異なっています。他のエンジンは全て、いわゆる「メソッドベース JIT」を採用しており、読み込んだ JS コードを全て機械語にコンパイルし、実行しています。一方で Firefox は「Tracing JIT」を採用しています。Firefox では読み込んだ JS コードを全てインタープリタで実行しながら記録します。ホットパスを検出すると、それを機械語に変換して実行します。(Tracing について詳しくは昨年 hacks.mozilla.org に投稿された記事をご覧ください)

訳注: Tracing についての日本語での解説は訳者が公開している解説スライドをご覧く ださい

Tracing JIT の問題は、ある条件にあてはまるとインタープリタと機械語を相互に切り替えながら実行する必要があることです。機械語からインタープリタに戻らなければならない場合のことを「Trace が中断された」と表現しています。もちろん、インタープリタはネイティブな機械語よりも遙かに遅くなりますが、それが誰もが想定していたよりも多く発生することが分かりました。

そこで私たちは、第2世代のエンジンでは両手法のいいとこ取りをすることにしました:

  1. WebKit JS エンジンの一部分を流用して新しいメソッド JIT エンジンを実装し、それを用いて JavaScript コードを実行します。これにより JS 実行速度のベースラインは他のエンジンと同程度に引き上げられます。ここで最も重要なことは、コードに依らずおしなべて高速化されることです。言い換えれば、機械語との切り替えてインタープリタでの低速実行する必要がなくなるということです。
  2. 機械語を内部のループで更に高速なコードに変換するために Tracing エンジンを組み合わせます。つまり、コードに依らず高速化できるメソッドベース JIT に加えて、Tracing エンジンの強みも活かせるようにします。

この開発はまだ非常に初期の段階であり、デモをお見せできる段階にはありませんが、私たちが何をしようとしているのか知ってもらうのも良いと思ってこの記事を書きました。

より詳しく知りたい方は David MandelinDavid Anderson のブログや 新エンジンのプロジェクトページ をご覧ください。

Firefox 3.6 でサポートされる ClassList

この文書はフランスのOpenWebエンスージアストであるAnthony Ricaudによって書かれたものです。

なぜclassListが必要なのか

動的なWebアプリケーションは通常、何かの処理の結果としての視覚的なフィードバックや、ユーザーの操作による表示の変更を必要としています。

ユーザーインターフェイスを変更するために、DOM API (document.createElementdiv.removeChildelt.style.colorなど) を利用して要素を追加したり、削除したり、変更したりすることができます。しかし、現在表示されていてCSSによって関連付けされたものを変更するのであれば、要素のクラス属性を更新するのが簡単な方法です。

サンプルを使って説明しましょう。二つのモード (ベーシックモードとエキスパートモード) でフォームを表示する方法を考えていきましょう。

これはCSSルールを利用して、以下のように、互いのモードに独自クラスを指定するようにして書くことができます。

#anexpertinput.basic {
  display: none;
}
#anexpertinput.expert {
  display: inline;
}

動的に要素のクラスを変更するためにはelement.classNameを使うことができます。しかしながら、一つのクラスに対して追加や削除やトグルを行いたいかもしれません。これをするためには、2つの方法がたいてい使われます。ライブラリを使うか、正規表現を使って複雑なコードを書くなどです。ここにclassListと呼ばれるHTML5 APIを利用した新しい方法があります。このclassListは、Firefox 3.6から利用可能です。

このclassListをどのように使用するかについてとパフォーマンスの改善について見ていきましょう。

classList API

これらはclassList APIを使うサンプルです。

// By default, start without a class in the div: 
// Set "foo" as the class by adding it to the classList div.classList.add('foo'); // now
// Check that the classList contains the class "foo" div.classList.contains('foo'); // returns true // Remove the class "foo" from the list div.classList.remove('foo'); // now
// Check if classList contains the class "foo" div.classList.contains('foo'); // returns false: "foo" is gone // Check if class contains the class "foo", // If it does, "foo" is removed, if it doesn't, it's added div.classList.toggle('foo'); // class set to
div.classList.toggle('foo'); // class set to

デモ

ベーシックモードとエキスパートモードの両方をフォームで利用する最初のサンプルに戻りましょう。ライブデモを見て、これがどのように動作するか見てください。

以下のコードで、1行のJavaScriptを使って二つのモード間を切り替えることができます。


Blablablablabla...

#box.expert > #help,
#box.expert > label[for="postpone"],
#box.expert > label[for="lang"] {
   display: none;
}

classListの詳細については、MozillaのドキュメントHTML5の仕様書を見てください。

パフォーマンス

classList APIは唯一の簡単な方法ではないですが、よりパワフルな手段を提供します。デモをFirefox 3.6で実行した際の結果が以下のグラフになります。

benchmark classList

互換性

他のブラウザベンダーがHTML 5 classList APIをまだ実装していないため、これらのブラウザ向けにclassListを使わないコードを必要とするでしょう。そのような状況のためにこのサンプルコードを利用できます。

よく利用されるJavaScriptライブラリ内でclassListの現在の実装についてもっと知りたいのであえば、以下のようなライブラリを参照してください: