コンテナータイミング API

コミュニティグループ報告書草案,

このバージョン:
https://WICG.github.io/container-timing/
テストスイート:
https://github.com/web-platform-tests/wpt/tree/master/container-timing
課題追跡:
GitHub
編集者:
Jason Williams (Bloomberg)
(Igalia)

概要

この仕様は、DOM の注釈付けされたセクションが画面に表示され、その初回描画が完了した時点を監視できる API を定義します。

この文書のステータス

この仕様は、Web Platform Incubator Community Group によって公開されました。 これは W3C 標準ではなく、W3C 標準化過程上のものでもありません。 W3C Community Contributor License Agreement (CLA) の下では、限定的なオプトアウトおよびその他の条件が適用されることに注意してください。 W3C Community and Business Groups について詳しく学ぶ。

1. はじめに

Container Timing API を使用すると、DOM の注釈付きセクションが画面に表示され、最初の描画が 完了した時点を監視できます。開発者は、[^containertiming^] 属性(Element Timing API の elementtiming と同様)を使用して DOM のサブセクションをマークし、そのセクションが初めて描画されたときに パフォーマンスエントリーを受け取ることができます。

この API により、開発者はページ内のさまざまなコンポーネントのタイミングを測定できます。開発者が アプリケーションをコンポーネントとして構成することが増えるにつれ、アプリケーションまたは Web ページの サブセクションにおけるパフォーマンスを測定したいという需要が高まっています。

Element Timing とは異なり、DOM のセクションが描画を完了した時点をレンダラーが知ることはできません (将来の変更、新しい画像に対する非同期リクエスト、読み込みの遅いボタンなどが存在し得るため)。 そのため、この API は、更新があったときに PerformanceEntry オブジェクトの形式で候補を発行します。

2. 動機

開発者は、テーブル、ウィジェット、その他のコンポーネントなど、DOM のサブセクションがいつ描画されたかを 測定し、描画時間を追跡して分析に送信できるようにしたいと考えています。現在の Web API はこれを十分には サポートしていません:

Web 作者は自分のドメインを誰よりもよく理解しており、自分たちのコンテンツブロックのパフォーマンスを、 ユーザーや組織が理解できる方法で伝えたいと考えています(例: "time to first tweet")。

2.1. ライフサイクル

このライフサイクルの例では、コンポーネントは異なる時点で複数のコンテンツ片を描画し、それぞれの時点で 更新された情報を含む新しい PerformanceContainerTiming entry が生成されます。

ただし、いったん領域が描画されると、その同じ領域の後続の描画によって新しい entry は生成されません。 Container Timing ライフサイクル図

3. 使用例

次の例は、コンテナールートを登録し、その描画タイミングを監視する方法を示します。

登録は、[^containertiming^] 属性を使用して要素ごとに行われます:
<div containertiming="foobar">
  <main>...</main>
  <aside>...</aside>
</div>

<script>
  const observer = new PerformanceObserver((list) => {
    let perfEntries = list.getEntries();
    for (const entry of perfEntries) {
      console.log('コンテナーが描画されました:', entry.identifier,
                  '時刻', entry.startTime,
                  'サイズ:', entry.size);
    }
  });
  observer.observe({ entryTypes: ["container"] });
</script>

この属性は、要素が文書に追加される前に設定する必要があります(HTML 内で設定するか、 JavaScript で設定する場合は、文書に追加する前に設定します)。この属性を遡及的に設定した場合は、 それ以降のイベントと将来の描画のみが取得されます。

3.1. サブツリーの無視

DOM ツリーの一部は、[^containertimingignore^] 属性を使用して無視できます:
<div containertiming="foobar">
  <main>...</main>
  <!-- aside の更新はコンテナータイミングイベントを発生させません -->
  <aside containertimingignore>...</aside>
</div>

4. 用語

コンテナルートとは、 [^containertiming^] 属性を持つ HTMLElement である。

無視されるサブツリーとは、 [^containertimingignore^] 属性を持つ HTMLElement を根とするサブツリーである。

ペイント済み領域とは、 コンテナルートが最初に観測されて以降に蓄積された、ペイントされたすべての部分を表す領域(矩形の集合)であり、 CSS ピクセルで表される。ペイント済み領域はビューポート座標空間で維持される。コンテナルート要素が 移動した場合(例:レイアウトの変更または moveBefore() による場合)、 以前に蓄積された矩形は調整されない — 領域はビューポート座標内で拡大し続ける。

コンテナタイミング APIは、コンテナルートが画面にペイントされた時点に関するタイミング情報を提供する。

5. PerformanceContainerTiming インターフェイス

[Exposed=Window]
interface PerformanceContainerTiming : PerformanceEntry {
    readonly attribute DOMString identifier;
    readonly attribute DOMRectReadOnly intersectionRect;
    readonly attribute unsigned long long size;
    readonly attribute DOMHighResTimeStamp firstRenderTime;
    readonly attribute HTMLElement? lastPaintedElement;
    readonly attribute HTMLElement? rootElement;
};

PerformanceContainerTiming includes PaintTimingMixin;

注記: intersectionRectの 座標およびsizeは CSS ピクセル(sizeの場合は平方 CSS ピクセル)で表現され、 ペイント済み 領域の座標空間および交差矩形アルゴリズムによって生成される単位と一致する。

PerformanceContainerTiming オブジェクトには、次の関連付けられた概念がある。

entryType 属性のゲッターは、DOMString "container" を返さなければならない。

name 属性のゲッターは、空文字列を返さなければならない。

duration 属性は 0 を返さなければならない。

startTime 属性のゲッターは、thisrenderTime の値を返さなければならない。

identifier 属性は、 thisidentifier の値を返さなければならない。

intersectionRect 属性は、thisintersectionRect の値を返さなければならない。

size 属性は、 thissize の値を返さなければならない。

firstRenderTime 属性は、thisfirstRenderTime の値を返さなければならない。

lastPaintedElement 属性は、thislastPaintedElement の値を返さなければならない。

rootElement 属性は、 thisrootElement の値を返さなければならない。

注記: ユーザーエージェントは、削除されたコンテンツによって メモリリークが発生しないように、コンテナルートレコードマップを維持する必要がある。特に、エントリーの存続期間を HTMLElement への弱いポインターに 結び付けることで、HTMLElement が 削除された後のいずれかの時点で、それらをクリーンアップできる。このマップはウェブ開発者に公開されないため、 ガベージコレクションのタイミングが公開されることはない。

6. 処理モデル

注: Container Timing API を実装するユーザーエージェントは、 "container"supportedEntryTypes に含める必要があります。これは Window コンテキスト向けです。 これにより、開発者は container timing のサポートを検出できます。

6.1. 文書ごとの状態

Document について、ユーザーエージェントは、コンテナルートである HTMLElementContainer Timing Record オブジェクトに対応付ける、コンテナルートレコードマップを維持しなければならない。

6.2. HTMLElement インターフェイスの拡張

この節は、[DOM] 仕様が修正され次第、削除される。

HTMLElement インターフェイスを次のように拡張する。

partial interface HTMLElement {
    [CEReactions, Reflect] attribute DOMString containerTiming;
    [CEReactions, Reflect] attribute boolean containerTimingIgnore;
};
containerTiming 属性は、要素をコンテナルートとして識別する DOMString である。その値は、対応する PerformanceContainerTiming エントリーの identifier となる。

containerTimingIgnore 属性は、存在する場合、 要素とその子孫を、祖先のコンテナルートに対するコンテナタイミング測定に寄与すべきではない無視されるサブツリーとしてマークする。

6.3. Container Timing Record

この仕様は、処理モデルで使用される内部データ構造を定義します:

コンテナタイミングレコードには、次の関連付けられた 概念がある。
描画タイミング情報 paintTimingInfoDOMString identifier が与えられたときに、コンテナー タイミングレコードを作成するには、次の手順を実行します:
  1. record を新しい コンテナータイミングレコードとします。

  2. recordpaintTimingInfopaintTimingInfo に設定します。

  3. recordidentifieridentifier に設定します。

  4. record を返します。

6.4. コンテナールートの登録

[^containertiming^] コンテンツ属性を持つ HTMLElement が文書に接続されたとき:

  1. ユーザーエージェントは、その要素を コンテナールートとして登録しなければなりません。

  2. ユーザーエージェントは、コンテナールートに対して空の 描画領域を初期化しなければなりません。

  3. ユーザーエージェントは、無視されるサブツリーを除き、コンテナールートのサブツリー内のすべての 描画操作を追跡しなければなりません。

6.5. containertiming 属性の削除

[^containertiming^] コンテンツ属性が HTMLElement element から削除されたとき、次の手順を実行する。
  1. documentelementノード文書とする。

  2. documentコンテナルートレコードマップelement のエントリーが 含まれている場合、そのエントリーを削除する。

注: [^containertiming^] 属性が後で同じ要素に 再度追加された場合、次の描画時に新しい コンテナータイミングレコードが 作成されます。描画領域は新たに開始され、以前の描画データは保持されません。

6.6. コンテナールートの切断

コンテナルートである HTMLElement element が文書から切断されたとき、次の手順を実行する。
  1. documentelementノード文書とする。

  2. documentコンテナルートレコードマップelement のエントリーが 含まれている場合、そのエントリーを削除する。

注: 要素が [^containertiming^] 属性を引き続き 持ったまま文書に再接続された場合、新しい コンテナールートの登録として扱われます。次の描画時に、新しい コンテナータイミングレコードが、新しい 描画領域とともに作成されます。

6.7. コンテナータイミングのために描画された要素を処理する

要素がペイントされ、ユーザーエージェントがコンテナタイミングの更新を処理する必要があるとき、Document documentペイントタイミング情報 paintTimingInfoHTMLElement element、および DOMRectReadOnly intersectionRect が与えられた場合、次の手順を実行する。
  1. elementコンテナタイミングに寄与しない場合、返る。

  2. containerRoot を、element を与えてコンテナ ルート要素を取得する結果とする。

  3. containerRoot が null の場合、返る。

  4. record を、documentコンテナルート レコードマップにある containerRoot のエントリーとする。そのようなエントリーが存在しない場合、record を、paintTimingInfocontainerRoot の [^containertiming^] コンテンツ属性の値を与えてコンテナタイミングレコードを作成する結果に設定し、 その後、(containerRootrecord) を documentコンテナルートレコードマップに追加する。

  5. enclosingRectintersectionRect の最小外接矩形とする。

  6. documentcontainerRootelementenclosingRect、および paintTimingInfo を与えて、 record最後の新しいペイント済み領域を必要に応じて更新する

  7. Document に保留中のコンテナタイミング変更があるものとしてマークする。

注記: このアルゴリズムは、ペイントを行う各画像ノードまたはテキスト ノードに対して呼び出される。交差矩形は、要素を ターゲット、ビューポートをルートとして交差矩形アルゴリズムを使用して計算し、 ビジュアルビューポートとの交差を取る必要がある。テキストノードの場合、交差 矩形は、所有されるテキストノードの集合内のすべてのテキストノードのボーダーボックスを含む最小の矩形であり、ビジュアルビューポートとの交差を取ったものである。

6.8. コンテナータイミングエントリーを発行する

Document document の container timing エントリーを発行するよう求められた場合、次の手順を実行する。これは、すべてのペイント 操作が処理された後、フレームごとに 1 回呼び出されるべきである。
  1. document に保留中の container timing の変更がない場合、返る。

  2. documentcontainer root records mapcontainerRootrecord それぞれについて:

    1. recordhasPendingChanges が false の場合、継続する。

    2. recordcontainerRoot を指定して、Container Timing エントリーを作成する

    3. recordhasPendingChanges を false に設定する。

    4. recordlastNewPaintedAreaElement を null に設定する。

    5. recordlastNewPaintedAreaSize を 0 に設定する。

  3. Document を、保留中の container timing の変更がなくなったものとしてマークする。

注: 描画された要素ごとに複数のエントリーを発行することがある他の一部の描画タイミング API とは異なり、 Container Timing は各 コンテナールートの描画領域を蓄積し、 フレームごと、コンテナールートごとに最大で 1 つの PerformanceContainerTiming エントリーを発行します。このバッチ処理方式はより効率的であり、コンテナーの描画状態を包括的に把握できます。

6.9. 親コンテナールート Element の取得

HTMLElement element が与えられたときに、親 コンテナルート要素を取得するには、次の手順を実行する。
  1. parentelement の parentElement とする。

  2. parent が null の場合、null を返す。

  3. parent を与えてコンテナルート要素を取得する結果を返す。

6.10. コンテナータイミングへの寄与

HTMLElement は、以下のすべてが真である場合、コンテナルートコンテナタイミングに寄与する

HTMLElement elementコンテナルート containerRoot のコンテナタイミングに寄与するかどうかを判定するには、次の手順を実行する。
  1. element が null の場合、false を返す。

  2. element がシャドウツリー内にある場合、false を返す。

  3. elementcontainerRoot の子孫でない場合、false を返す。

  4. element無視されるサブツリー内にある場合、false を返す。

  5. true を返す。

6.11. コンテナールート Element の取得

HTMLElement element が与えられたときに、コンテナ ルート要素を取得するには、次の手順を実行する。
  1. element が null の場合、null を返す。

  2. element の [^containertiming^] コンテンツ属性が存在する場合、 element を返す。

  3. element の parentElement が null でない場合、element の parentElement を与えてコンテナ ルート要素を取得する結果を返す。

  4. null を返す。

6.12. 最後の新規描画領域を必要に応じて更新する

Container Timing Record record について、Document documentcontainer root である HTMLElement containerRootHTMLElement elementDOMRectReadOnly enclosingRect、および paint timing info paintTimingInfo が与えられたとき、 最後の新しいペイント領域を更新する可能性があるには、次の手順を実行する。
  1. paintedRegionrecordpaintedRegion とする。

  2. paintedRegionenclosingRect を完全に含む場合、返る。

  3. newPaintedArea を、paintedRegion にまだ 含まれていない enclosingRect の領域とする。

  4. recordpaintedRegion を、 paintedRegionenclosingRect の和集合に設定する。

  5. recordlastNewPaintedAreaPaintTimingInfopaintTimingInfo に設定する。

  6. newPaintedArearecordlastNewPaintedAreaSize より大きい場合:

    1. recordlastNewPaintedAreaElementelement に設定する。

    2. recordlastNewPaintedAreaSizenewPaintedArea に設定する。

  7. recordhasPendingChanges を true に設定する。

  8. containerRoot の [^containertimingignore^] content 属性が存在する場合、返る。

  9. parentContainerRoot を、containerRoot を指定して 親 container root 要素を取得する 結果とする。

  10. parentContainerRoot が null の場合、返る。

  11. parentRecord を、parentContainerRoot に対応する documentcontainer root records map 内のエントリーとする。そのようなエントリーが存在しない場合、 parentRecord を、paintTimingInfoparentContainerRoot の [^containertiming^] content 属性の値を指定して Container Timing Record を作成する 結果に設定し、 その後 (parentContainerRootparentRecord) を documentcontainer root records map に追加する。

  12. documentparentContainerRootelementenclosingRect、および paintTimingInfo が与えられた parentRecord について、最後の新しいペイント領域を更新する可能性があるを実行する。

注: lastPaintedElement は、1 回のレンダリングフレーム内で新たに描画された最大の領域に寄与した要素です。これにより、 実装固有の描画順序への依存を回避できます。lastPaintedElement は、それ自体を独立したパフォーマンス指標として使用するのではなく、大規模または複雑な コンテナールート(例えば、 テーブル)の更新を引き起こしているものを調査する開発者向けのデバッグ支援として意図されています。lastNewPaintedAreaSize は、各フレームの比較を新たに開始できるように、 エントリーが発行された後にリセットされます。

注: このアルゴリズムは、サイズにかかわらず描画 領域に対するすべての変更を報告します。描画領域が 1 ピクセルだけ変更された場合でも、新しい PerformanceContainerTiming エントリーがキューに追加されます。小さな変更を除外したい開発者は、エントリー間の size の値を比較することで除外できます。

6.13. コンテナータイミングエントリーの作成

コンテナタイミングレコード record およびコンテナルートである HTMLElement containerRoot が与えられたときに、コンテナタイミングエントリーを作成するには、ユーザーエージェントは次の手順を実行しなければならない。
  1. entryを、次のように設定された新しいPerformanceContainerTiming エントリとする:

  2. entryPerformanceEntryのキューに追加する

7. セキュリティとプライバシーに関する考慮事項

7.1. クロスオリジン制限

この API はクロスオリジン境界を尊重します:

7.2. 情報の露出

この API によって提供される情報の大部分は、既存の API によってすでに推定できます:

この API は次のものを公開しません:

7.3. タイミング攻撃

この API は DOMHighResTimeStamp を使用します。これは他の Performance API と同様に、セキュリティ目的で分解能の制限を受ける場合があります。

7.4. プライバシーに関する考慮事項

この API は次のことを行いません:

8. 謝辞

貴重なフィードバックと助言をくださった以下の方々に深く感謝します:

適合性

文書の 規約

適合要件は、 記述的な表明 および RFC 2119 用語の組み合わせによって表現されます。 規範的な部分におけるキーワード “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” は、RFC 2119 で説明されているとおりに解釈されます。 ただし、読みやすさのため、 この仕様では、これらの語がすべて大文字で現れるとは限りません。

この仕様のテキストはすべて規範的です。 ただし、明示的に非規範的と示されたセクション、例、および注記は除きます。 [RFC2119]

この仕様の例は、“for example” という語で導入されるか、 規範的なテキストから分離され、 class="example" によって次のように示されます:

これは参考例の例です。

参考注記は “Note” という語で始まり、 規範的なテキストから分離され、 class="note" によって次のように示されます:

注: これは参考注記です。

索引

この仕様で定義される 用語

参照により定義される 用語

参照文献

規範的参照文献

[DOM]
Anne van Kesteren. DOM Standard. Living Standard. URL: https://dom.spec.whatwg.org/
[GEOMETRY-1]
Sebastian Zartner; Yehonatan Daniv. Geometry Interfaces Module Level 1. URL: https://drafts.csswg.org/geometry/
[HR-TIME-3]
Yoav Weiss. High Resolution Time. URL: https://w3c.github.io/hr-time/
[HTML]
Anne van Kesteren; et al. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra Standard. Living Standard. URL: https://infra.spec.whatwg.org/
[PAINT-TIMING]
Ian Clelland; Noam Rosenthal. Paint Timing. URL: https://w3c.github.io/paint-timing/
[PERFORMANCE-TIMELINE]
Nicolas Pena Moreno. Performance Timeline. URL: https://w3c.github.io/performance-timeline/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. 1997年3月. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL Standard. Living Standard. URL: https://webidl.spec.whatwg.org/

参考参照文献

[INTERSECTION-OBSERVER]
Stefan Zager; Emilio Cobos Álvarez; Traian Captan. Intersection Observer. URL: https://w3c.github.io/IntersectionObserver/

IDL 索引

[Exposed=Window]
interface PerformanceContainerTiming : PerformanceEntry {
    readonly attribute DOMString identifier;
    readonly attribute DOMRectReadOnly intersectionRect;
    readonly attribute unsigned long long size;
    readonly attribute DOMHighResTimeStamp firstRenderTime;
    readonly attribute HTMLElement? lastPaintedElement;
    readonly attribute HTMLElement? rootElement;
};

PerformanceContainerTiming includes PaintTimingMixin;

partial interface HTMLElement {
    [CEReactions, Reflect] attribute DOMString containerTiming;
    [CEReactions, Reflect] attribute boolean containerTimingIgnore;
};