script 要素

4.3.1 script 要素

Status: Working draft

カテゴリー
メタデータ・コンテンツ
フロー・コンテンツ
フレージング・コンテンツ
この要素を使うことができるコンテキスト:
メタデータ・コンテンツが期待される場所
フレージング・コンテンツが期待される場所
コンテンツモデル:
src 属性がなければ、type 属性の値に依存する。
src 属性があれば、この要素は、空か、スクリプト説明文のみを含むかの、いずれかでなければいけません。
コンテンツ属性:
グローバル属性
src
async
defer
type
charset
DOMインタフェース:
interface HTMLScriptElement : HTMLElement {
           attribute DOMString src;
           attribute boolean async;
           attribute boolean defer;
           attribute DOMString type;
           attribute DOMString charset;
           attribute DOMString text;
};

script 要素は、ウェブ制作者がドキュメントに動的なスクリプトやデータブロックを含めることができるようにします。この要素は、ユーザーに対するコンテンツを表しません。

動的スクリプトを入れるために使う場合、インラインでスクリプトを組み込むか、または、src 属性を使って外部ファイルからスクリプトをインポートすることができます。スクリプト言語が "text/javascript" に相当するものでない場合、type 属性は必須です。type 属性が存在する場合、その値はスクリプト言語のタイプでなければいけません。

データブロックを入れるために使う場合、そのデータをインラインでデータを組み込まなければいけません。そして、type 属性を使ってデータのフォーマットを指定しなければいけません。この場合、src 属性を指定してはいけません。

type 属性は、スクリプトの言語やデータのフォーマットを指定します。この属性が存在すれば、その値は妥当な MIME タイプでなければいけません。オプションでパラメータを付けることができますが、charset パラメータを指定してはいけません(デフォルトは "text/javascript" です。この属性がない場合に使われます。)。

src 属性は、指定する場合、利用する外部スクリプトのアドレスとなります。この属性の値は、type 属性があればその指定されたタイプの、なければ "text/javascript" タイプのスクリプト・リソースを識別する妥当な URL でなければいけません。

charset 属性は、外部スクリプトリソースの文字エンコーディングを指定します。この属性は、src 属性がない場合は、指定してはいけません。もしこの属性がセットされた場合、その値は妥当な文字エンコーディング名でなければいけません。そして、そのエンコーディングに対応する推奨名でなければいけません。そして、もしあれば、外部ファイルの Content-Type メタデータcharset パラメータで指定されたエンコーディングに一致しなければいけません。[IANACHARSET]

asyncdefer 属性は、どのようにスクリプトを実行すべきかを指し示す論理属性です。

これらの属性を使って3つのモデルを選択することができます。async 属性があれば、スクリプトは利用可能になった時点で非同期に実行されます。async 属性がなく、defer 属性があれば、スクリプトはページのパースが終了したときに実行されます。どちらの属性もなければ、ユーザーエージェントがページをパースする前に、即座にスクリプトが取り出され実行されます。これらの属性に対応する正確な処理モデルは後述します。

defer 属性は、たとえ async 属性が指定されていても、指定することができます。この場合、defer しかサポートしない(async をサポートしない)古いウェブブラウザーは、デフォルトである同期ブロッキング動作の代わりに、defer 挙動にフォールバックすることになります。

defer 属性がを指定することができるなら、src 属性も指定することができます。

動的に src, type, charset, async, defer 属性を変更しても、直接的には何も起こりません。これらの属性は、後述しますが、ある特定の時にしか使われません。(先に言ってしまうと、要素がドキュメントに挿入されたときです。)

script 要素は、4つの関連メタデータを持ちます。1つめは、スクリプトが "実行済み" になったかどうかを指し示すフラグです。当初は、script 要素のこのフラグは未定義でなければいけません(生成時においては、スクリプトブロックは "実行済み" ではありません。)。script 要素が複製されたら、"実行済み" フラグは、もしセットされていれば、それが生成されたときの複製に伝搬しなければいけません。2つめは、その要素が "パーサー挿入" かどうかを指し示すフラグです。このフラグは HTML パーサーによってセットされ、document.write() コールを扱うために使われます。3つめと4つめは、スクリプトブロックのタイプと、スクリプトブロックの文字エンコーディングです。それらは、その時点の要素の属性に基づいて、スクリプト実行時に決定されます。

"実行済み" または "パーサー挿入" のいずれでもない script 要素が、次にリストアップしたイベントの一つを検知したら、ユーザーエージェントは script 要素を実行しなければいけません:

スクリプトの実行script 要素が実行されるとき、ユーザーエージェントは次の処理を実行しななければいけません:

  1. 以下のいずれかであれば:

    • script 要素が type 属性を持ち、その値が空文字、または、
    • script 要素が type 属性を持たず、値が空文字の language 属性を持つ、または、
    • script 要素が type 属性または language 属性のいずれも持たない、なら、

    ... この script 要素のスクリプトブロックのタイプを "text/javascript" にします。

    そうでなければ、script 要素は type 属性を持ち、この script 要素のスクリプトブロックのタイプを、その属性の値とします。

    そうでなければ、その要素は空でない language 属性を持ちます。:この script 要素のスクリプトブロックのタイプを、文字列 "text/" と、後に続けて、language 属性の値を連結したものとします。

    language 属性は非準拠です。type 属性が存在すれば、常に無視されます。

  2. script 要素が charset 属性を持っていれば、この script 要素のスクリプトブロックの文字エンコーディングを、charset 属性で指定されたエンコーディングとします。

    そうでなければ、この script 要素のスクリプトブロックの文字エンコーディングを、ドキュメントのエンコーディングと同じとします。

  3. script 要素のスクリプティングが無効、または、ユーザーエージェントが、この script 要素のスクリプトブロックのタイプで指定されたスクリプティング言語をサポートしていないなら、ユーザーエージェントは、この時点でこの手順を中止しなければいけません。スクリプトは実行されません。

  4. この要素が src 属性を持っておらず、その子ノードがコメントノードと空のテキストノードだけで構成されているなら、ユーザーエージェントは、この時点でこの手順を中止しなければいけません。このスクリプトは実行されません。

  5. 5.ユーザーエージェントは、この要素の "実行済み" フラグをセットしなければいけません。

  6. この要素が src 属性を持っているなら、その属性の値は、その要素に対して解決されなければいけません。そして、それが成功したら、指定のリソースをフェッチしなければいけません。

    歴史的な理由から、もしURLが javascript: URL という形式なら、ユーザーエージェントは、フェッチアルゴリズムの定義で必須であるにもかかわらず、実際には、指定のスクリプトを実行してはいけません。その代わり、ユーザーエージェントは、空の HTTP 400 レスポンスを受信したかのように振る舞わなければいけません。

    リソースのコンテンツタイプのメタデータが利用可能になったら、それに、Content-Type のエンコーディング展開アルゴリズムを適用します。もしこれがエンコーディングを返したら、ユーザーエージェントはそのエンコーディングをサポートし、そのスクリプトブロックの文字エンコーディングを、そのエンコーディングとします。

    取得プロセスが完了し、スクリプトのローディングが完了したら、ユーザーエージェントは、後述の手順を完了する必要があります。(もしパーサーがその時点でまだアクティブなら、それらの手順は、ペンディングしているスクリプト実行のハンドリングより、パーサーを優先します。)

    パフォーマンスの理由から、ユーザーエージェントは、属性がセットされたらすぐにスクリプトを取得することができます。その代わり、その要素がドキュメントに挿入されるという期待のもとでの動作となります。いずれにせよ、要素がドキュメントに挿入されたら、ロードを開始しなければいけません。もしユーザーエージェントがこのような事前取得を実行したにもかかわらず、その要素がドキュメントに挿入されない、もしくは、src 属性が動的に変更されたなら、ユーザーエージェントはスクリプトを実行しないでしょう。そして、取得プロセスは、事実上、無駄になってしまうでしょう。

  7. 次に、状況を説明する次のオプションの最初に従わなければいけません:

    ドキュメントがまだパース中で、その要素が defer 属性を持ち、src 属性を持ち、async 属性を持っていないなら、
    その要素は、ドキュメントのパース終了時に実行するスクリプトのリストの最後に、この要素を追加します。
    その要素が async 属性と src 属性を持っているなら、
    非同期に実行するスクリプトのリストの最後に、この要素を追加しなければいけません。
    その要素が async 属性を持つが、src 属性を持たず、非同期に実行するスクリプトのリストが空でないなら、
    非同期に実行するスクリプトのリストの最後に、この要素を追加しなければいけません。
    その要素が src 属性を持ち、"パーサー挿入" フラグを持っていれば、
    この要素は、保留外部スクリプトとなります。(このようなスクリプトは同時に1つだけです。)
    その要素が src 属性を持っているなら、
    できる限り早く実行するスクリプトのリストの最後に、この要素を追加しなければいけません。
    そうでなければ、
    ユーザーエージェントは、たとえ他のスクリプトが実行中だったとしても、すぐにそのスクリプトブロックを実行しなければいけません。

外部スクリプトのフェッチは、そのリソースをフェッチした時点で(下記に定義)、ネットワーキング・タスクソースによってキューイングされるそのタスクが実行されるまで、その要素のドキュメントの load イベントを遅らせなければいけません。

スクリプトのローディング完了時: もし script 要素が、前述のリストの一つに追加され、ドキュメントがまだパース中だったら、パーサーはそれを処理します。そうでなければ、ユーザーエージェントは、ネットワーキング・タスクソースタスクキューに置くタスクとして、次の手順を実行しなければいけません:

script 要素が、ドキュメントパース終了時に実行するスクリプトのリストに追加されたら:
  1. その script 要素がリストの最初の要素でなければ、まだ何もしません。これらの手順を中止します。

  2. そうでなければ、スクリプトブロックを実行(リストの最初の要素)します。

  3. リストからその script 要素を削除します(つまり、リストの最初のエントリーをシフトアウトします。)。

  4. もしリストにまだエントリーが残っており、現在リストの最初にいる要素に関連づけられているエントリーがロード済みなら、手順2に戻って、それを実行します。

ドキュメントパース終了時に実行するスクリプトのリストにあるスクリプトは、その innerHTML 属性がドキュメントのノードでセットされるなら、早めに実行することもできます。

script 要素が、非同期に実行するスクリプトのリストに追加されたら:
  1. そのスクリプトがリストの最初の要素でなければ、まだ何もしません。これらの手順全体を終了します。

  2. スクリプトブロックを実行(リストの最初の要素)します。

  3. リストからその script 要素を削除します。(つまり、リストの最初のエントリーをシフトアウトします。)。

  4. リストにまだスクリプトが残っており、リストの先頭の要素が、リスト追加時点で src 属性がなかった、もしくは現在ひとつだけあるが、その関連のスクリプトのロードが終了してしまったなら、手順2に戻り、この要素に関連づけられているスクリプトを実行します。

script 要素が、できる限り早く実行するスクリプトのリストに追加されたら:
  1. そのスクリプトブロックを実行します。

  2. リストからその script 要素を削除します。

スクリプトブロックの実行: 上記のステップがスクリプトの実行を要求したら、ユーザーエージェントは下記のように振る舞わなければいけまあせん:

ロードがエラーに終わったら(例えば、DNSエラー や HTTP 404 エラー)

スクリプトブロックの実行は、その要素上での error と呼ばれるシンプルなイベントの発出からだけで構成されなければいけません。

ロードが成功したら
  1. 次のように、スクリプトブロックソースを初期化します:

    スクリプトが外部ファイルだったら

    そのファイルの内容が、Unicode文字の文字列として解釈されますが、スクリプトのソースとなります。

    下表の各行に対して、最初の行から下に向かって、ファイルが、最初のカラムのバイト数より多くの利用可能なバイトを持ち、そのファイルの先頭のバイトが最初のカラムのバイトに一致したら、以前の値にかかわらず、スクリプトブロックの文字エンコーディングを、その行の2番目のセルのエンコーディングとなるようにセットします:

    16進数表記のバイト列 エンコーディング
    FE FF UTF-16BE
    FF FE UTF-16LE
    EF BB BF UTF-8

    この手順で、Unicode Byte Order Mark (BOM) を見つけます。

    ファイルは、スクリプトブロックの文字エンコーディングで指定された文字エンコーディングを使って Unicode に変換されなければいけません。

    スクリプトがインラインで、スクリプトブロックのタイプがテキストベースの言語なら、

    "スクリプト実行" アルゴリズムが最初に呼び出された時点の DOM text 属性の値が、スクリプトのソースとなります。

    スクリプトがインラインで、スクリプトブロックのタイプがXMLベースの言語なら

    "スクリプト実行" アルゴリズムが最初に呼び出された時点の script 要素の子ノードが、スクリプトのソースとなります。

  2. 適切なスタイルシートがフェッチされ適用されるか、ユーザーエージェントがタイムアウトし、それらのスタイルシートを待機しないと決めるまで、ボーズします。

  3. スクリプトブロックのソーススクリプトブロックのタイプを使って、script 要素ノードからスクリプトを生成します。

    これが、スクリプトがコンパイルされ、実際に実行されるところです。

  4. script 要素で load と呼ばれるシンプルなイベントを発出します。

DOM 属性 src, type, charset, async, defer は、同じ名前の対応するコンテンツ属性を反映しなければいけません。

script . text [ = value ]

要素のコンテンツを返します。テキストノードではない子ノードは無視されます。

値を指定することで、要素の子を置き換えることができます。

DOM 属性 text は、script 要素の直下の子要素となるすべてのテキストノードのコンテンツをツリー順に連結したものを返さなければいけません(コメントや要素は無視されます)。値が指定されたら、textContent DOM属性と同じように動作しなければいけません。

この例では、ふたつの script 要素が使われています。一方は外部スクリプトを組み込み、もう一方はいくらかのデータを含んでいます。

<script src="game-engine.js"></script>
<script type="text/x-game-map">
........U.........e
o............A....e
.....A.....AAA....e
.A..AAA...AAAAA...e
</script>

この場合のデータは、スクリプトがビデオゲームの地図を生成するために使うかもしれません。しかし、そのデータを、そのように使わなければいけないというわけではありません。恐らく、その地図データは、実際にはページのマークアップの他の部分に組み込まれているかもしれません。そして、ここにあるデータブロックは、そのゲーム地図内の特定の特徴を探すユーザーを助けるために、サイトの検索エンジンによって使われるだけなのかもしれません。

document.write() メソッドを使って挿入された場合は、script 要素は(通常は同期的に)実行します。しかし、innerHTMLouterHTML 属性を使って挿入された場合は、何も実行しません。

4.3.1.1 スクリプティング言語

スクリプトブロックのタイプが、ユーザーエージェントが実装しているスクリプティング言語の MIME タイプに一致するなら、ユーザーエージェントは、そのスクリプティング言語をサポートしていることになります。

以下に、MIME タイプとそれが参照する言語をいくつか挙げます:

application/ecmascript
application/javascript
application/x-ecmascript
application/x-javascript
text/ecmascript
text/javascript
text/javascript1.0
text/javascript1.1
text/javascript1.2
text/javascript1.3
text/javascript1.4
text/javascript1.5
text/jscript
text/livescript
text/x-ecmascript
text/x-javascript
JavaScript. [ECMA262]
text/javascript;e4x=1
JavaScript with ECMAScript for XML. [ECMA357]

ユーザーエージェントは、他の MIME タイプや言語をサポートすることができます。

サポートする言語かどうかをタイプから決定するとき、ユーザーエージェントは、未知の MIME パラメータを無視してはいけません。未知のパラメータ付きのタイプは、未対応であると見なさなければいけません。charset パラメータは、ここでの MIME タイプ の比較の目的のため、未知のパラメータとして扱われなければいけません。

4.3.1.2 外部スクリプト用のインライン説明文

script 要素の src 属性が指定されたら、script 要素のコンテンツは、もしあれば、要素のコンテンツから引き出される DOM text 属性の値が、次の ABNF の documentation プロダクション、および、Unicode の文字セットに一致するようにしなければいけません。[ABNF]

documentation = *( *( space / tab / comment ) [ line-comment ] newline )
comment       = slash star *( not-star / star not-slash ) 1*star slash
line-comment  = slash slash *not-newline

; characters
tab           = %x0009 ; U+0009 TAB
newline       = %x000A ; U+000A LINE FEED
space         = %x0020 ; U+0020 SPACE
star          = %x002A ; U+002A ASTERISK
slash         = %x002F ; U+002F SOLIDUS
not-newline   = %x0000-0009 / %x000B-10FFFF
                ; a Unicode character other than U+000A LINE FEED
not-star      = %x0000-0029 / %x002B-10FFFF
                ; a Unicode character other than U+002A ASTERISK
not-slash     = %x0000-002E / %x0030-10FFFF
                ; a Unicode character other than U+002F SOLIDUS

これは、ウェブ制作者が、外部スクリプトファイルを参照すると同時に、そのドキュメントの中では、著作権情報や API 情報といった説明文を入れることができるようにしたものです。この構文は、src 属性も提供しているとはいえ、ウェブ制作者が誤って妥当なスクリプトのように見えるものを含めないよう、制約されます。

<script src="cool-effects.js">
 // create new instances using:
 //    var e = new Effect();
 // start the effect using .play, stop using .stop:
 //    e.play();
 //    e.stop();
</script>

※ 原文:http://www.w3.org/TR/2009/WD-html5-20090825/semantics.html#script