[1] [[HTML]] の [DFN[[CODE(HTMLe)@en[[[script]]]]]] [[要素]]は、動的な[[スクリプト]]や、
[[スクリプト]]が使うデータを[[文書]]に埋め込むものです。
[9]
:[[開始タグ]]:必須
:[[終了タグ]]:必須
:出現できる文脈:[CODE(HTMLe)[[[head]]]] の子として、または [CODE(HTMLe)[[[body]]]]
子孫の大抵の場所で
:[[属性]]:
,属性名 ,属性値 ,既定値 ,説明 ,出典
,[[大域属性]]
,[CODE(HTMLa)[[[archive]]]] , , ,[NC4]
,[CODE(HTMLa)@en[[[async]]]]
,[CODE(HTMLa)[[[charset]]]] ,[CODE(SGML)[%[[Charset]]]] , ,charset ヒント ,[HTML 4]
,[CODE(HTMLa)[[[classname]]]] ,[[逆ドメイン名]] , ,級名 ,[ECMA-290]
,[CODE(HTMLa)@en[[[crossorigin]]]]
,[CODE(HTMLa)[[[defer]]]] ,([[真偽値属性]]) ,(偽) ,遅延評価 ,[HTML 4]
,[CODE(HTMLa)[[[event]]]] , , ,[[事象]] ,[HTML 4] 予約
,[CODE(HTMLa)[[[for]]]] ,[CODE(SGML)[[[IDREF]]]] , ,対象 ,[HTML 4] 予約
,[CODE(HTMLa)[[[id]]]] ,[CODE(SGML)[[[ID]]]] ,(なし) ,固有識別子
,[CODE(HTMLa)[[[language]]]] , , ,スクリプト言語 ,[HTML 4] 非推奨
,[CODE(HTMLa)[[[name]]]] , , , ,非標準
,[CODE(HTMLa)[[[purpose]]]] , , ,実行目的 ,[ECMA-290]
,[CODE(HTMLa)[[[src]]]] ,[CODE(SGML)[%[[URI]]]] ,(内容) ,外部スクリプト ,[HTML 4]
,[CODE(HTMLa)[[[type]]]] ,[CODE(SGML)[%[[ContentType]]]] ,(必須) ,[[スクリプト言語]] ,[HTML 4]
,[CODE(XMLa)[[VAR[ev:]][[event]]]] ,[CODE(ABNF)[[[QName]]]] ,(なし) ,[[事象名]]
,[CODE(XMLa)[[VAR[ev:]][[observer]]]] ,[CODE(XML)[[[IDREF]]]] , ,[[事象観察器]]
,[CODE(XMLa)[[VAR[ev:]][[phase]]]] , , ,
,[CODE(XMLa)[[VAR[ev:]][[propagate]]]] , , ,[[伝播]]制御
,[CODE(XMLa)[[VAR[ev:]][[target]]]] ,[CODE(XML)[IDREF]] , ,事象対象
* 仕様書
[REFS[
- [130] [CITE@en-US-x-hixie[HTML Standard]] ([TIME[2013-12-19 00:10:55 +09:00]] 版)
]REFS]
* 意味
[131] [CODE(HTMLe)@en[[[script]]]] [[要素]]は、動的な[[スクリプト]]や、データブロックを[[文書]]に含めるために使うことができます。
[SRC[>>130]]
;; [134] どちらであるかは [CODE(HTMLa)@en[[[type]]]] [[属性]]や [CODE(HTMLa)@en[[[language]]]]
[[属性]]によって決まります。
[132] [CODE(HTMLe)@en[[[script]]]] [[要素]]は[[利用者]]に対する[[内容]]を[[表現]]していません。 [SRC[>>130]]
* 動的なスクリプト
[133] 動的な[[スクリプト]]として [CODE(HTMLe)@en[[[script]]]] [[要素]]を使う時は、
- [[スクリプト]]を[[要素]]の[[内容]]として直接埋め込むか、
- 外部の[[スクリプト]]を [CODE(HTMLa)@en[[[src]]]] [[属性]]によって参照するか
... のどちらかの方法となります [SRC[>>130]]。
[135] [CODE(MIME)@en[[[text/javascript]]]] 以外の[[スクリプト言語]]の時は、
[CODE(HTMLa)@en[[[type]]]] [[属性]]は[['''必須''']]です [SRC[>>130]]。
[136] [CODE(HTMLe)@en[[[script]]]] [[要素]]の[[内容]]は、
[[スクリプト言語]]の仕様により定められた要件に従わなければ[['''なりません''']] [SRC[>>130]]。
* データブロック
[137] データブロックとして [CODE(HTMLe)@en[[[script]]]] [[要素]]を使う時は、
[[要素]]の[[内容]]として直接埋め込まなければ[['''なりません''']] [SRC[>>130]]。
[138] [CODE(HTMLa)@en[[[type]]]] [[属性]]は[['''必須''']]であり、
[CODE(HTMLa)@en[[[src]]]] [[属性]]は使っては[['''なりません''']] [SRC[>>130]]。
[139] [CODE(HTMLe)@en[[[script]]]] [[要素]]の[[内容]]は、
[CODE(HTMLa)@en[[[type]]]] [[属性]]で指定された書式の要件に従わなければ[['''なりません''']] [SRC[>>130]]。
* 構文
** タグ
[68] [CITE[Bug 6357 – ]]
の対応関係を考慮して複雑な解釈を行います。それに反して [[HTML]] として[[直列化]]できない値や混乱を招くものを禁止するために
>>140 のような規定があります。
** 外部スクリプトについてのドキュメントの制約
[142] [CODE(HTMLa)@en[[[src]]]] [[属性]]が指定されている場合、 [CODE(HTMLe)@en[[[script]]]]
[[要素]]の[[内容]]は外部の[[スクリプト]]についての[[ドキュメント]]とみなされます。
[[スクリプト]]として実行はされません。この場合には、 ([[スクリプト言語]]に関わらず)
次のものだけを使わなければならないという制約が課されます (空でも構いません) [SRC[>>130]]。
[FIG[
- [145] [CODE(charname)@en[[[SPACE]]]]
- [146] [CODE(char)@en[[[U+0009]]]]
- [147] [CODE(charname)@en[[[LF]]]]
- [148] [[JavaScript]] の行内コメント [CODE[/* ... */]]
- [149] [[JavaScript]] の一行コメント [CODE[[[//]] ... [[LF]]]]
-- 末尾に[[改行]]が必要です。
]FIG]
** 言語依存の制約
[150] [[HTML Standard]] は共通の制約以外には [CODE(HTMLe)@en[[[script]]]] [[要素]]の[[内容]]について制約を課しておらず、
[CODE(HTMLa)@en[[[type]]]] (と [CODE(HTMLa)@en[[[language]]]]) によって決定される[[言語]]の仕様による制限に適合しなければならないとしています。
[151] ただし実際にはそのような制約を明示している仕様はありません。
[152] [[HTML Standard]] によれば、 [CODE(HTMLe)@en[[[script]]]] [[要素]]で [CODE(HTMLa)@en[[[src]]]]
[[属性]]がない場合、 [CODE(HTMLe)@en[[[script]]]] [[要素]]の[[内容]]は
- [153] [[XML]] ベースの[[言語]]であれば[[子供]]を
- [154] テキストベースの[[言語]]であれば[[子供]]の[[テキスト節点]]を
... 使うことになっています。ここから推測すると、
- [155] [[XML]] ベースの[[言語]]であれば、 [CODE(HTMLe)@en[[[script]]]] [[要素]]の[[内容]]がその [[XML]]
[[言語]]の[[要素]]や[[テキスト]]
- [156] テキストベースの[[言語]]であればその[[言語]]によって記述された[[テキスト]]のみで、
[[要素]]は使用してはいけない
... という風に解釈するのが妥当でしょう。
[157] ただし [[HTML]] 構文では [CODE(HTMLe)@en[[[script]]]]
[[要素]]の構文解析直後の状態は常に[[テキスト節点]]を高々1つだけ含んだ状態になります。[[要素]]を[[子供]]にするためには
[[XML]] 構文を使うか[[スクリプト]]で挿入するしかありません。そのため、データブロックとして [[XML]]
ベースのデータが [CODE(HTMLe)@en[[[script]]]] [[要素]]の[[内容]]に埋め込まれることがありますが、
[[XML]] のソースを[[テキスト節点]]として含んだ状態になってしまいます。
** 擬似注釈宣言の使用
[18] [CODE(HTMLe)[script]] 要素に対応していない古い WWW ブラウザは、
[CODE(HTMLe)[script]] 要素内の[[文字データ]]も構わず解釈してしまいます。
そこで、 [CODE(HTMLe)[script]] 要素の内容としてスクリプトを記述するときには、
HTML の[[注釈宣言]]のように最初に [CODE(HTML)[]] をつけることが慣習となっています。
HTML 4 によれば、これは HTML の機能ではなく、[[スクリプト機関]]の機能とされています。
この機能に対応している言語には [[JavaScript]], [[VBScript]], [[Tcl]]
があるようです。 [SRC[HTML 4 18.3.2]] より正確には、この3つの言語は
[CODE(HTMLe)[script]] 要素の内容の一番最初の非[[空白]]文字列が
[CODE[]] は、3つの言語のいずれも、それだけで書くことはできず、
それぞれの言語の注釈の内容として (JavaScript の場合は [SAMP(JS)[// -->]]
のようにして) 書くことが必要らしいです。
[Q[らしい]]というのは、正確にこれを規定した仕様がないからです。
HTML 4 は[Q[スクリプト機関]]によるものだと言っていますから、
スクリプト言語の言語仕様かなにかに規定があってもよさそうなものですが、
そのようなものは見たことがありません。また、 HTML
に直接埋め込まれていない [[ECMAScript]] のスクリプトのソース・コードに
[CODE[
]PRE]
のように自然言語の注釈を入れておくことがよく行われていました
(初期の使用例にそう載っていたからみんなで真似したのでしょう)。
(この例のように開き (のようなもの) の後に書くこともできましたが、
閉じの前に書くのが普通だったと記憶しております。)
後にこのような冗長なことはせず、
[PRE(HTML)[
]PRE]
のように簡単に書くようになりました。
[35] また、[Q[裏技]]的なものとして、
[PRE(HTML)[
]PRE]
のような書き方が紹介されることもありました。
(この例のようになぜかスクリプトの途中に書いているものもあれば、
注釈宣言 (のようなもの) の前後に書いているものもありました。
どこに入れるにせよ、書く内容は一行にするか、
うまくして行頭にスクリプト言語の注釈導入子が来るように調整することが重要です。
また、 [CODE(SGML)[[[etago]]]] が使えないことにも注意が必要です。)
[38] スクリプト言語の演算子として [CODE[>]] を使うことが良くありますが、
古いブラウザの中には注釈宣言を [CODE[>]] で終えてしまうものがあることが知られています。
[SAMP(JS)[[VAR[x]] > [VAR[y]]]] のような式は [SAMP(JS)[[VAR[y]] < [VAR[x]]]]
と書くことで回避できます。 [SRC[HTML 4 18.3.2 Note]]
もっとも、そのようなブラウザは HTML 4 の時点でも骨董品ですし、
HTML 4 も特にそうするべきだなどとは言っていません。
参考文献:
- [16] [CITE[ 内の要素はすべてコメントで囲んだ方が安全です。]]
誤って「[CODE(JS)@en[//->]]」のようなもので終わることもあるみたいです。
[[#comment]]
** 処理モデル
[28] [CODE(HTMLe)[script]] 要素によるスクリプトは、
文書の読込み時に実行されます [SRC[HTML 4 18.1]]。
[CODE(HTMLa)[src]] 属性による外部スクリプトは優先的に実行されるという説を唱える人がいますが、
根拠は不明です。特定の UA ではそうなのかもしれませんが、
少なくても HTML 4 は何も規定していません。
但し、 [CODE(HTMLa)[[[defer]]]] 属性や [CODE(HTMLa)[[[event]]]]
属性は実行時機に影響するのかもしれません。
*** 構文解析との関係
[63]
[CODE(HTMLa)@en[[[defer]]]]、[CODE(HTMLa)@en[[[async]]]] なしの場合で、
[CODE(HTMLa)@en[[[src]]]] ありの場合に、外部[[スクリプト]]が実行されるまで[[構文解析]]は停止するか?
[CITE[Index of /~wakaba/-temp/test/html/script/src]] ([TIME[2008-12-16 11:37:00 +09:00]] 版)
[64] [[HTML]] として記述された [CODE(HTMLe)@en[[[script]]]] [[要素]]の場合 (nodefer-1)、
どのブラウザも[[構文解析]]が停止します。
[65] [[DOM]] によって作成された [CODE(HTMLe)@en[[[script]]]] [[要素]]の場合 (nodefer-script-1)、
[[Opera]] 以外は[[構文解析]]を続行し、外部[[スクリプト]]は準備が出来次第実行します
([[HTML5]] に従った動作)。 [[Opera]] 9.61 は >>64 同様、[[構文解析]]を停止します。
** 安全性
[43]
'''Web メイルにおける HTML メイル''':
[[HTML]] を[[利用者界面]]として利用した [[MUA]]
(いわゆる [[Webメイル]]) で [[HTML]]
[[文書]]が含まれる[[メイル]]・[[メッセージ]]を表示する時には特に注意が必要です。
[CODE(HTMLe)@en[[[script]]]] [[要素]]など[[スクリプト]]が実行され得るものをそのまま
[[HTML]] に含めると、 [[Webブラウザ]]側でその [[HTML]] [[文書]]全体
[WEAK[([[HTMLメイル]]自体とその周りの[[利用者界面]]を含む全体)]]
の権限で[[スクリプト]]が実行されることになります。
[[Webブラウザ]]外に被害が及ぶかという点では通常の鯖側の[[スクリプト]]の安全上の脅威と変わりませんが、
[[利用者界面]]の部分を介して[[利用者]]の意図せぬ (削除などの)
操作を行ったり、受信したメッセージや個人情報が流出したりする危険性があります。
[[#comment]]
** 歴史
[2] [CODE(HTMLe)[script]] 要素は、 [[NN2]] が [[LiveScript]]
と共に実装したのがはじめであると考えられています。
[20] [CODE(HTMLe)[script]] 要素がはじめて公式な仕様書に入ったのは
1997年1月の [[HTML 3.2]] でした。しかし、
このときの最終的な勧告では詳細が決まらず、
将来の版のために予約すると述べるに留まっていました。
>
[SRC[HTML 3.2 DTD]]
** HTML4
[12] その後1997年12月の [[HTML 4]] で、 [CODE(HTMLe)[script]]
要素型はようやく正式な仕様の一部となりました。
当時 [[WinIE]] や [[NN]] が実装していた [CODE(HTMLe)[script]]
の基本的な機能が仕様に入りましたが、 WinIE だけが実装していた
[CODE(HTMLa)[event]] 属性と [CODE(HTMLa)[for]] 属性は、
将来のために予約とされました。
[24] 1998年に勧告された [[DOM 1]] やその後の [[DOM 2]] では、
[CODE(HTMLe)[script]] 要素型に対応する [CODE(DOMi)[[[HTMLScriptElement]]]]
界面が定義されています。ここでは、標準の属性の他、
[CODE(HTMLa)[for]] 属性と [CODE(HTMLa)[event]] 属性も[Q[将来の使用のために予約]]
として定義だけされています。
[25] >>24 そんな将来くるのかな〜。来たら嫌だな〜
[26] >>24-25 将来の使用は M$ の仕様の間違いじゃないのかな。
[32]
>>24-26
その後 [[XHTML 1]] が標準化されましたが、予約2属性はやはり正式な仕様には昇格せず、
このまま忘れ去られようとしています。しかし、両属性の機能は拡張して汎用化されて
[[XML事象]]仕様の一部として標準化されました (2002年)。
[REFS[
- [29] [[HTML 4]]
-- [CITE[18 Scripts in HTML documents]]
-- [CITE[Element content]]
- [[ECMA-290]]
- [[XHTML 1.0]]
-- [CSECTION[4.8. Script and Style elements]]
(参考)
]REFS]
[4] [CODE(HTMLa)[[[src]]]] 属性が指定されている場合、
スクリプトはその外部資源で定義されます。
[ABBR[[[UA]]] [利用者エージェント]]
は[[内容]]を無視し、指定された
[ABBR[URI] [統一資源識別子]] のスクリプトを取り寄せなければなりません。
[CODE(HTMLa)[src]] 属性が指定されていない場合、
[VAR[UA][利用者エージェント]]
は内容をスクリプトとして解釈しなければなりません。
[SRC[HTML 4 18.2.1]]
[30] [ABBR[[[XHTML]]] [拡張可能ハイパーテキスト・マーク付け言語]]
より前の [ABBR[HTML] [ハイパーテキスト・マーク付け言語]] では、
[CODE(HTMLe)[script]]
要素の内容は [CODE(HTMLe)[[[style]]]] 要素の内容同様[[文字データ]]
([CODE(SGML)[[[CDATA]]]]) 宣言内容とされていました。
つまり、 [CODE(HTMLe)[script]] 要素内ではほとんどの[[マーク]]は認知されず、
[ABBR[[CODE(SGML)[[[etago]]]]] [終了タグ開き]] ([CODE(HTML)[]]) の
直後に[[名前開始文字]] [WEAK[([[ラテン文字]]など)]] または
[ABBR[[CODE(SGML)[[[tagc]]]]] [タグ閉じ]] ([CODE(HTML)[>]])
が来たらそこで [CODE(HTMLe)[script]] 要素が終わることになっていました。
ですから、スクリプト言語の[[演算子]]などとして
[ABBR[HTML] [ハイパーテキスト・マーク付け言語]]
の[[マーク文字]]が登場することがよくありますが、
そのような場合にもほとんど[[文字参照]]化する必要がありませんでした。
[36]
[ABBR[[CODE(SGML)[[[ETAGO]]]]] [終了タグ閉じ]] がかけないのは
[CODE(JS)[[CODE(DOMa)[[[document]]]].[CODE(DOMm)[[[write]]]]]]
のデータを作る時などにしばしば問題となり、その最盛期には、
これが原因でうまく動かないことに悩む人もよく見受けられました。
回避するためには、そのスクリプト言語の文字列連結を使ったり
([SAMP(JS)['<' + '/a>']])、 escape (quote) 機能を使ったり
([SAMP(JS)['<\/a>']])、文字生成関数を使ったり
([SAMP(VB)["<" & [[Chr]] (47) & "a>"]])
する方法がよく紹介されました。
[33] しかし、 [ABBR[[[XML]]] [拡張可能マーク付け言語]] では
[ABBR[[CODE(SGML)[CDATA]]] [文字データ]] 宣言内容は使えないので、
[ABBR[[[XHTML 1]]] [拡張可能ハイパーテキスト・マーク付け言語 1]] では
[ABBR[[CODE(XML)[[[PCDATA]]]]] [解析可能文字データ]]
と宣言されています。
ですから、 [ABBR[[CODE(SGML)[STAGO]]] [開始タグ開き]]
([CODE(XML)[<]]) は必ず [[escape]]
して [CODE(XML)[<]] としなければならないなどの制限があります。
これを回避するために [[[CODE(XML)[CDATA]]区間]]を使う方法がよく紹介されますが、
そうすると多くの既存の [ABBR[WWW] [World Wide Web]]
ブラウザとの互換性が失われてしまいます。
ですから、 [ABBR[XHTML] [拡張可能ハイパーテキスト・マーク付け言語]] で
[CODE(HTMLe)[script]] 要素を使う時は [CODE(HTMLa)[src]]
属性を使った外部スクリプトとするのが良いと言われています。
[41]
[CODE(HTMLa)[src]] で指定された資源が取得できない時に内容を使うとする説があります。
[CITE[SCRIPT - Client-side Script(jp)]]
しかし、 [ABBR[HTML] [ハイパーテキスト・マーク付け言語]] 4
の規定と矛盾します。
[WEAK[(この文書はほんとうに [ABBR[HTML] [ハイパーテキスト・マーク付け言語]] 4 に基づいているのでしょうか?)]]
[47]
[CITE[Working with the WebKit Nightly Builds]]
([[名無しさん]] [WEAK[2006-11-05 02:47:22 +00:00]])
[48]
[CITE[Surfin’ Safari - Blog Archive » Understanding HTML, XML and XHTML]]
** XHTML2
[73] [[XHTML2]] 第6次案までは [CODE(HTMLe)@en[[[script]]]] [[要素]]がありましたが、
第7次案で [CODE(HTMLe)@en[[[handler]]]] に改名されました。
** HTML5
[79]
図にしましたwwww
[REFS[
-
-
]REFS]
* 実装
[31] [CODE(file)[[[CGI.pm]]]] は、 XHTML 出力 mode だと、
[[注釈宣言]]内に [[[CODE(XML)[CDATA]]区間]]宣言という素晴らしい出力をしてくれます(w
[50]
[CITE[Bug 60724 –
]PRE]
[[VBScript]] による例
[PRE(HTML)[
]PRE]
[[Tcl]] による例
[PRE(HTML)[
]PRE]
[[#comment]]
** メモ
[44]
[CITE[XHTML Frequently Answered Questions]]
[[HTML 4]] は [[SGML]] [[応用]]なのに
[CODE(JS)@en[[[document]].[[write]]]]
が使えて、
[[XHTML 1]] は [[XML]] [[応用]]だから
[CODE(JS)@en[[[document]].[[write]]]]
が使えないというのはよくわからない。
([[名無しさん]] [WEAK[2006-08-05 06:53:16 +00:00]])
[46]
[CITE[404 Blog Not Found:javascript - scriptタグによる通信が特許侵害!?]]
([[名無しさん]] [WEAK[2006-11-04 02:20:29 +00:00]])
[49]
[CITE[Bug 178258 – document.forms has no properties on a page without (JavaScript error)]] ([CODE[2007-01-29 17:04:28 +09:00]] 版)
([[名無しさん]])
[51]
[CITE@en[HTML5 script start tag should select appropriate content model according to src]] ([[David Woolley]] 著, [CODE[2007-04-21 22:52:46 +09:00]] 版)
([[名無しさん]] [WEAK[2007-04-28 03:58:40 +00:00]])
[52]
[CITE[HTML5 IRC logs: w3c / #html-wg / 20070423]] ([CODE[2007-06-30 15:38:51 +09:00]] 版)
> [03:47] Lachy: since you were discussing Safari's handling of earlier, we might make that a Dashboard-only quirk - we foolishly did it for Firefox compatibility, and then a huge number of Dashboard widgets started relying on it, and now Firefox no longer handles it as empty in HTML
([[名無しさん]])
[53]
[CITE@en[http charset,
]PRE]
([[名無しさん]])
[55]
[CITE@en[Re: