ECMAScript 仕様の連鎖生成規則2021年12月19日 23時58分

この記事は JavaScript アドベントカレンダーの 19 日目の分です。


JavaScript の言語仕様は ECMAScript として策定されています。ECMAScript の仕様書を読んでいくにあたって注意すべき点として、連鎖生成規則 (chain production) に対する挙動の記述が省略されているかもしれないということが挙げられます。筆者は当初このことに気づかず、「この生成規則に対する Runtime Semantics が定義されていないけど、どうなっているんだろう?」と悩みました。

連鎖生成規則とは、finally 節に対する生成規則

Finally :
finally Block

のように、生成規則の右辺に非終端記号がひとつだけ存在するものです。終端記号はいくつあっても (ひとつもなくても) 構いません。この場合、Finally 生成規則に対する Runtime Semantics は、その右辺に存在する非終端記号 Block に対する Runtime Semantics がそのまま呼び出されるというものになります。

HTML のフォーム送信データを書き換える2021年12月18日 22時28分

この記事は HTML アドベントカレンダーの 18 日目の分、兼 JavaScript アドベントカレンダーの 18 日目の分です。


HTML のフォーム送信処理が実行されるときに、JavaScript を使って送信データを書き換えるにはどうしたらよいでしょうか。まず思いつくのが submit イベント発生時にフォームコントロール要素の入力値 (value プロパティの値など) を書き換えることでしょう。別の手段として formdata イベントがあります。formdata イベントを利用すれば、フォームコントロール要素に手を加えずに送信データを書き換えることができます。

formdata イベントに紐づく FormDataEvent オブジェクトformData プロパティを持ち、その値はまさに今送信されようとしているデータを表した FormData オブジェクトとなっています。この FormData オブジェクトに対して appendsetdelete メソッドを呼び出すことで、送信されるデータを変更することができるのです。

以下の例では、フォームを送信する際に time というキーに対して現在日時を表す文字列が設定され、/search?q=keyword&time=2021-12-18T12%3A00%3A00.000Z といった URL に移動します。

<form action="/search"
      onformdata="event.formData.append('time', new Date().toISOString());">
  <p>
    <input type="search" name="q" aria-label="検索する語">
    <button type="submit">検索する</button>
  </p>
</form>

formdata イベントは、form 要素オブジェクトを引数にして FormData コンストラクタを呼び出したとき (new FormData(form)) にも (引数として渡された form 要素上で) 発生します。

HTML のフォーム送信に使われたボタンを判別する2021年12月16日 23時00分

この記事は HTML アドベントカレンダーの 16 日目の分、兼 JavaScript アドベントカレンダーの 16 日目の分です。


HTML のフォームには複数の送信ボタンを設置できます。ある送信ボタンを実行してフォームを送信すると、その送信ボタンの name 属性と (送信ボタンが button 要素なら) value 属性の値も送信データに含まれます。

どの送信ボタンを実行してフォームを送信したのか、JavaScript からは submit イベントに紐づく SubmitEvent オブジェクトsubmitter プロパティで判別できます。以下の例では、「公開する」または「削除する」ボタンを実行すると、JavaScript コンソールにそのボタンが出力されます。

<form
    method="post"
    action="/edit"
    onsubmit="console.log(event.submitter); return false;">
  <p>
    <button type="submit" name="publish" value="1">公開する</button>
    <button type="submit" name="delete" value="1">削除する</button>
  </p>
</form>

submitter プロパティが実装される前は、各ボタンの click イベントを基に、どのボタンが最後に実行されたのか記憶しておく必要がありました。そこからするとずいぶん楽になりましたね。

HTML 要素の innerText プロパティで要素が生成されうる2021年12月10日 11時13分

この記事は HTML アドベントカレンダーの 10 日目の分、兼 JavaScript アドベントカレンダーの 10 日目の分です。


HTML 標準では、HTML 文書を JavaScript などのプログラミング言語から扱うためのインターフェイスも定義しています。そのひとつが HTML 要素の innerText プロパティ、要素の内容を文字列として取得・設定するプロパティです。かつて Internet Explorer が独自に実装し、他の Web ブラウザも追従した結果として標準化されたものですね。

innerText プロパティの値の取得

innerText プロパティで取得できる値は、ブラウザにレンダリングされたようなテキスト内容となります。CSS で display: none; が指定された要素の内容は含まれませんし、display: block; が指定された要素の内容の前後には改行文字 (U+000A) が挿入されます。表のセル同士の間にはタブ文字 (U+0009) が挿入されます。

そのため、innerText プロパティの値を取得する際にはブラウザの描画処理、いわゆるリフローが走ることになります。スタイルを気にせず単に要素のテキスト内容を取得したいときは、innerText プロパティではなく textContent プロパティを使ったほうがよいでしょう。textContent プロパティの値の取得時にはリフローが走りません。

innerText プロパティの値の設定

innerText という名前からすると値の設定時には単なるテキストノードが生成されそうな気もしますが、HTML 要素が生成されることもあります。設定する値に改行文字が含まれるときは、その改行文字が br 要素に置換されるのです。

単に要素のテキスト内容を設定したいときは、innerText プロパティではなく textContent プロパティを使ったほうがよいでしょう。textContent プロパティの値の設定時には HTML 要素が生成されません。

参考文献

JavaScript の正規表現で複数文字からなる絵文字を扱えるようにする提案2021年12月04日 23時31分

この記事は JavaScript アドベントカレンダーの 4 日目の分です。


今やあちこちで使われている絵文字ですが、その中には 1 文字に見えるのに複数の文字 (符号位置) から構成されるものがあります。例えば「👨‍👩」という男女が並んだ絵文字は、U+1F468 MAN、U+200D ZERO WIDTH JOINER、U+1F469 WOMAN の 3 つの符号位置からなります。

JavaScript の正規表現でこのような絵文字にマッチさせようとすると正規表現パターンが長大になってしまいます。また、文字クラス [...] 内にこのような絵文字を記述すると、「U+1F468、U+200D、U+1F469 という符号位置の並び」ではなく「U+1F468、U+200D、U+1F469 のいずれかの符号位置」にマッチしてしまいます (/u フラグが有効な場合)。

これを解決するための提案が ECMAScript proposal: support properties of strings (a.k.a. “sequence properties”) in Unicode property escapes です。Unicode において符号位置の並びに対して定義されているプロパティを、正規表現パターンで扱えるようにしようというもので、2021 年 12 月現在は stage 2 となっています。

これが実現すれば、\p{RGI_Emoji} という正規表現パターンが「👨‍👩」という符号位置の並びにマッチするようになります。さらに、このパターンは文字クラス [...] の内部で使うこともできます。ひとつの文字クラスにマッチするのはひとつの符号位置 (/u フラグが無効な場合はひとつの符号単位) というこれまでの常識が覆されるのです。

個人的には、将来的に JavaScript 組み込みの機能で Unicode の書記素クラスタを扱えるようにならないかと期待しています。

参考文献