コンテナータイミング 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 のサブセクションをマークし、そのセクションが 初めて描画されたときに performance entry を受け取ることができます。

この 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('Container painted:', entry.identifier,
                  'at', entry.startTime,
                  'size:', entry.size);
    }
  });
  observer.observe({ entryTypes: ["container"] });
</script>

この属性は、要素が文書に追加される前に設定するべきです(HTML 内で設定するか、JavaScript で設定する場合は 文書に追加する前に設定します)。属性を遡及的に設定しても、後続のイベントと将来の描画のみが捕捉されます。

3.1. サブツリーの無視

DOM ツリーの一部は、<containertiming-ignore> 属性を使用して無視できます:
<div containertiming="foobar">
  <main>...</main>
  <!-- Aside updates won't trigger container timing events -->
  <aside containertiming-ignore>...</aside>
</div>

4. 用語

コンテナールートとは、 Element のうち、containertiming 属性を持つものです。

無視されるサブツリーとは、 Element をルートとするサブツリーで、その要素が containertiming-ignore> 属性を持つものです。

描画済み領域とは、 最初に観測されて以降に蓄積された、コンテナールートの描画済み部分すべてを表す 領域(矩形の集合)です。

コンテナータイミング 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 Element? lastPaintedElement;
    readonly attribute Element? rootElement;
};

PerformanceContainerTiming includes PaintTimingMixin;
PerformanceContainerTiming オブジェクトには、次の関連概念があります:

entryType 属性の getter は、DOMString "container" を返さなければなりません。

name 属性の getter は空文字列を返さなければなりません。

duration 属性は 0 を返さなければなりません。

startTime 属性の getter は、thisrenderTime の値を返さなければなりません。

identifier 属性は、 thisidentifier の値を返さなければなりません。

intersectionRect 属性は、thisintersectionRect の値を返さなければなりません。

size 属性は、 thissize の値を返さなければなりません。

firstRenderTime 属性は、thisfirstRenderTime の値を返さなければなりません。

lastPaintedElement 属性は、thislastPaintedElement の値を返さなければなりません。

rootElement 属性は、 thisrootElement の値を返さなければなりません。

注: ユーザーエージェントは、削除されたコンテンツが メモリリークを引き起こさないように、container root records map を維持する必要があります。 特に、entry の寿命を Element への 弱ポインターに結び付けることができ、Element が 削除された後のある時点でそれらをクリーンアップできます。この map は Web 開発者に公開されないため、 これはガベージコレクションのタイミングを公開しません。

6. 処理モデル

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

6.1. 文書ごとの状態

Document について、ユーザーエージェントは container root records map を維持しなければなりません。これは コンテナールート Element から Container Timing Record オブジェクトへの対応付けです。

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

このセクションは、[DOM] 仕様が変更された後に削除されます。

ここでは、Element インターフェイスを次のように拡張します:

partial interface Element {
    [CEReactions] attribute DOMString containertiming;
    [CEReactions] attribute DOMString? containertimingIgnore;
};
containertiming 属性は、その要素を コンテナールートとして識別する DOMString です。その値は、対応する PerformanceContainerTiming entry 内の identifier になります。

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

6.3. Container Timing Record

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

Container Timing Record には、次の関連概念があります:
paint timing info paintTimingInfoDOMString identifier が与えられたとき、Container Timing Record を 作成するには、次の手順を実行します:
  1. record を新しい Container Timing Record とします。

  2. recordpaintTimingInfopaintTimingInfo に設定します。

  3. recordidentifieridentifier に設定します。

  4. record を返します。

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

[^containertiming^] content attribute を持つ Element が文書に接続されたとき:

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

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

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

6.5. Container Timing のための要素描画の処理

要素が描画され、ユーザーエージェントが container timing の更新を処理する必要があるとき、 Document documentpaint timing info paintTimingInfoElement element、および DOMRectReadOnly intersectionRect が与えられた場合、次の手順を実行します:
  1. elementcontainer timing に寄与しない場合、return します。

  2. containerRoot を、element が与えられたときの コンテナールート要素を 取得する結果とします。

  3. containerRoot が null の場合、return します。

  4. record を、documentcontainer root records map 内の containerRoot に対する entry とします。そのような entry が存在しない場合、 paintTimingInfocontainerRoot の [^containertiming^] content attribute の値が与えられたときの Container Timing Record を作成する結果を record に設定し、(containerRootrecord) を documentcontainer root records map に追加します。

  5. enclosingRectintersectionRect の最小包含矩形とします。

  6. documentcontainerRootelementenclosingRect、および paintTimingInfo が与えられたとき、 record について 最後の新規描画領域を更新する可能性を実行します。

  7. Document を、保留中の container timing 変更を持つものとしてマークします。

注: このアルゴリズムは、描画される各画像またはテキスト ノードに対して呼び出されます。intersection rectangle は、要素を target、viewport を root として intersection rect algorithm を使用し、visual viewport と交差させて 計算するべきです。テキストノードの場合、intersection rectangle は、所有されるテキストノードの集合内のすべてのテキストノードの border box を含む最小矩形を、visual viewport と交差させたものです。

6.6. Container Timing Entry の発行

Document document について container timing entry を発行するよう求められたとき、次の手順を実行します。 これは、すべての paint operation が処理された後、フレームごとに 1 回呼び出されるべきです:
  1. document が保留中の container timing 変更を持たない場合、return します。

  2. documentcontainer root records map における 各 containerRootrecord について、反復します:

    1. recordhasPendingChanges が false の場合、continue します。

    2. recordcontainerRoot が与えられたとき、 Container Timing entry を作成します。

    3. recordhasPendingChanges を false に設定します。

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

注: 描画された要素ごとに複数の entry を発行する場合がある 他の一部の paint timing API とは異なり、Container Timing は各 コンテナールートについて 描画済み領域を蓄積し、コンテナールートごと、フレームごとに最大 1 つの PerformanceContainerTiming entry を発行します。このバッチ化のアプローチはより効率的であり、コンテナーの描画状態を全体的に把握できます。

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

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

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

  3. parent が与えられたときの コンテナールート要素を取得する結果を返します。

6.8. Container Timing への寄与

Element は、次のすべてが true である場合、コンテナールートcontainer timing に寄与します:

Element element が、コンテナールート containerRoot の container timing に寄与するかどうかを 判定するには:
  1. element が null の場合、false を返します。

  2. element が shadow tree 内にある場合、false を返します。

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

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

  5. true を返します。

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

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

  2. element の [^containertiming^] content attribute が存在する場合、 element を返します。

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

  4. null を返します。

6.10. 最後の新規描画領域を更新する可能性

Container Timing Record record について、Document documentコンテナールート Element containerRootElement elementDOMRectReadOnly enclosingRect、および paint timing info paintTimingInfo が 与えられたとき、最後の新規描画領域を更新する可能性を実行するには、 次の手順を実行します:
  1. paintedRegionrecordpaintedRegion とします。

  2. paintedRegionenclosingRect を完全に含む場合、return します。

  3. recordpaintedRegionpaintedRegionenclosingRect の union に設定します。

  4. recordlastNewPaintedAreaPaintTimingInfopaintTimingInfo に設定します。

  5. recordlastNewPaintedAreaElementelement に設定します。

  6. recordhasPendingChanges を true に設定します。

  7. containerRoot の [^containertiming-ignore^] content attribute が存在する場合、return します。

  8. parentContainerRoot を、containerRoot が与えられたときの 親コンテナールート要素を取得する結果とします。

  9. parentContainerRoot が null の場合、return します。

  10. parentRecord を、documentcontainer root records map 内の parentContainerRoot に対する entry とします。そのような entry が 存在しない場合、paintTimingInfoparentContainerRoot の [^containertiming^] content attribute の値が与えられたときの Container Timing Record を作成する結果を parentRecord に設定し、(parentContainerRootparentRecord) を documentcontainer root records map に追加します。

  11. documentparentContainerRootelementenclosingRect、および paintTimingInfo が与えられたとき、 parentRecord について 最後の新規描画領域を更新する可能性を実行します。

注: このアルゴリズムは、サイズにかかわらず、描画済み領域への あらゆる変更を報告します。描画領域の 1 ピクセルの変更であっても、新しい PerformanceContainerTiming entry がキューに入れられます。小さな変更を除外したい開発者は、entry 間の size 値を比較することで、それを行うことができます。

6.11. Container Timing Entry の作成

Container Timing Record recordコンテナールート Element containerRoot が与えられたとき、Container Timing entry を作成するために、 ユーザーエージェントは次の手順を実行しなければなりません:
  1. entry を新しい PerformanceContainerTiming entry とし、次の値を持たせます:

  2. entry である PerformanceEntry をキューに入れます

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 Element? lastPaintedElement;
    readonly attribute Element? rootElement;
};

PerformanceContainerTiming includes PaintTimingMixin;

partial interface Element {
    [CEReactions] attribute DOMString containertiming;
    [CEReactions] attribute DOMString? containertimingIgnore;
};