質問: javascript(coffeescript)を使い、ajaxで取得したhtmlコードをinnerHTMLでDOM要素に突っ込んでいます。 このとき、htmlコードの中にscriptタグを入れていてもjavascriptが実行されないのですが、 1. 実行されないのは標準の挙動でしょうか?それともブラウザが気を利かせていての挙動でしょうか? 2. セキュリティを考慮した上で意図したスクリプトだけ実行させるにはどうすればいいでしょうか? 以前にハマったんだけどうやむやにしてたら今日またハマって、たぶん時間かけて調べてもまた結局わからずじまいになりそうなうえにこれ理解してないのまずい気がするので、どうか怒らないで教えてください。
回答: 1. 実行されないのは標準の挙動 (仕様通り) です。 実行条件は 4.11.1 The script element に記載されていますが、`script` 要素の `src` や `async` などの属性の有無や、`script` 要素の生成方法など、様々な条件を網羅して記述されているため、きちんと読むのは正直結構しんどいです。 ただ、`innerHTML` を使ったケースでは「実行されない」という結果については、ちょうど Note に記述されています: > > Note: When inserted using the document.write() method, script elements execute (typically synchronously), but when inserted using innerHTML and outerHTML attributes, they do not execute at all. > > > なお、実行はされずとも `script` 要素はきちんと DOM ツリー上に作られています。 2. 意図したスクリプトを実行するためには、`element.innerHTML` のようなHTML文字列をパースして自動的に DOM 要素を作るインタフェースは用いずに、@kleaf さんの回答 のように `document.createElement` や `document.createTextNode` (または `node.textContent` )で `script` 要素を構築するのが間違いないかと思います。これならば実行されないという条件に入らないので。 逆に、意図せずスクリプトが実行されないようにするためには、やはり `innerHTML` ではなく `document.createTextNode` を使って、入力値から DOM 要素を作らせない (テキストしか作らせない) ようにすればいいです。そうではなく、入力値から安全に DOM 要素を生成するという要件であれば、スクリプト文字出力時のエスケープ処理を行う必要があります。