9. 仕様の作成
Michael Gardner と Randy Solton は 11 月の会合が終わった後すぐに仕様の第 1 ドラフトに取り掛かり、それから六週間で驚くべき進捗を生んだ。Gardner と Solton の他に、第 1 ドラフトは技術的貢献者として Brendan Eich (Netscape), C. Rand McKinney (Netscape), Donna Converse (Netscape), Shon Katzenberger (Microsoft), Robert Welland (Microsoft) を挙げている。
Robert Welland はレドモンド1に戻り、自身が書いた JScript 0.1 仕様を Shon Katzenberger に渡して JavaScript の意味論を記述する作業を進めるよう伝えた [Welland et al. 2018, +12:02]。数学の Ph. D. を持つ Katzenberger は形式的な記法の扱いに慣れており、疑似コード (補遺 Q) という概念を使って上手く JavaScript の意味論を記述した。完成した文書は相互運用性を十分保証できると彼が思えるだけの詳細さを持っていた。Katzenberger は JavaScript 規格の作成における Microsoft の主任技術貢献者となる。彼は実際の実装を実行して仕様と合っているかどうかを確認し、Welland と Smith の徹夜仕事が見つけていなかった詳細を疑似アルゴリズムに追加していくことで仕様を改善した。彼は改訂された新しい仕様を Borland の編集者に渡し、彼らが公式のドラフトを完成させた。Katzenberger は 2018 年のインタビュー [Welland et al. 2018, +21:16] で、編集上の変更が意図せずアルゴリズムを壊すことがあって感心しなかったと語っている。編集者を Guy Steele が務めることになったとき Katzenberger は非常に喜んだ。
1997年 1 月 10 日のドラフト [TC39 1997] で仕様の基本的な構造が完成 (図 13) し、JavaScript を定義するための基本的な手法、慣習、言い回しが定義された。その多くは 20 年が経過した現在でも ECMAScript 規格で利用されている。
1997 年 1 月 10 日のドラフト | ECMA-262 第 1 版 |
範囲 | |
準拠 | |
参考文献 | |
概要 | |
表記規則 | 表記規則 |
ソーステキスト | ソーステキスト |
字句規則 | 字句規則 |
型 | 型 |
型変換 | 型変換 |
変数 | 実行文脈 |
式 | 式 |
文 | 文 |
関数定義 | 関数定義 |
プログラム | プログラム |
ネイティブ ECMAScript オブジェクト | ネイティブ ECMAScript オブジェクト |
エラー |
構文規則の説明は主に Netscape が提供した仕様から取られたのに対して、式および文レベルの文法構造の説明や生成規則の名前には主に Microsoft が提供した仕様で使われたものが採用された。式の構文は提供された二つの仕様のいずれとも少しだけ異なっており、例えば関数呼び出し、オブジェクトの生成 (new
演算子)、オブジェクトのプロパティアクセスといった式要素の優先順位が異なる。
第 1 ドラフトは自動的なセミコロンの挿入 (Automatic Semicolon Insertion, ASI) をパースエラーを修正する処理として明確に記述している。言語の文の文法には複合文でない全ての文を終わらせる明示的なセミコロンが含まれる。そのため ASI が無いと、セミコロンを付けないときパースエラーが発生する。ASI の仕様は JavaScript パーサーがそういったパースエラーに対してセミコロンの存在を仮定してエラーの修正を試みなければならない状況を定義する。第 1 ドラフトの ASI 規則は不完全であり、 以降のドラフトおよび版で洗練された。
1 月 10 日のドラフトには言語に含まれる様々な構文の意味論を定義するための Shon Katzenberger が書いた疑似アルゴリズムが含まれる。疑似アルゴリズムの例を図 14 に示す。疑似アルゴリズムは連番の番号が付いたステップとステップ間の簡単な条件分岐から構成され、各ステップは命令的語な散文からなる。ステップを記述する散文は英語で書かれ、よく使われる操作を表す基本的な単語に対しては単語の定義が仕様の中に含まれる。アルゴリズムに対しては仕様内で命名や「呼び出し」が行われる。
4.7.4 GetValue(V)
1. If Type(V) is not a Reference, return V.
2. Call GetBase(V)
3. If Result(2) is null, generate a runtime error.
4. Call the [[Get]] method of Result(2), passing GetProperty(V) for the property name and
GetAccess(V) for the access mode.
5. Return Result(4).
このドラフトではアルゴリズムで使われるデータ型も定義される。例えば Number, Boolean, String, Object, Undefined, Null はどれも ECMAScript プログラムから見える値の型である。一方で Reference, Completion, List は言語の意味論を定義するための型であり、ECMAScript プログラムからは直接観測できない。
Object 型の仕様では、オブジェクトのプロパティのそれぞれに対してアクセスや改変をどの程度行えるかを制御するために、プロパティの属性語 (attribute) という概念が導入される。第 1 ドラフトでは ReadOnly, ErrorOnWrite, DontEnum, NotImplicit, NotExplicit, Permanent, Internal という七つの異なる属性が定義されていたが、最終的に ErrorOnWrite, NotImplicit, NotExplicit は削除され、Permanent は DontDelete と改名された。Internal 属性を持つプロパティはオブジェクトに関連付く内部状態を保持するものの、その内部状態を ECMAScript プログラムから直接観測することはできない。そういったプロパティは内部プロパティ語と呼ばれ、組み込みオブジェクトやホストオブジェクトに特有の振る舞い、あるいは普通のオブジェクトの意味論を実装するのに必要な状態を保持する。
内部メソッド語という概念も導入された。内部メソッドはオブジェクトの基礎的な振る舞いを定義するアルゴリズムのことを言う。普通のオブジェクトと異なるオブジェクト (例えば配列オブジェクト) に対しては内部メソッド (の一部) に別の定義を指定できる。本質的に、内部メソッドのインターフェースは簡単なメタオブジェクトプロトコル語の仕様である。
仕様の中で内部メソッドと内部プロパティは [[Foo]] のように二つの四角括弧で囲って表される。1 月 10 日のドラフトでは [[Get]], [[Put]], [[HasProperty]], [[Construct]], [[Call]] という内部メソッドと [[Prototype]] という内部プロパティが定義された。これらの内部メソッドはオブジェクトのプロパティアクセス、プロトタイプ継承、関数起動の意味論の初めての定式化で利用される。ES1 が完成するまでの間に内部メソッド [[CanPut]] と [[Delete]] が追加された。
第 1 ドラフトの目次にはネイティブの (組み込みの) ECMAScript オブジェクトに関する節とブラウザおよびウェブサーバーというホスト環境のオブジェクトに関する節が載っているものの、これらの節は空となっている。また第 1 ドラフトには「Issue (問題あり)」と明示的にタグが付いた要素が 20 個あり、追加される可能性のある言語拡張もいくつか補遺に示されている。
1 月 10 日のドラフトは 1997 年 1 月 15 日に開催された初回の技術的ワーキンググループにおける議論のたたき台となった。この議論ではいくつかの重要な決断が行われた [Wiltamuth 1997a]。決定された事項の一部を示す:
- 最初の規格にはホスト (例えばブラウザやウェブサーバー) 特有のライブラリに含まれるオブジェクトや関数の仕様を含めない。
- 当時の言語に対する拡張は仕様の完全なドラフトを完成させてから考える。
- コンマ演算子と
?
演算子は Reference 値を伝播させない。そのため代入の左辺で使うことはできず、関数呼び出しにthis
が渡されることはない。 - 非 ASCII の Unicode 文字は識別子で許される。
- ヌル文字 (U+0000) は文字列値で許されない。
- グローバルな関数宣言と変数宣言は列挙可能 (enumerable) かつ削除可能 (deletable) なプロパティを作成する。組み込みオブジェクトの仕様で定義されるプロパティはデフォルトで列挙不能かつ削除不能である。
初回のワーキンググループ会合で解決されなかった問題には、複数代入の評価順序、継承された読み込み専用プロパティに対する代入の意味論、そして 1970 年以前の日時を表す値の扱いがある。
ワーキンググループ (図 15) は 1997 年 4 月まで定期的に議論を行い、編集者が準備した大きな問題と小さな問題のリストを一つずつ取り上げていった。会合は 9 回開かれ、それぞれの報告書が残されている [1997a, b, c, d, e, f, g, h, i]。ワーキンググループの会合に何度か主席した Richard Gabriel は個人的な会話で、会合でよく目にした光景を語った。Guy Steele が何らかの機能のエッジケースにおける振る舞いについて質問をする。すると Brendan Eich が「分からない」と言ったり、Eich と Shon Katzenberger の意見がまとまらなかったり一致しなかったりする。このような場合、二人は互いに自分たちの実装でテストケースを実行し、答えが一致したときはそれが仕様で規定される振る舞いとなった。答えが異なる場合は合意に至るまで議論が行われた。
Scott Wiltamuth (記録係) | (Microsoft) |
Brendan Eich | (Netscape) |
Shon Katzenberger | (Microsoft) |
Michael Gardner (第 1 ドラフト共同編集者) | (Borland) |
Randy Solton (第 1 ドラフト共同編集者) | (Borland) |
Clayton Lewis | (Netscape) |
Guy Steele (編集者) | (Sun) |
Garnder と Solton による最初の仕様ドラフトに続く形で、1997 年 2 月 27 日から 5 月 2 日までの間に Guy Steele が編集者を務めた 7 つのドラフトが TC39 全体に公開された。Ecma 総会に提出された最終ドラフト [TC39 1997b] を除いた全てのドラフトには様々な問題が解決されるまでの詳細な記録が残されている [TC39 1997d]。
JavaScript とその使い方に長期的影響をもたらした問題もある。例えば議論が長く続いた問題の一つに、短絡評価を行う論理演算子 &&
と ||
に渡されたオペランドが真偽値に型強制可能だったとき、評価結果をオペランドの値とする (「Perl スタイル」) か、それとも true
または false
にする (「Java スタイル」) か、というものがある。元々 Brendan Eich は「Perl スタイル」の意味論で大部分を実装していたものの、一部で「Java スタイル」の振る舞いも存在した。これに対して Microsoft と Borland は全ての場合を「Java スタイル」の意味論で実装していた。最終的に「Perl スタイル」で統一する判断がなされた。
この判断によって、数年後に広く使われることになる JavaScript のイディオムが可能になった。値 null
と値 undefined
は false
に型強制され、オブジェクトの参照は全て true
に型強制される。そのため図 16 に示す形でオブジェクトのプロパティや省略可能な関数パラメータにデフォルトの値を提供できる。
function f(options) {
// options にオブジェクトが渡されたなら、それを使う
// そうでなければデフォルトのオプションを使う
options = options || getDefaultOptionsObject();
...
}
Brendan Eich は JavaScript 1.2 で行った ==
演算子の意味論の変更 (型強制の削除) を仕様に含めたいと思っていたことを記憶している。しかし Shon Katzenberger は、その変更で破壊される既存のウェブページの数が多すぎるので変更はもはや不可能であると Eich を説得した。これを受けて Eich は SpiderMonkey の JavaScript 1.3 リリースで元の意味論を復活させた。
TC39 の第 3 回会合は 1997 年 3 月 18–19 日に開催された。これは規格第 1 版の受理と承認を受ける目標とされた 6 月の Ecma 総会より前に予定されていた最後の公式 TC39 会合だった。このスケジュールに間に合わせるには、規格を TC39 から総会に提出するための投票を第 3 回会合で行う必要がある。
3 月 12 日にドラフトのバージョン 0.12 [TC39 1997a] が TC39 全体に公開され、それについて 3 月 14 日のワーキンググループ会合で議論があった。ドラフトは技術的な完成に近づいていたものの、複雑な Date
オブジェクトの定義に関する章には節題があるだけだった。ただ Shon Katzenberger がそのまま仕様にできるクオリティの完全な提案を持ってきていたので、議論とレビューを行えば仕様に取り込める状況だった。文書は 1 月 10 日のドラフトから 2 か月で実質 41 ページから 96 ページに成長した。ドラフト 0.12 には問題を書き留めるために内部で使われた「Issue」というタグが 8 つ含まれ、問題追跡用の補遺 (appendix) には重要な項目が 6 つ残っており、さらに Date
の仕様も欠けていた。ワーキンググループ会合では他にも数十の問題が議論されたので、最終的な仕様ではこれらも解決しなければならなかった。
論争を引き起こしかねない問題はこれ以上残っておらず、3 月の末までに最終ドラフトを完成させられるという Scott Wiltamuth の確信に基づき、TC39 は 6 月の承認投票に向けてドラフトを Ecma 総会に提出することに全会一致で合意した。この結果、仕様を完成させ、Ecma 事務局のスタッフと連携してスケジュールと書式の要件を Ecma の要求に合わせる責任が仕様のワーキンググループに生じた。ドラフトの完成には Wiltamuth の予定より一か月長くかかり、ここからさらに 3 つの中間ドラフトが内部で公開された。最終ドラフト [TC39 1997b] は 1997 年 5 月 2 日に公開され、5 月 5 日に Ecma 総会のメンバーに配布された。最終ドラフトは Ecma の文書規則に従った文書であり、Richard Gabriel が執筆した非規定的語な言語概説が含まれる。1997 年 6 月の会合で、Ecma 総会は提出されたドラフトを編集上の小さな変更の後に Ecma 規格 ECMA-262 第 1 版 (Ecma Standard ECMA-262, 1st Edition) として公開することに合意した。編集上の変更は 1997 年 9 月 10 日に完了し、完成した文書は TC39 に配布された。9 月 16–17 日の TC39 会合 [TC39 1997h] で ECMA-262 第 1 版 の公開版がリリースされた [Steele 1997]。
-
訳注: レドモンドには Microsoft の本社がある。 ↩︎