1. はじめに
このセクションは規範的ではありません。
現在、HTMLVideoElement
を
ピクチャインピクチャウィンドウ(requestPictureInPicture())に表示するためのWeb
APIが存在します。このため、ウェブサイトはカスタムのピクチャインピクチャ体験(PiP)を提供する能力が制限されています。
この機能を拡張し、ウェブサイトが常に最前面に表示されるウィンドウ上で完全なDocument
を提供できるようにしたいと考えています。
この新しいウィンドウは、既存の open() メソッドを使って開かれる、同一オリジンの白紙ウィンドウに似ていますが、いくつかの違いがあります:
-
PiPウィンドウは他のウィンドウの上に浮かびます。
-
PiPウィンドウはオープニングウィンドウより長く存続することはありません。
-
ウェブサイトはPiPウィンドウの位置を設定できません。
-
PiPウィンドウは遷移できません(`window.history`や`window.location`を使って新しいドキュメントへ変更するとPiPウィンドウが閉じます)。
2. 依存関係
この仕様に記載されたIDL断片は、Web IDL仕様で定められた通り、適合するIDL断片として解釈される必要があります。[WEBIDL]
3. セキュリティに関する考慮事項
3.1. セキュアコンテキスト
このAPIは [SECURE-CONTEXTS] のみで利用可能です。
3.2. なりすまし
ユーザーエージェントは、DocumentPictureInPicture
ウィンドウ上に十分なUIを提供し、悪意のあるウェブサイトが他のウィンドウの上に表示される能力を乱用して他サイトやシステムUIのなりすましを防止することが求められます。
3.2.1. 位置指定
ユーザーエージェントは、ウェブサイトがウィンドウの位置を設定できないようにする必要があります。これにより、ウェブサイトが意図的にウィンドウを他ページのUIの一部と思わせる場所に配置することを防ぎます。特に、moveTo()
や moveBy()
APIは、ドキュメントピクチャインピクチャウィンドウでは無効化されなければなりません。
3.2.2. オリジンの可視性
ユーザーエージェントは、DocumentPictureInPicture
ウィンドウをどのオリジンが制御しているかを常にユーザーに明確に伝える必要があります。これにより、ユーザーはコンテンツの出所を認識できます。例えば、ユーザーエージェントはウィンドウのタイトルバーにウェブサイトのオリジンを表示することが考えられます。
3.2.3. 最大サイズ
ユーザーエージェントは、常に最前面に表示されるウィンドウでウェブサイトが画面全体を覆いユーザーをピクチャインピクチャウィンドウに閉じ込めることを防ぐため、ドキュメントピクチャインピクチャウィンドウの最大サイズを制限すべきです。これによりユーザーのデスクトップのなりすましも防止できます。
3.3. IFrame
このAPIは 最上位トラバーサブル でのみ利用できます。ただし、DocumentPictureInPicture
Window
には HTMLIFrameElement
を含めることができ、
クロスオリジンの HTMLIFrameElement
も利用可能です。
4. プライバシーに関する考慮事項
4.1. フィンガープリント
PiPウィンドウを閉じてから後で再度開いた場合、前回のPiPウィンドウのサイズや場所を再利用することでユーザー体験を向上できることがあります。しかし、ユーザーエージェントは異なるオリジン間でサイズや位置を再利用しないことが推奨されます。これは悪意のあるウェブサイトによるフィンガープリントの手段となる可能性があるためです。
5. API
[Exposed =Window ]partial interface Window { [SameObject ,SecureContext ]readonly attribute DocumentPictureInPicture documentPictureInPicture ; }; [Exposed =Window ,SecureContext ]interface :DocumentPictureInPicture EventTarget { [NewObject ]Promise <Window >requestWindow (optional DocumentPictureInPictureOptions = {});options readonly attribute Window window ;attribute EventHandler ; };onenter dictionary { [DocumentPictureInPictureOptions EnforceRange ]unsigned long long = 0; [width EnforceRange ]unsigned long long = 0;height boolean =disallowReturnToOpener false ;boolean =preferInitialWindowPlacement false ; }; [Exposed =Window ,SecureContext ]interface :DocumentPictureInPictureEvent Event {(constructor DOMString ,type DocumentPictureInPictureEventInit ); [eventInitDict SameObject ]readonly attribute Window ; };window dictionary :DocumentPictureInPictureEventInit EventInit {required Window ; };window
DocumentPictureInPicture
オブジェクトは、ウェブサイトが新しい常時最前面の Window
を作成・オープンできる他、その Window
の開閉に関するイベントをリッスンすることができます。
各Window
オブジェクトには documentPictureInPicture API
が関連付けられており、これは DocumentPictureInPicture
の新しいインスタンスが Window
と共に作成されます。
documentPictureInPicture ゲッターの手順:
-
this の documentPictureInPicture API を返す。
各DocumentPictureInPicture
オブジェクトには last-opened
window(初期値はnullで、requestWindow() メソッドの手順で設定される Window
オブジェクト)が関連付けられています。
window ゲッターの手順:
-
win を this の last-opened window とする。
-
win が
nullでなく、win の closed 属性がfalseなら、win を返す。 -
nullを返す。
requestWindow(options) メソッドの手順:
-
Document Picture-in-Picture support が
falseなら、"NotSupportedError"DOMExceptionをスローする。 -
this の relevant global object の navigable が 最上位トラバーサブル でない場合、"
NotAllowedError"DOMExceptionをスローする。 -
this の relevant global object の navigable の Is Document Picture-in-Picture 真理値が
trueの場合、"NotAllowedError"DOMExceptionをスローする。 -
this の relevant global object に transient activation がない場合、"
NotAllowedError"DOMExceptionをスローする。 -
options["
width"] が存在し0より大きく、options["height"] が存在しないか0の場合、RangeErrorをスローする。 -
options["
height"] が存在し0より大きく、options["width"] が存在しないか0の場合、RangeErrorをスローする。 -
Consume user activation を this の relevant global object で実行する。
-
win を this の last-opened window とする。win が
nullでなく、win の closed 属性がfalseなら、閉じる win の navigable を実行する。 -
必要に応じて、ユーザーエージェントは既存のピクチャインピクチャウィンドウを閉じることができる。
-
pip traversable を 新しい最上位トラバーサブルを作成 の結果とし、this の relevant global object の navigable の active browsing context と "_blank" を引数とする。
結果となるDocument
の URL は `about:blank` ですが、document base URL は requestWindow()
を呼び出した
イニシエータ側のURLとなります。通常の `about:blank` ポップアップでこの継承動作を実装していないブラウザもありますが、
ドキュメントピクチャインピクチャウィンドウでは仕様通りこの継承が行われるよう実装者に推奨します。そうしないと互換性問題が生じます。
-
pip traversable の active document の mode を this の relevant global object の associated Document の mode に設定する。
-
pip traversable の Is Document Picture-in-Picture 真理値を
trueに設定する。 -
options["
width"] が存在し0より大きい場合:-
必要に応じて、ユーザーに使いやすいウィンドウサイズになるよう、options["
width"] が大き過ぎる場合は丸めたり無視してもよい。 -
必要に応じて、pip traversable の active browsing context のウィンドウの左右の表示領域の距離を options["
width"] ピクセルに設定してもよい。
-
-
options["
height"] が存在し0より大きい場合:-
必要に応じて、ユーザーに使いやすいウィンドウサイズになるよう、options["
height"] が大き過ぎる場合は丸めたり無視してもよい。 -
必要に応じて、pip traversable の active browsing context のウィンドウの上下の表示領域の距離を options["
height"] ピクセルに設定してもよい。
-
options["preferInitialWindowPlacement"]
が存在し真であれば、ユーザーエージェントはこの指示を使い、前回閉じた pip traversable ウィンドウの位置やサイズを考慮せず、
13・14のような動作を優先してもよい。
-
options["
disallowReturnToOpener"] が存在しtrueなら、ユーザーエージェントはピクチャインピクチャウィンドウ上で、ユーザーがオープナーウィンドウへ戻れるUI部品を表示しないようにすべきです。
動画およびドキュメントピクチャインピクチャどちらでも、ユーザーエージェントは元ページに戻りPiPウィンドウを閉じるためのボタンを表示することがよくあります。この操作は大抵は妥当ですが(特に動画PiPでは動画がメインドキュメントに戻るため)、ドキュメントピクチャインピクチャウィンドウでは必ずしも妥当とは限りません。disallowReturnToOpener
は、ウェブサイトがその体験に対しこの操作が妥当かどうかユーザーエージェントへ意思表示するヒントです。
-
pip traversable の active browsing context のウィンドウを他のウィンドウの上に浮かせるように設定する。
-
this の last-opened window を pip traversable の active window に設定する。
-
グローバルタスクをキューする を DOM 操作タスクソース で this の relevant global object で、イベントを発火し、名前は
enter、型はDocumentPictureInPictureEvent、window属性は pip traversable の active window で初期化。 -
pip traversable の active window を返す。
ウィンドウのサイズはウェブサイトが設定できますが、初期位置はユーザーエージェントが管理します。
enter-
DocumentPictureInPictureでPiPウィンドウが開かれた時に発火します。
6. 概念
6.1. ドキュメントピクチャインピクチャのサポート
各ユーザーエージェントは ドキュメントピクチャインピクチャサポート 真理値を持ち、その値は 実装依存(ユーザーの設定によって変化する場合がある)です。
6.2. DocumentPictureInPicture ウィンドウ
各最上位トラバーサブルは ドキュメントピクチャインピクチャかどうか 真理値を持ち、その値は初期状態でfalseですが、requestWindow()
メソッドの手順でtrueに設定されることがあります。
6.3. ドキュメントピクチャインピクチャウィンドウの閉じ方
close に十分な合意が得られたら統合すること。
close の手順2、 「toUnload に対してアンロードがユーザーキャンセルか判定した結果が true なら return」 を次のように修正する:
-
もし traversable のドキュメントピクチャインピクチャかどうか真理値が true ならこの手順をスキップする。それ以外の場合は、アンロードがユーザーキャンセルか判定 の結果が true なら return。
6.4. 既存のPiPウィンドウを閉じる
既存のピクチャインピクチャウィンドウを閉じるには:
-
ユーザーエージェントの 最上位トラバーサブル集合 の各 top-level traversable に対して:
-
もし top-level traversable のドキュメントピクチャインピクチャかどうか真理値が
trueなら、close top-level traversableを実行。 -
もし top-level traversable のactive documentのpictureInPictureElement が
nullでなければ、ピクチャインピクチャ終了アルゴリズムを top-level traversableのactive documentに対して実行。 -
top-level traversable のactive documentの子孫ナビゲーブル各 navigable に対して:
-
もし navigable のactive documentのpictureInPictureElement が
nullでなければ、ピクチャインピクチャ終了アルゴリズムを navigableのactive documentに対して実行。
-
-
6.5. PiPウィンドウは1つだけ
どの最上位トラバーサブルも同時に開いているドキュメントピクチャインピクチャウィンドウは最大1つでなければならない。最上位トラバーサブル でそのactive windowのdocumentPictureInPicture APIのlast-opened windowがnullでなければ、
さらにドキュメントピクチャインピクチャウィンドウを開こうとしたとき、ユーザーエージェントは既存のlast-opened windowをrequestWindow()メソッドの手順に従い閉じなければならない。
ただし、全最上位トラバーサブルでピクチャインピクチャモードのウィンドウがひとつだけ許可されるかどうかは、実装とプラットフォームによる。
そのため、すでに最上位トラバーサブルでドキュメントピクチャインピクチャかどうか真理値がtrueだったり
active documentのpictureInPictureElement
がnullでない場合にピクチャインピクチャ要求が来たらどうなるかは実装依存である。ユーザーエージェントは既存のピクチャインピクチャウィンドウを閉じる動作や
複数のピクチャインピクチャウィンドウを作成する動作もあり得る。
6.6. 元のドキュメントやPiPドキュメントが破棄された時にPiPウィンドウを閉じる
関連付けられたドキュメントピクチャインピクチャウィンドウを閉じる、与えられた
Document
documentに対して:
-
navigableをdocumentのnode navigableとする。
-
もしnavigableが最上位トラバーサブルでなければこれらの手順を中止。
-
もしnavigableのドキュメントピクチャインピクチャかどうか真理値が
trueなら close navigableを実行してこの手順を中止。 -
winをnavigableのactive windowのdocumentPictureInPicture APIのlast-opened windowとする。
destroy に十分な合意が得られたら統合すること。
destroy の最後に「ステップ10」を追加:
-
関連付けられたドキュメントピクチャインピクチャウィンドウを閉じる、与えられたdocumentに対して。
開いているドキュメントピクチャインピクチャウィンドウがあるページを閉じた時、そのPiPウィンドウも閉じることを保証するためです。
6.7. 元のドキュメントやPiPドキュメントが遷移した時にPiPウィンドウを閉じる
navigate に十分な合意が得られたら統合すること。
navigate のステップ16.3、 「Queue a global task on the navigation and traversal task source given navigable’s active window to abort navigable’s active document.」 の後ろにステップ16.4を挿入:
-
グローバルタスクをキューする を ナビゲーションとトラバーサルタスクソースで navigableのactive windowに対し、abort navigableのactive documentおよび関連付けられたドキュメントピクチャインピクチャウィンドウを閉じるを navigableのactive documentに対して実行。
-
もしnavigableが最上位トラバーサブルで、そのドキュメントピクチャインピクチャかどうか真理値が
trueならこれらの手順を中止。
開いているドキュメントピクチャインピクチャウィンドウがあるページを遷移した時、そのPiPウィンドウも閉じることを保証します。また、ドキュメントピクチャインピクチャウィンドウ内のドキュメントを遷移した時もPiPウィンドウが閉じられることを保証します。
6.8. PiPウィンドウのサイズ変更
ドキュメントピクチャインピクチャウィンドウをプログラムでサイズ変更することは便利ですが、常時最前面の特性のため、サイズ変更の自由度が高いと迷惑・侵襲的な使われ方をされるおそれがあります。 そのため、ウィンドウサイズ変更APIの利用にはユーザー操作を消費する形にして一部懸念を緩和します。
resizeTo()
に十分な合意が得られたら統合すること。
resizeTo()
のステップ3「targetがスクリプトによって生成された補助ブラウジングコンテキストでないなら return」の後ろに次の新手順を追加:
-
もし target の最上位トラバーサブルのドキュメントピクチャインピクチャかどうかが
trueなら:
resizeBy()
に十分な合意が得られたら統合すること。
resizeBy()
のステップ3「targetがスクリプトによって生成された補助ブラウジングコンテキストでないなら return」の後ろに次の新手順を追加:
-
もし target の最上位トラバーサブルのドキュメントピクチャインピクチャかどうかが
trueなら:
6.9. オープナーウィンドウへのフォーカス
ピクチャインピクチャウィンドウからオープナータブへ再フォーカスできると便利なことが多いです。例えばウィンドウが小さい場合ユーザー体験に合わない場面などが想定されます。focus()
APIを修正し、ピクチャインピクチャウィンドウからオープナーにフォーカスする時にシステムレベルのフォーカスも取得できるようにします。
focus()
に十分な合意が得られたら統合すること。
focus()
のステップ3「Run the focusing steps with current」の後ろに次の新手順を追加:
-
もし current が最上位トラバーサブルの場合:
-
pipWindowをcurrentのactive windowのdocumentPictureInPicture APIのlast-opened windowとする。
-
もしpipWindowが
nullでなく、pipWindowのrelevant global objectにtransient activationがあるなら:-
consume user activation を pipWindowのrelevant global objectで実行。
-
current にシステムフォーカスを与える。
-
-
オープナーへのシステムフォーカス付与は必ずしもドキュメントピクチャインピクチャウィンドウの閉鎖を意味する必要はありません。ウェブサイトがフォーカス後にPiPウィンドウを閉じたい場合は、close()
を利用できます。
6.10. CSS display-mode
CSS display-mode メディア特性 picture-in-picture により、Web開発者は(ウェブアプリの一部が)ピクチャインピクチャモードで表示されている時のみ適用されるCSSルールを記述できます。
6.11. ユーザーアクティベーションの伝播
ドキュメントピクチャインピクチャウィンドウの特性上、ウィンドウ内ボタンのイベントハンドラがオープナーのコンテキストで動作することがあります。 これにより、ウェブサイトがactivation consuming APIsを利用する際扱いづらくなります。 なぜなら、ドキュメントピクチャインピクチャウィンドウ側はtransient activationがある一方で、オープナーにはないことがあるためです。
これを容易にするため、activation notification手順を修正し、ドキュメントピクチャインピクチャウィンドウでユーザーアクティベーションを発生させた時にオープナーにも伝播させます。 さらにオープナーでアクティベーションが発生した際は、ドキュメントピクチャインピクチャウィンドウ内の同一オリジンフレームにも伝播させ、通常の子孫フレーム同様に活性化します。
activation notification手順に十分な合意が得られたら統合すること。
activation notificationのステップ4「windowsに active windowを追加、各子孫ナビゲーブルのactive windowのみ、ナビゲーブルのactive documentのオリジンがdocumentのオリジン と同一オリジンのみ」 の後ろに次の3ステップを追加:
-
もしdocumentのnode navigable の最上位トラバーサブル のドキュメントピクチャインピクチャかどうか真理値が
trueなら、 windowsに documentのnode navigableの最上位トラバーサブルのactive browsing contextのオープナーのブラウジングコンテキストのactive windowを追加。 -
document picture-in-picture window を document のnode navigable の最上位トラバーサブル のactive window のdocumentPictureInPicture API のlast-opened windowとする。
-
もし document picture-in-picture window が
nullでなければ、 windows に document picture-in-picture window の active windowを追加、ただし document picture-in-picture window の associated document の子孫ナビゲーブルで、ナビゲーブルのactive documentのオリジンが document picture-in-picture windowの associated document の オリジンと同一オリジンの場合のみ追加。
加えて、このアクティベーションが2箇所(オープナー・ピクチャインピクチャウィンドウ)で使われることのないよう正しく消費されることも保証する必要があります。そのため consume user activation の手順を修正し、ピクチャインピクチャ側のユーザーアクティベーションを消費する時にオープナー側も消費し、オープナー側のユーザーアクティベーションを消費する時に関連するピクチャインピクチャ側も消費するようにします。
consume user activation手順に十分な合意が得られたら統合すること。
consume user activation のステップ3「navigablesを inclusive descendant navigablesで定義」の後ろに次の3ステップを追加:
-
もしtopのドキュメントピクチャインピクチャかどうか真理値が
trueなら navigablesに topのactive browsing contextのオープナーのブラウジングコンテキストのactive documentのinclusive descendant navigablesを追加。 -
document picture-in-picture window を top のactive window のdocumentPictureInPicture API のlast-opened windowとする。
-
もし document picture-in-picture window が
nullでなければ、 navigablesに document picture-in-picture window のassociated documentのinclusive descendant navigablesを追加。
7. 例
このセクションは規範的ではありません
7.1. 動画プレイヤーをPiPへ抽出する
7.1.1. HTML
< body > < div id = "player-container" > < div id = "player" > < video id = "video" src = "foo.webm" ></ video > <!-- プレーヤーの追加要素 --> </ div > </ div > < input type = "button" onclick = "enterPiP();" value = "PiPに入る" /> </ body >
7.1.2. JavaScript
// ピクチャインピクチャウィンドウのハンドル。 let pipWindow= null ; function enterPiP() { const player= document. querySelector( '#player' ); // ウィンドウサイズを適切に設定するため、width/heightを指定。 const pipOptions= { width: player. clientWidth, height: player. clientHeight, }; documentPictureInPicture. requestWindow( pipOptions). then(( pipWin) => { pipWindow= pipWin; // プレイヤーがPiPへ移行したことを示すコンテナのスタイル変更。 playerContainer. classList. add( 'pip-mode' ); // プレイヤーをPiPウィンドウへ追加。 pipWindow. document. body. append( player); // PiP終了イベント監視してプレイヤーを戻す。 pipWindow. addEventListener( 'pagehide' , onLeavePiP. bind( pipWindow), { once: true }); }); } // PiPウィンドウが閉じた時呼ばれる。 function onLeavePiP() { if ( this !== pipWindow) { return ; } // コンテナのPiPスタイルを除去。 const playerContainer= document. querySelector( '#player-container' ); playerContainer. classList. remove( 'pip-mode' ); // プレイヤーをメインウィンドウへ戻す。 const player= pipWindow. document. querySelector( '#player' ); playerContainer. append( player); pipWindow= null ; }
7.2. PiPウィンドウで要素にアクセスする
const video= pipWindow. document. querySelector( '#video' ); video. loop= true ;
7.3. PiPウィンドウでイベントをリッスンする
より良いピクチャインピクチャ体験のため、ウェブサイトではユーザー入力イベント(クリックなど)に反応するカスタムボタンやコントロールを実装することがよくあります。
const pipDocument= pipWindow. document; const video= pipDocument. querySelector( '#video' ); const muteButton= pipDocument. document. createElement( 'button' ); muteButton. textContent= 'ミュート切替' ; muteButton. addEventListener( 'click' , () => { video. muted= ! video. muted; }); pipDocument. body. append( muteButton);
7.4. PiPを終了する
ウェブサイト側でユーザーがウィンドウの閉じるボタンを押さなくても、DocumentPictureInPicture
のWindow
を閉じたい場合は、close() メソッドを利用できます:
// これでPiPウィンドウを閉じ、onLeavePiP()が実行されます。 // リスナー付き。 pipWindow. close();
7.5. PiPウィンドウが閉じる時に要素を取得する
PiPウィンドウを閉じる理由が何であれ(ウェブサイトが閉じる・ユーザーが閉じる)、要素をPiPウィンドウから元に戻したくなる場合がよくあります。これはpagehide
イベントのハンドラで実装可能です。上記動画プレイヤー例のonLeavePiP()でも示されています:
// PiPウィンドウが閉じた時呼ばれる。 function onLeavePiP() { if ( this !== pipWindow) { return ; } // コンテナのPiPスタイルを除去。 const playerContainer= document. querySelector( '#player-container' ); playerContainer. classList. remove( 'pip-mode' ); // プレイヤーをメインウィンドウへ戻す。 const player= pipWindow. document. querySelector( '#player' ); playerContainer. append( player); pipWindow= null ; }
7.6. PiPウィンドウをプログラムでサイズ変更する
ドキュメントピクチャインピクチャウィンドウはresizeTo()
やresizeBy()
APIをサポートしていますが、PiPウィンドウ上でのユーザー操作が必要です:
const expandButton= pipWindow. document. createElement( 'button' ); expandButton. textContent= 'PiPウィンドウを拡張' ; expandButton. addEventListener( 'click' , () => { // PiPウィンドウの幅を20px、高さを30px拡張。 pipWindow. resizeBy( 20 , 30 ); }); pipWindow. document. body. append( expandButton);
7.7. オープナータブに戻る
focus()
APIを使えば、ピクチャインピクチャウィンドウからオープナータブにフォーカスを移動でき(要ユーザー操作):
const returnToTabButton= pipWindow. document. createElement( 'button' ); returnToTabButton. textContent= 'オープナータブに戻る' ; returnToTabButton. addEventListener( 'click' , () => { window. focus(); }); pipWindow. document. body. append( returnToTabButton);
7.8. CSSピクチャインピクチャディスプレイモードの使用例
次の例は、PiPウィンドウ内の body 要素のマージンを除去し、タイトルのフォントサイズを小さくしてコンテンツをウィンドウにフィットさせる方法を示します:
@media all and( display-mode: picture-in-picture) { body{ margin : 0 ; } h1{ font-size : 0.8 em ; } }
7.9. 戻るボタンの非表示
多くのユーザーエージェントは、動画やドキュメントピクチャインピクチャウィンドウでオープナーに戻ってウィンドウを閉じるボタンを表示しますが、これは一部のウェブサイトのドキュメントピクチャインピクチャ体験では適していない場合もあります。disallowReturnToOpener
オプションでこのボタンを非表示にできます。
await documentPictureInPicture. requestWindow({ disallowReturnToOpener: true });
7.10. 初期ウィンドウ配置の優先
ドキュメントピクチャインピクチャウィンドウは開いている間にユーザーがサイズ変更や再配置する場合があります。閉じてから再度開いた時、ユーザーエージェントは前回の位置・サイズをヒントとして使い、ウィンドウをデフォルト位置以外に配置する場合もあります。
前回のウィンドウ位置・サイズを使って欲しくない場合、preferInitialWindowPlacement
をtrueに指定してヒントを出すことができます。例えば、新規の活動用に新しいPiPウィンドウを開く場合などです。これによりユーザーエージェントはデフォルト位置やサイズ、あるいはサイトが指定したサイズヒント通りに表示する場合があります。
await documentPictureInPicture. requestWindow({ preferInitialWindowPlacement: true });
8. 謝辞
Frank Liberato、Mark Foltz、Klaus Weidner、François Beaufort、Charlie Reis、Joe DeBlasio、Domenic Denicola、Yiren Wang各氏の意見や貢献、また本ドキュメントと議論に寄せられた知見に感謝します。