laurel
@laurel (こね)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

onerror属性に設定したスクリプトの挙動について

onerror属性の挙動について,調査しても手がかりが掴めなかったので質問させてください.

<!DOCTYPE html>
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script>
        document.cookie = "hello"
    </script>
</head>

<body onload=console.log(cookie)>
    <img src=broken onerror=console.log(cookie)>
</body>
</html>

上記のhtmlをローカルサーバーで配信して,ブラウザで開くと,bodyタグのonload属性で実行されるconsole.logではReferenceErrorが発生するのに対し,imgタグのonerror属性ではエラーが発生せず,コンソールにhelloの文字列が表示されます.

(ちなみに,onloadの方でdocument.cookieと記述すれば,コンソールにhelloと表示されます.)

勝手に補完されているから,と考えるのが妥当なのかなと思うのですが,ググったりリファレンスを見てもそれらしい記述が見当たりません.

上記の挙動について詳しい解説や仕様のソースをご存じの方はいらっしゃいませんでしょうか?

よろしくお願いします.

1

1Answer

HTML Standard の get the current value of the event handler あたりに書いてあります。

大まかにいうと、 onerror の値がスクリプト文字列なら funcion onerror (event) { } で囲い、 ECMAScript 仕様に定められた OrdinaryFunctionCreate 操作を用いて関数に変換します。このとき、

9. Let function be the result of calling OrdinaryFunctionCreate, with arguments:
...
scope
...
3. If eventHandler is an element's event handler, then set scope to NewObjectEnvironment(document, true, scope).
(Otherwise, eventHandler is a Window object's event handler.)

と書いてあるように、その関数の外側のスコープが document オブジェクトになるようにしています。つまり関数からは、document が持つプロパティが外側のスコープで定義された変数のように見えます。よって document.cookie は関数の中で cookie としてアクセスできます。

ただしこれは、条件に「If eventHandler is an element's event handler」と書いてあるとおり、要素のイベントハンドラについての話です。 onload のような Window オブジェクトに紐付くイベントハンドラは条件を満たさないため、 外側のスコープが document になることはありません。

4Like

Comments

  1. @laurel

    Questioner

    まさしく知りたかった情報です!
    `document`のプロパティが`onerror`の値の関数が作成されるときに,スコープに展開されてるわけなんですね.
    また,そもそもonloadは要素に紐づく属性ではないってことですね.

    自分ではまったく見つからなかったので,とても助かりました!
    ありがとうございました

Your answer might help someone💌