1. 序論
~pageが読込まれるに伴い, および利用者が読込まれた~pageとヤリトリする間、[ ~app, ~browser ]の両者とも,後で~browserにより実行されるような様々な~eventを~queueする — 例えば: ~UAは、 利用者の活動に基づいて入力~eventを~scheduleする / ~appは、 `requestAnimationFrame()$m 用の~callbackや他の~callback, 等々を~scheduleする。 ~queueされたこれらの~eventは、 ~browserにより 1 個ずつ~dequeueされ, 実行される。 ◎ As the page is loading and while the user is interacting with the page afterwards, both the application and browser queue various events that are then executed by the browser -- e.g. user agent schedules input events based on user’s activity, the application schedules callbacks for requestAnimationFrame and other callbacks, etc. Once in the queue, the browser dequeues these events one-by-one and executes them.
しかしながら,~taskには長い時間(複数の~frame)かかり得るものもあり、 それが起きた場合/とき, ~UI~threadは阻まれ,他のすべての~taskも阻まれる結果になり得る。 これは、 利用者からは[ 利用者~入力に対し~browserが応答-不能になり,~pageから “締め出される” ]ことにより,共通的に可視になる。 今日における~web上の不良な利用者~体験の大多数は、 それが~sourceにある: ◎ However, some tasks can take a long time (multiple frames) and if/when that happens, the UI thread may become blocked and block all other tasks as well. To the user, this is commonly visible as a "locked up" page where the browser is unable to respond to user input; this is a major source of bad user experience on the web today:
- “ヤリトリ可能になる時機” が遅延される: ◎ Delayed "time to Interactive":
- ~pageが読込まれる間,あるいは視覚的には完全に具現化されていても、 長い~taskは~main~thread†と~~連携することが多い — その結果、 利用者は~pageとヤリトリできなくなる。 よくある元凶として、 拙く設計された第三者-主体の内容が挙げられる。 ◎ while the page is loading, or even completely visually rendered, long tasks often tie up the main thread and prevent the user from interacting with the page. Poorly designed third-party content is frequently the culprit.
- 【† `~event~loopの処理@~WAPI#event-loop-processing-model$を遂行する~thread (`概略的な説明@https://developer.mozilla.org/docs/Glossary/Main_thread$)。 】
- 入力の待時間が~~長い/可変: ◎ High/variable input latency:
- ~criticalな利用者~対話~event (例: `tap^en, `click^en, `scroll^en, `wheel^en, 等々) は、 長い~taskの背後に~queueされ,即応しない — その結果、 利用者~体験は予測-不能になる。 ◎ critical user-interaction events (e.g. tap, click, scroll, wheel, etc.) are queued behind long tasks which yields janky and unpredictable user experience.
- ~event取扱いの待時間が~~長い/可変: ◎ High/variable event handling latency:
- 入力~同様、 ~event~callback(例: `onload^et ~event, 等々)の処理は, ~appの更新を遅延する。 ◎ like input, processing event callbacks (e.g. onload events, etc.) delay application updates.
- 即応しない[ ~animation/~scrolling ]: ◎ Janky animations and scrolling:
- 一部の[ ~animation/~scrolling ]は、 組成器と~main~threadとの間の協調を要求する — 長い~taskが~main~threadを阻んでいる場合、[ ~animation/~scrolling ]の応答性に影響し得る。 ◎ some animation and scrolling interactions require coordination between compositor and main threads; if a long task is blocking the main thread it can affect responsiveness of animations and scrolling.
一部の~app (および `RUM@https://en.wikipedia.org/wiki/Real_user_monitoring$ ~vendor 【 `real user monitoring^en / “現実の利用者~体験の監視” 】 )は、 すでに, “長い~task” が起こる事例を識別して追跡しようと試みている。 一例として、 短い周期的な~timerを~installした上で,各~満了から次回の満了までに経過した時間を検分する~patternが知られている。 経過した時間が~timer周期を超えるならば、 1 個~以上の長い~taskが~event~loopの実行を遅延させた見込みが高いことになる。 この~approachは、 大体は働くが,いくつかの点で処理能に~~悪影響を及ぼす: ◎ Some applications (and RUM vendors) are already attempting to identify and track cases where "long tasks" happen. For example, one known pattern is to install a ~short periodic timer and inspect the elapsed time between the successive expirations: if the elapsed time is greater than the timer period, then there is high likelihood that one or more long tasks have delayed execution of the event loop. This approach mostly works but has several bad performance implications:\
- 長い~taskを検出するために~pollし続けることにより、 ~appが遊休~時に走らす~codeに割り当てられる “静止期間” が細切れになる ( `requestIdleCallback()$m を見よ)。 ◎ by polling to detect long tasks, the application prevents quiescence and long idle blocks (see requestIdleCallback);\
- ~batteryが短命になる。 ◎ it’s bad for battery life;\
- 何が遅延させているか知るすべが無い (例:当事者-主体, 第三者-主体 どちらの~codeか?)。 ◎ there is no way to know what is causing the delay (e.g. first party or third party code).
`RAIL@https://developers.google.com/web/fundamentals/performance/rail$ ( `Response Animation Idle Load^en )処理能~modelから、[ ~appは,利用者~入力に対し 100ms 以内に応答するべきである ]と示唆されている (~touchによる移動-や~scrollingにおいては 16ms 以内)。 この~APIの目標は、 この~~目的に抵触し得る~taskについての通知を表面化することである。 この~APIは、 50ms 以上かかる~taskを表面化する。 そのような~taskを伴わない~web~siteならば、 利用者~入力に対し — それを受信した時点で実行-中な~taskが完遂するまで 50ms 未満, それに反応する~taskを実行するのも 50ms 未満になるので — 100ms 以内に応答することになるはずである。 ◎ The RAIL performance model suggests that applications should respond to user input in less than 100ms (for touch move and scrolling, the threshold is 16ms). The goal of this API is to surface notifications about tasks that may prevent the application from hitting these targets. This API surfaces tasks that take 50ms or more. A website without these tasks should respond to user input in under 100ms: it will take less than 50ms to finish the task that is being executed when the user input is received and less than 50ms to execute the task to react to such user input.
1.1. 用例
const %observer = new PerformanceObserver(function(%list) { for (const %entry of %list.getEntries()) { /* 長い~task通知を処理する:解析と監視~用に報告する… ◎ Process long task notifications: report back for analytics and monitoring ... */ } }); /* これまで, および未来における長い~taskの通知~用に,観測器を登録する ◎ Register observer for previous and future long task notifications. */ %observer.observe({type: "long-animation-frame", buffered: true}); /* 以降,長い~script実行が生じたときは、 観測器にて `long-animation-frame^l ~entryが~queueされ,受信されるようになる。 ◎ Long script execution after this will result in queueing and receiving "long-animation-frame" entries in the observer. */ /* これまで, および未来における長い~animation~frameの通知~用に観測器を登録する。 以降, ~main~threadが長い期間~多忙な所では、 観測器にて `long-animation-frame^l ~entryが~queueされ,受信されるようになる。 ◎ Register observer for previous and future long animation frame notifications. After this, long periods where the main thread is busy will result in queueing and receiving "long-animation-frame" entries in the observer. */ %observer.observe({type: "long-animation-frame", buffered: true});
1.2. 長い~animation~frameと長い~taskの違い
`長い~task$も, `長い~animation~frame$も,輻輳や非即応性( `jank^en )を測定するが、 長い~animation~frameは, この種の輻輳を利用者が どう知覚するかに もっと相関する情報を供する — 長い~animation~frameは、 ~main~threadが遊休になったときから[ 当の~frameが描画されるか,~UAが描画するものは何も無いと裁定する ]ときまでを成す ある `sequence^en を測定するので。 ◎ While both long tasks and long animation frames measure congestion and jank, long animation frames provide information that has a better correlation with how user preceive this type of congestion. That’s because long animation frames measure a sequence that begins when the main thread is idle, and end when the frame either renders or the user agents decides there is nothing to render.
`~task$には、 実装の詳細に委ねられる部分がある。 この仕様が追加する長い~animation~frame用の~APIは、 それを補償するよう試みる — 同じ[ ~main~threadの[ 輻輳/非即応性 ]を成す現象 ]に関して,もっと利用者~中心な計量を導入することにより。 ◎ The task term is somewhat of an implementation detail, and the long animation frame addition attempts to remedy that by introducing a more user-centric metric of the same phenomenon of main thread congestion/jank.
長い~animation~frameは, 1 回の描画~相にかかる最大を有することが保証されるので、 描画~相~自体について追加的な情報を公開するためにも利用できる — `renderStart$m や `styleAndLayoutStart$m など。 ◎ Because long animation frames are guaranteed to have a maximum of one rendering phase, we can also use them to expose additional information about the rendering phase itself, such as renderStart and styleAndLayoutStart.
【この訳に特有な表記規約】
◎表記記号ms は、 ミリ秒単位( `milliseconds^en )を表す。
2. 長い~animation~frameの計時
`長い~animation~frame@ とは、[ `描画を更新する手続き$で描画を更新することが必要yあり得る`~task$ ]のうち,[ 必要yでないものは,そのことが判明するまで/ 必要yであるものは,当の~taskの終了まで ]の所要時間が 50ms を超過するものを指す。 ◎ A long animation frame refers to any of the following occurrences whose duration exceeds 50ms: • A task, after which updating the rendering is not necessary. • A task after which updating the rendering is necessary, up until rendering is updated.
長い~animation~frameの計時は、 この節に与える新たな~interfaceを孕む。 ◎ Long Animation Frame timing involves the following new interfaces:
2.1. `PerformanceLongAnimationFrameTiming^I ~interface
[`Exposed$=Window]
interface `PerformanceLongAnimationFrameTiming@I : `PerformanceEntry$I {
/*
`PerformanceEntry$I の~memberを多重定義する:
◎
Overloading PerformanceEntry
*/
readonly attribute `DOMHighResTimeStamp$I `startTime$m1;
readonly attribute `DOMHighResTimeStamp$I `duration$m1;
readonly attribute `DOMString$ `name$m1;
readonly attribute `DOMString$ `entryType$m1;
readonly attribute `DOMHighResTimeStamp$I `renderStart$m;
readonly attribute `DOMHighResTimeStamp$I `styleAndLayoutStart$m;
readonly attribute `DOMHighResTimeStamp$I `blockingDuration$m;
readonly attribute `DOMHighResTimeStamp$I `firstUIEventTimestamp$m;
[`SameObject$] readonly attribute `FrozenArray$<`PerformanceScriptTiming$I> `scripts$m;
[`Default$] `object$ `toJSON@m1();
};
各 `PerformanceLongAnimationFrameTiming$I ~objは、 `計時~報@ を有する — それは、 `~frame計時~報$である。 ◎ A PerformanceLongAnimationFrameTiming has a frame timing info timing info.
【 以下で利用される`相対的な高分解能~時刻$が返す`所要時間$には,特定の単位は含意されないが、 この仕様においては,常に `DOMHighResTimeStamp$I と同じ ms 単位であると見做される。 】
`blockingDuration@m 取得子~手続きは: ◎ The blockingDuration attribute’s getter steps are:
- %~sort済み~task所要時間~群 ~LET `~listを降順に~sortする$( `計時~報$の`~task所要時間~群$ftI ) ◎ Let sortedTaskDurations be timing info's task durations, sorted in descending order.
-
~IF[ コレの`計時~報$の`描画~更新の開始~時刻$ftI ~NEQ 0 ]: ◎ If this's timing info's update the rendering start time is not zero, then:
- %描画-所要時間 ~LET `所要時間を得る$( ↓ ) ⇒# コレの `renderStart$m が返す値, `相対的な高分解能~時刻$( コレの`計時~報$の`終了~時刻$ftI ) ◎ Let renderDuration be the duration between this's renderStart and the relative high resolution time given this's timing info's end time.
-
%~sort済み~task所要時間~群[ 0 ] ~INCBY %描画-所要時間 ◎ Increment sortedTaskDurations[0] by renderDuration.
注記: これは、 最も長い~task所要時間に対しては,【それ自体ではなく】[ それに描画-所要時間を加えた結果 ]が 50ms を超える場合に[ 他を阻んだものと見なされる ]ようにする。 ◎ Note: This makes it so that the longest task duration + render duration would be considered blocking if their total duration is >50ms.
- %他を阻んだ所要時間の合計 ~LET 0 ◎ Let totalBlockingDuration be 0.
- %~sort済み~task所要時間~群 を成す ~EACH( %所要時間 ) に対し ⇒ ~IF[ %所要時間 ~GT 50 ] ⇒ %他を阻んだ所要時間の合計 ~INCBY %所要時間 ~MINUS 50 ◎ For each duration in sortedTaskDurations, if duration is greater than 50 then increment totalBlockingDuration by duration - 50.
- ~RET %他を阻んだ所要時間の合計 ◎ Return totalBlockingDuration.
`scripts@m 取得子~手続きは: ◎ The scripts attribute’s getter steps are:
- %~script群 ~LET 新たな`~list$ ◎ Let scripts be a list « ».
- %入口~window ~LET コレに`関連な大域~obj$ ◎ Let entryWindow be this’s relevant global object.
-
コレの`~frame計時~報$の`~script群$ftIを成す ~EACH( %~script報 ) に対し: ◎ For each scriptInfo in this's frame timing info's scripts:
- %~script~window ~LET %~script報 の`~window$stI ◎ Let scriptWindow be scriptInfo’s window.
- %~script~navigable ~LET %~script~window に`結付けられた文書$の`~node~navigable$ ◎ ↓
- %入口~navigable ~LET %入口~window に`結付けられた文書$の`~node~navigable$ ◎ ↓
- %~script~entry ~LET `新たな~obj$( `PerformanceScriptTiming$I, コレに`関連な~realm$ ) ◎ Let scriptEntry be a new PerformanceScriptTiming in this's relevant realm,\
- %~script~entry の`計時~報$psT ~SET %~script報 ◎ whose timing info is scriptInfo and\
-
%~script~entry の`~window帰属$psT ~SET ( %~script~navigable, %入口~navigable ) に応じて: ◎ whose window attribution is the value corresponding to the first matching statement:
- %~script~window ~EQ `undefined^jv ⇒ `other$swA ◎ scriptWindow is undefined • other
- %~script~window ~EQ %入口~window ⇒ `self$swA ◎ scriptWindow is entryWindow • self
- %~script~navigable ~IN %入口~navigable の`先祖~navigable群$ ⇒ `ancestor$swA ◎ entryWindow’s associated Document's node navigable's ancestor navigables contains scriptWindow’s associated Document's node navigable • ancestor
- %入口~navigable ~IN %~script~navigable の`先祖~navigable群$ ⇒ `descendant$swA ◎ scriptWindow’s associated Document's node navigable's ancestor navigables contains entryWindow’s associated Document's node navigable • descendant
- %入口~navigable の`~top-level辿可能$nav ~EQ %~script~navigable の`~top-level辿可能$nav ⇒ `same-page$swA ◎ entryWindow’s associated Document's node navigable's top-level traversable is scriptWindow’s associated Document's node navigable's top-level traversable • same-page
- 他の場合 ⇒ `other$swA ◎ Otherwise • other.
- %~script群 に %~script~entry を`付加する$ ◎ Append scriptEntry to scripts.
- ~RET %~script群 ◎ Return scripts.
2.2. `PerformanceScriptTiming^I ~interface
enum `ScriptInvokerType@I {
`classic-script@siT,
`module-script@siT,
`event-listener@siT,
`user-callback@siT,
`resolve-promise@siT,
`reject-promise@siT
};
enum `ScriptWindowAttribution@I {
`self@swA,
`descendant@swA,
`ancestor@swA,
`same-page@swA,
`other@swA
};
[`Exposed$=Window]
interface `PerformanceScriptTiming@I : `PerformanceEntry$I {
/*
`PerformanceEntry$I の~memberを多重定義する:
◎
Overloading PerformanceEntry
*/
readonly attribute `DOMHighResTimeStamp$I `startTime$m1;
readonly attribute `DOMHighResTimeStamp$I `duration$m1;
readonly attribute `DOMString$ `name$m1;
readonly attribute `DOMString$ `entryType$m1;
readonly attribute `ScriptInvokerType$I `invokerType$m;
readonly attribute `DOMString$ `invoker$m;
readonly attribute `DOMHighResTimeStamp$I `executionStart$m;
readonly attribute `DOMString$ `sourceURL$m;
readonly attribute `DOMString$ `sourceFunctionName$m;
readonly attribute `long long$ `sourceCharPosition$m;
readonly attribute `DOMHighResTimeStamp$I `pauseDuration$m;
readonly attribute `DOMHighResTimeStamp$I `forcedStyleAndLayoutDuration$m;
readonly attribute `Window$I? `window$m;
readonly attribute `ScriptWindowAttribution$I `windowAttribution$m;
[`Default$] `object$ `toJSON@m1();
};
各 `PerformanceScriptTiming$I には、 次に挙げるものが結付けられる: ◎ ↓
- `計時~報@psT ⇒ ある`~script計時~報$ ◎ A PerformanceScriptTiming has an associated script timing info timing info.
- `~window帰属@psT ⇒ ある `ScriptWindowAttribution$I ◎ A PerformanceScriptTiming has an associated ScriptWindowAttribution window attribution.
`invoker@m 取得子~手続きは: ◎ The invoker attribute’s getter steps are:
- %計時~報 ~LET コレの`計時~報$psT ◎ ↓
-
%計時~報 の`呼出元~種別$stI【!`invokerType$m】に応じて: ◎ Switch on this’s invokerType:
- `classic-script$siT/ `module-script$siT ⇒ ~RET %計時~報 の`~source~URL$stI ◎ "`classic-script`" "`module-script`" • Return this’s timing info's source url.
-
`event-listener$siT ◎ "`event-listener`"
- %~target名 ~LET « %計時~報 の`呼出元の名前$stI » ◎ Let targetName be this’s timing info's invoker name.
- ~IF[ %計時~報 の`~event~target要素の~ID$stI ~NEQ 空~文字列 ] ⇒ %~target名 に次を順に`付加する$ ⇒# `#^l, %計時~報 の`~event~target要素の~ID$stI ◎ If this’s timing info's event target element id is not the empty string, then: Set targetName to the concatenation of « targetName, "#", this’s timing info's event target element id ».
- ~ELIF[ %計時~報 の`~event~target要素の~src属性$stI ~NEQ 空~文字列 ] ⇒ %~target名 に次を順に`付加する$ ⇒# `[src=^l, %計時~報 の`~event~target要素の~src属性$stI, `]^l ◎ Otherwise, If this’s timing info's event target element src attribute is not the empty string, then: Set targetName to the concatenation of « targetName, '[src=', this’s timing info's event target element src attribute, ']' ».
- %~target名 に次を順に`付加する$ ⇒# `.on^l, %計時~報 の`~event型$stI ◎ Return the concatenation of « targetName, ".on", this's timing info's event type ».
- ~RET %~target名 を`連結する$ ◎ ↑
これはちょっと慣習に倣っただけに感じる — 名前の生成を論じる必要がある。 ◎ this feels a bit custom, need to discuss name generation.
- `user-callback$siT ⇒ ~RET %計時~報 の`呼出元の名前$stI ◎ "`user-callback`" • Return this’s timing info's invoker name.
-
`resolve-promise$siT / `reject-promise$siT : ◎ "`resolve-promise`" "`reject-promise`"
- ~IF[ %計時~報 の`呼出元の名前$stI ~EQ 空~文字列 ] ⇒ ~RET %計時~報 の`呼出元~種別$stI【!コレの`invokerType$m】に応じて ⇒# `resolve-promise$siT ならば `Promise.resolve^l / `reject-promise$siT ならば `Promise.reject^l ◎ If this’s timing info's invoker name is the empty string, then: • If this’s invokerType is "`resolve-promise`", then return "`Promise.resolve`". • Otherwise, return "`Promise.reject`".
- %結果 ~LET « `呼出元の名前$stI, `.^l » ◎ ↓
- %結果 に次を`付加する$ ⇒ %計時~報 の`呼出元~種別$stI【!`invokerType$m】 に応じて ⇒# `resolve-promise$siT ならば `then^l / `reject-promise$siT ならば `reject-promise^l ◎ Let thenOrCatch be "`then`" if invokerType is "`resolve-promise`"; otherwise "`reject-promise`".
- ~RET %結果 を`連結する$ ◎ Return the concatenation of « invoker name, ".", thenOrCatch ».
`executionStart@m 取得子~手続きは:
- %実行~開始~時刻 ~LET コレの`計時~報$psTの`実行~開始~時刻$stI
- ~IF[ %実行~開始~時刻 ~EQ 0 ] ⇒ ~RET 0
- ~RET `相対的な高分解能~時刻$( %実行~開始~時刻, コレに`関連な大域~obj$ )
`forcedStyleAndLayoutDuration@m 取得子~手続きは ⇒ ~RET 次を表現する`実装定義$な値 ⇒ ~styleと~layoutを — 例:[ `getComputedStyle()$m / `getBoundingClientRect()$m ]を~callすることにより — 同期的に遂行することに費やした時間 ◎ The forcedStyleAndLayoutDuration attribute’s getter step is to return an implementation-defined value that represents time spent performing style and layout synchronously, e.g. by calling getComputedStyle() or getBoundingClientRect().
これを[ 相互運用可能/規範的 ]にする仕方を見出す必要がある。 たぶん、 それらの関数を[ 同期的な~styleや~layoutを要求するものとして ]~Web~IDL内で~markするか? また、 それが解決されたなら,`計時~報$psTへ移動する。 ◎ Find a way to make this interoperable/normative. Perhaps mark those functions in WebIDL as requiring synchronous style/layout? Also move to timing info once that’s resolved.
`pauseDuration@m 取得子~手続きは ⇒ ~RET コレの`計時~報$psTの`静止-所要時間$stI ◎ The pauseDuration attribute’s getter step is to return this's timing info's pause duration.
`window@m 取得子~手続きは: ◎ The window attribute’s getter steps are:
- %~window ~LET コレの`計時~報$psTの`~window$stIに対し, `deref$c を~callした結果 ◎ Let window be the result of calling deref on this's timing info's window.
- ~IF[ %~window ~EQ `undefined^jv ] ⇒ ~RET ~NULL ◎ If window is undefined, then return null;\
- ~RET %~window ◎ Otherwise return window.
3. 処理~model
注記: 長い~animation~frame用の~APIを実装している~UAは、 `~window$が`~supportする~entry型~群$【!`supportedEntryTypes$m】に `long-animation-frame^l を含める必要がある。 ◎ Note: A user agent implementing the Long Animation Frame API would need to include "long-animation-frame" in supportedEntryTypes for Window contexts, respectively.
3.1. ~frame計時~報
`~frame計時~報@ は、 次に挙げる`~item$sctを有する`構造体$であり, 長い~animation~frame用の~algoにおいて内部状態管理に利用される: ◎ frame timing info is a struct used as a bookkeeping detail by the long animation frame algorithms. It has the following items:
- `開始~時刻@ftI ◎ start time
- `現在の~taskの開始~時刻@ftI ◎ current task start time
- `描画~更新の開始~時刻@ftI ◎ update the rendering start time
- `~styleと~layoutの開始~時刻@ftI ◎ style and layout start time
- `最初の~UI~event時刻印@ftI ◎ first ui event timestamp
- `終了~時刻@ftI ◎ end time
- いずれも,ある `DOMHighResTimeStamp$I — 初期~時は 0 とする。 ◎ A DOMHighResTimeStamp, initially 0.\
- 注記: いずれも,`安全でない~moment$【![=monotonic~clock/unsafe current time=|unsafe=]】なので、 ~APIを介して公開する際には,`時刻を粗化する$ベキである。 ◎ Note: all the above are [=monotonic clock/unsafe current time=|unsafe=], and should be coarsened when exposed via an API.
- `~task所要時間~群@ftI ◎ task durations
- `DOMHighResTimeStamp$I たちが成す`~list$ — 初期~時は空とする。 ◎ A list of DOMHighResTimeStamp, initially empty.
- `~script群@ftI ◎ scripts
- `~script計時~報$たちが成す`~list$ — 初期~時は空とする。 ◎ A list of script timing info, initially empty.
- `処理待ち~script@ftI ◎ pending script
- ~NULL / ある`~script計時~報$ — 初期~時は ~NULL とする。 ◎ Null or a script timing info, initially null.
`~script計時~報@ は、 次に挙げる`~item$sctを有する`構造体$である: ◎ script timing info is a struct. It has the following items:
- `呼出元~種別@stI ◎ invoker type
- ある `ScriptInvokerType$I ◎ A ScriptInvokerType.
- `開始~時刻@stI ◎ start time
- `終了~時刻@stI ◎ end time
- `実行~開始~時刻@stI ◎ execution start time
- `安全でない~moment$を表現する `DOMHighResTimeStamp$I — 初期~時は 0 とする。 ◎ An unsafe DOMHighResTimeStamp, initially 0.
- `静止-所要時間@stI ◎ pause duration
- 【!representing a number of milliseconds】 `DOMHighResTimeStamp$I — 初期~時は 0 とする。 ◎ A DOMHighResTimeStamp representing a number of milliseconds, initially 0.
- `呼出元の名前@stI ◎ invoker name
- `~source~URL@stI ◎ source url
- `~source関数~名@stI ◎ source function name
- `~event型@stI ◎ event type
- `~event~target要素の~ID@stI ◎ event target element id
- `~event~target要素の~src属性@stI ◎ event target element src attribute
- いずれも,ある文字列 — 初期~時は空~文字列とする。 ◎ A string, initially the empty string.
- `~source文字~位置@stI ◎ source character position
- ある整数 — 初期~時は −1 とする。 ◎ A number, initially -1.
- `~window@stI ◎ window
- ある `Window$I を指す ある `WeakRef$jt ◎ A WeakRef to a Window.
各`文書$は `現在の~frame計時~報@doc を有する — それは、[ ~NULL/`~frame計時~報$ ]であり, 初期~時は~NULLとする。 ◎ A Document has a null or frame timing info current frame timing info, initially null.
3.2. 長い~animation~frameを報告する
3.2.1. 長い ~animation~frameの監視-法
所与の ( `文書$ %文書 ) と `同一-生成元に属する最も近い根@ は: ◎ To get the nearest same-origin root for a Document document:
- %先祖~群 ~LET %文書 の`先祖~navigable群$ ◎ Let ancestors be the ancestor navigables of document.
- %先祖~群 を成す ~EACH( %先祖~navigable ) に対し ⇒ ~IF[ ( %先祖~navigable にて`作動中な文書$navの`生成元$doc, %文書 の`生成元$doc ) は`同一-生成元$である ]~AND[ %先祖~navigable にて`作動中な文書$navに`関連な~agent$ ~EQ %文書 に`関連な~agent$ ] ⇒ ~RET %先祖~navigable にて`作動中な文書$nav ◎ For each ancestorNavigable in ancestors: If ancestorNavigable’s active document's origin is same origin with document’s origin, and ancestorNavigable’s active document's relevant agent is document’s relevant agent, then return ancestorNavigable’s active document.
- ~RET %文書 ◎ Return document.
所与の ( `文書$ %文書 ) に `関連な~frame計時~報@ は ⇒ ~RET %文書 と`同一-生成元に属する最も近い根$の`現在の~frame計時~報$doc ◎ The relevant frame timing info for a Document document is its nearest same-origin root's current frame timing info.
`~task開始~時刻を記録する@ ときは、 所与の ( `DOMHighResTimeStamp$I %安全でない~task開始~時刻, `文書$ %文書 ) に対し: ◎ To record task start time given a DOMHighResTimeStamp unsafeTaskStartTime, and a Document document:
- %根 ~LET %文書 と`同一-生成元に属する最も近い根$ ◎ Let root be document’s nearest same-origin root.
- ~IF[ %根 の`現在の~frame計時~報$doc ~EQ ~NULL ] ⇒ %根 の`現在の~frame計時~報$doc ~SET 新たな`~frame計時~報$ — その ⇒# `開始~時刻$ftI ~SET %安全でない~task開始~時刻 ◎ If root’s current frame timing info is null, then set root’s current frame timing info to a new frame timing info whose start time is unsafeTaskStartTime.
- %計時~報 ~LET %根 の`現在の~frame計時~報$doc ◎ ↓
- %計時~報 の`現在の~taskの開始~時刻$ftI ~SET %安全でない~task開始~時刻 ◎ Set root’s current frame timing info's current task start time to unsafeTaskStartTime.
- ~IF[ %計時~報 の`開始~時刻$ftI ~EQ 0 ] ⇒ %計時~報 の`開始~時刻$ftI ~SET %安全でない~task開始~時刻 ◎ If root’s current frame timing info's 's start time is 0, then set root’s current frame timing info's start time to unsafeTaskStartTime.
`~task終了~時刻を記録する@ ときは、 所与の ( `DOMHighResTimeStamp$I %安全でない~task終了~時刻, `文書$ %文書 ) に対し: ◎ To record task end time given an DOMHighResTimeStamp unsafeTaskEndTime, and a Document document:
- %計時~報 ~LET %文書 に`関連な~frame計時~報$ ◎ Let timingInfo be document’s relevant frame timing info.
-
~IF[ %計時~報 ~EQ ~NULL ] ⇒ ~RET ◎ If timingInfo is null, then return.
注記: これは、 ~browserが当の `sequence^en の間に可視でなくなる場合に生じ得る。 ◎ Note: This can occur if the browser becomes hidden during the sequence.
- %安全な~task終了~時刻 ~LET `相対的な高分解能~時刻$( %安全でない~task終了~時刻, %文書 に`関連な大域~obj$ ) ◎ Let safeTaskEndTime be the relative high resolution time given unsafeTaskEndTime and document’s relevant global object.
- %安全な~task開始~時刻 ~LET `相対的な高分解能~時刻$( %計時~報 の`現在の~taskの開始~時刻$ftI, %文書 に`関連な大域~obj$ ) ◎ Let safeTaskStartTime be the relative high resolution time given timingInfo’s current task start time and document’s relevant global object.
- %計時~報 の`~task所要時間~群$ftIに次の結果を`付加する$ ⇒ `所要時間を得る$( %安全な~task開始~時刻, %安全な~task終了~時刻 ) ◎ Append the duration between safeTaskStartTime and safeTaskEndTime to timingInfo’s task durations.
-
~IF[ ~UAは、 %文書 の`~node~navigable$の描画を更新しても,可視な効果は無いものと予見する ] ⇒ `~frame計時を報告する$( %文書 )【!~RET】 ◎ If the user agent believes that updating the rendering of document’s node navigable would have no visible effect, then report frame timing given document and return.
注記: ここでは、 実際には視覚的な更新が不要であったとしても,`長い~animation~frame$を刻む — それが,ある無関係な視覚的~更新と同時に起こる局面においては、 それは,他を阻むことになるので。 ◎ Note: even though there was no actual visual update, we mark a long animation frame here because it would be blocking in a scenario where it coincided with an unrelated visual update.
`描画~時刻を記録する@ ときは、 所与の ( `文書$ %文書, `DOMHighResTimeStamp$I %安全でない~styleと~layoutの開始~時刻 ) に対し: ◎ To record rendering time given a Document document, and a DOMHighResTimeStamp unsafeStyleAndLayoutStart:
- %計時~報 ~LET %文書 に`関連な~frame計時~報$ ◎ Let timingInfo be document’s relevant frame timing info.
-
~IF[ %計時~報 ~EQ ~NULL ] ⇒ ~RET ◎ If timingInfo is null, then return.
注記: これは、 ~browserが当の `sequence^en の間に可視でなくなる場合に生じ得る。 ◎ Note: This can occur if the browser becomes hidden during the sequence.
- %計時~報 の`描画~更新の開始~時刻$ftI ~SET %計時~報 の`現在の~taskの開始~時刻$ftI ◎ Set timingInfo’s update the rendering start time to timingInfo’s current task start time.
- %計時~報 の`~styleと~layoutの開始~時刻$ftI ~SET %安全でない~styleと~layoutの開始~時刻 ◎ Set timingInfo’s style and layout start time to unsafeStyleAndLayoutStart.
- `~frame計時を報告する$( %文書, `安全でない共有される現在の時刻$ ) ◎ report frame timing given document and the unsafe shared current time.
`~frame計時を報告する@ ときは、 所与の ( `文書$ %文書, `DOMHighResTimeStamp$I %安全でない終了~時刻 ) に対し: ◎ To report frame timing given a Document document and a DOMHighResTimeStamp unsafeEndTime:
- %計時~報 ~LET %文書 に`関連な~frame計時~報$ ◎ Let timingInfo be document’s relevant frame timing info.
- ~Assert: %計時~報 ~NEQ ~NULL ◎ Assert: timingInfo is not null.
- %大域~obj ~LET %文書 に`関連な大域~obj$ ◎ Let global be document’s relevant global object.
- %~frame所要時間 ~LET `所要時間を得る$( ↓ ) ⇒# `相対的な高分解能~時刻$( %計時~報 の`開始~時刻$ftI, %大域~obj ), `相対的な高分解能~時刻$( %安全でない終了~時刻, %大域~obj ) ◎ Let frameDuration be the duration between the relative high resolution time given timingInfo’s start time and global, and the relative high resolution time given unsafeEndTime and global.
-
~IF[ %~frame所要時間 ~GT 50ms ]:
- %処理能~entry ~LET `新たな~obj$( `PerformanceLongAnimationFrameTiming$I, %文書 に`関連な~realm$ )
- %処理能~entry の`計時~報$ ~SET %計時~報
- `処理能~entryを~queueする$( %処理能~entry )
- %文書 と`同一-生成元に属する最も近い根$の`現在の~frame計時~報$doc ~SET ~NULL ◎ set document’s nearest same-origin root's current frame timing info to null.
3.2.2. 長い~scriptの監視-法
`利用元~callback用に計時~報を記録する@ ときは、 所与の ( `~callback関数$ %~callback, `環境~設定群~obj$ %設定群 ) に対し ⇒ `~script入口点を作成する$( %設定群, `user-callback^l, 次の手続き ) ◎ To record timing info for user callback given a callback function callback and an environment settings object settings: Create script entry point given settings, "`user-callback`", and\
手続きは、 所与の ( `~script計時~報$ %~script計時~報 ) に対し: ◎ the following steps given a script timing info scriptTimingInfo:
- %~script計時~報 の`呼出元の名前$stI ~SET %~callback の`識別子$ ◎ Set scriptTimingInfo’s invoker name to callback’s identifier.
- `~source所在を適用する$( %~script計時~報, %~callback ) ◎ Apply source location for scriptTimingInfo given callback.
`~timer~handler用に計時~報を記録する@ ときは、 所与の ( [ 文字列/ `Function$I ] %~handler, `環境~設定群~obj$ %設定群, 真偽値 %繰返すか ) に対し ⇒ `~script入口点を作成する$( %設定群, `user-callback^l, 次の手続き ) ◎ To record timing info for timer handler given a string or Function handler, an environment settings object settings, and a boolean repeat: Create script entry point given settings, "`user-callback`", and the following\
手続きは、 所与の ( `~script計時~報$ %~script計時~報 ) に対し: ◎ steps given a script timing info scriptTimingInfo:
- %呼出元の名前 ~LET « `TimerHandler:^l » ◎ ↓
- %呼出元の名前 に次を`付加する$ ⇒ %繰返すか に応じて ⇒# ~T ならば `setInterval^l / ~F ならば `setTimeout^l ◎ Let setTimeoutOrInterval be "setInterval" if repeat is true, "setTimeout" otherwise.
- %~script計時~報 の`呼出元の名前$stI ~SET %呼出元の名前 を`連結する$ ◎ Set scriptTimingInfo’s invoker name to concatenation of « TimerHandler:", setTimeoutOrInterval ».
- ~IF[ %~handler は `Function$I である ] ⇒ `~source所在を適用する$( %~script計時~報, %~handler ) ◎ If handler is a Function, then apply source location for scriptTimingInfo given handler.
`~event~listener用に計時~報を記録する@ ときは、 所与の ( `Event$I %~event, `EventListener$I %~listener ) に対し ⇒ `~script入口点を作成する$( %~listener に`関連な設定群~obj$, `event-listener^l, 次の手続き ) ◎ To record timing info for event listener given an Event event and an EventListener listener: Create script entry point given listener’s relevant settings object, "`event-listener`", and the following\
手続きは、 所与の ( `~script計時~報$ %~script計時~報, `~frame計時~報$ %~frame計時~報 ) に対し: ◎ steps given a script timing info scriptTimingInfo and a frame timing info frameTimingInfo:
- %~script計時~報 の`~event型$stI ~SET %~event の `type@~DOM4#dom-event-type$m ◎ Set scriptTimingInfo’s event type to event’s type.
- %~target ~LET %~event の `currentTarget@~DOM4#dom-event-currenttarget$m ◎ Let target be event’s currentTarget.
-
~IF[ %~target は `Node$I である ]: ◎ If target is a Node, then:
- %~script計時~報 の`呼出元の名前$stI ~SET %~target の `nodeName@~DOM4#dom-node-nodename$m ◎ Set scriptTimingInfo’s invoker name to target’s nodeName.
-
~IF[ %~target は `Element$I である ]: ◎ If target is an Element, then:
- %~script計時~報 の`~event~target要素の~ID$stI ~SET %~target の`~ID$ ◎ Set scriptTimingInfo’s event target element id to target’s id.
- %~script計時~報 の`~event~target要素の~src属性$stI ~SET %~target の`属性を名前により取得する$( `src^l ) ◎ Set scriptTimingInfo’s event target element src attribute to the result of getting an attribute value by name "`src`" and target.
- ~ELSE ⇒ %~script計時~報 の`呼出元の名前$stI ~SET %~target の~interface名前 ◎ Else, set scriptTimingInfo’s invoker name to target’s interface name.
- `~source所在を適用する$( %~script計時~報, %~listener の`~callback$evL ) ◎ Apply source location for scriptTimingInfo given listener’s callback.
- ~IF[ %~event は `UIEvent$I である ]~AND[ %~frame計時~報 の`最初の~UI~event時刻印$ftI ~EQ 0 ] ⇒ %~frame計時~報 の`最初の~UI~event時刻印$ftI ~SET %~event の`timeStamp@~DOM4#dom-event-timestamp$m ◎ If event is a UIEvent, and frameTimingInfo’s first ui event timestamp is 0, then set frameTimingInfo’s first ui event timestamp to event’s timeStamp.
`~promise解決器~用に計時~報を記録する@ ときは、 所与の ( `Promise$I %~promise, %種別 ~IN { `resolve-promise^l, `reject-promise^l } ) に対し ⇒ `~script入口点を作成する$( %~promise に`関連な~realm$の`設定群~obj$rM, %種別, 次の手続き ) ◎ To record timing info for promise resolver given a Promise promise and a "`resolve-promise`" or "`reject-promise`" type: • Create script entry point given promise’s relevant realm's settings object, type, and the following\
手続きは、 所与の ( `~script計時~報$ %~script計時~報 ) に対し: ◎ steps given a script timing info scriptTimingInfo:
- %~script計時~報 の`呼出元の名前$stI ~SET %~promise の`呼出元の作成-時の名前$ ◎ Set scriptTimingInfo’s invoker name to promise’s invoker name when created.
- %~script計時~報 の`~source~URL$stI ~SET %~promise の`~scriptの作成-時の~URL$ ◎ Set scriptTimingInfo’s source url to promise’s script url when created.
`~script~block用の~source~URLを設定する@ ときは、 所与の ( `~script計時~報$ %~script計時~報, `~script$ %~script, [ `~URL$/ ~NULL ] %~URL ) に対し: ◎ To set source url for script block given a script timing info scriptTimingInfo, a script script, and a URL-or-null url:
- ~IF[ %~URL ~EQ ~NULL ] ⇒ ~RET ◎ If url is null, then return.
- %~scheme ~LET %~URL の`~scheme$url ◎ ↓
- ~IF[ %~scheme ~IN { `http^l, `https^l } ] ⇒ %~script計時~報 の`~source~URL$stI ~SET %~script の`基底~URL$sC ◎ If url’s scheme is "`http`" or "`https`", then set scriptTimingInfo’s source url to script’s base URL.
- ~ELIF[ %~scheme ~IN { `blob^l, `data^l } ] ⇒ %~script計時~報 の`~source~URL$stI ~SET 次を順に`連結する$ ⇒# %~scheme, `:^l【!":""】 ◎ Otherwise, if url’s scheme is "`blob`" or "`data`" then set scriptTimingInfo’s source url to the concatenation of « url’s scheme, ":"" ».
`古典~scriptの作成~時刻を記録する@ ときは、 所与の ( `~script$ %~script, [ `~URL$/ ~NULL ] %元の~source~URL ) に対し ⇒ `~script入口点を作成する$( %~script の`設定群~obj$sC, `classic-script^l, 次の手続き ) ◎ To record classic script creation time given a script script and a URL-or-null originalSourceURL: • Create script entry point with script’s settings object, "`classic-script`", and the following\
`古典~scriptの実行~開始~時刻を記録する@ ときは、 所与の ( `古典~script$ %~script ) に対し: ◎ To record classic script execution start time given a classic script script:
- %設定群 ~LET %~script の`設定群~obj$sC ◎ Let settings be script’s settings object.
- ~IF[ %~script の`~errorは黙秘するか$sC ~EQ ~T ] ⇒ ~RET ◎ If script’s muted errors is true, then return.
- ~IF[ %設定群 【の`大域~obj$enV】は`~window$でない ] ⇒ ~RET ◎ If settings is not a Window, then return.
- %文書 ~LET %設定群 【の`大域~obj$enV】に`結付けられた文書$ ◎ Let document be settings’s document.
- %~frame計時~報 ~LET %文書 に`関連な~frame計時~報$ ◎ Let frameTimingInfo be document’s relevant frame timing info.
- ~IF[ %~frame計時~報 ~EQ ~NULL ] ⇒ ~RET ◎ ↓
- %処理待ち~script ~LET %~frame計時~報 の`処理待ち~script$ftI ◎ ↓
- ~IF[ %処理待ち~script ~NEQ ~NULL 【~EQ ~NULL ?】 ] ⇒ ~RET ◎ If frameTimingInfo is null or if frameTimingInfo’s pending script is not null, then return.
- ~Assert: %処理待ち~script の`呼出元~種別$stI ~EQ `classic-script^l ◎ Assert: frameTimingInfo’s pending script's invoker type is "`classic-script`".
- %処理待ち~script の`実行~開始~時刻$stI ~SET `安全でない共有される現在の時刻$ ◎ Set frameTimingInfo’s pending script's execution start time to the unsafe shared current time.
`~module~scriptの実行~開始~時刻を記録する@ ときは、 所与の ( `~module~script$ %~script ) に対し ⇒ `~script入口点を作成する$( %~script の`設定群~obj$sC, `module-script^l, 次の手続き ) ◎ To record module script execution start time given a module script script: Create script entry point with script’s settings object, "`module-script`", and the following\
手続きは 所与の ( `~script計時~報$ %~script計時~報 ) に対し: ◎ step given a script timing info scriptTimingInfo:
- %~script計時~報 の`実行~開始~時刻$stI ~SET %~script の%~script計時~報 の`開始~時刻$stI ◎ Set scriptTimingInfo’s execution start time to script’s scriptTimingInfo’s start time.
- `~script~block用の~source~URLを設定する$( %~script計時~報, %~script, %~script の`基底~URL$sC ) ◎ Set source url for script block given scriptTimingInfo, script, and script’s base URL.
`~script入口点を作成する@ ときは、 所与の ( `環境~設定群~obj$ %設定群, `ScriptInvokerType$I %呼出元~種別, %手続き ) に対し: ◎ To create script entry point given an environment settings object settings, a ScriptInvokerType invokerType, and steps, which is an algorithm\
- ~Assert: %手続き は ( `~script計時~報$, `~frame計時~報$(省略時は ε ) ) を受容する~algoである。 ◎ that takes a script timing info and an optional frame timing info:
- ~IF[ %設定群 【の`大域~obj$enV】は`~window$でない ] ⇒ ~RET ◎ If settings is not a Window, then return.
- %文書 ~LET %設定群 【の`大域~obj$enV】に`結付けられた文書$ ◎ Let document be settings’s document.
- ~IF[ %文書 は`全部的に作動中$でない ]~OR[ %文書 の`可視性~状態$doc ~EQ `hidden^l ] ⇒ ~RET ◎ If document is not fully active or hidden, then return.
- %~frame計時~報 ~LET %文書 に`関連な~frame計時~報$ ◎ Let frameTimingInfo be document’s relevant frame timing info.
- ~IF[ %~frame計時~報 ~EQ ~NULL ] ⇒ ~RET ◎ If frameTimingInfo is null, then return.
- ~IF[ %~frame計時~報 の`処理待ち~script$ftI ~NEQ ~NULL ] ⇒ ~RET ◎ If frameTimingInfo’s pending script is not null, then return.
- %~script計時~報 ~LET 新たな`~script計時~報$ — その ⇒# `開始~時刻$stI ~SET `安全でない共有される現在の時刻$, `呼出元~種別$stI ~SET %呼出元~種別 ◎ Let scriptTimingInfo be a new script timing info whose start time is the unsafe shared current time, and whose invoker type is invokerType.
- %手続き( %~script計時~報, %~frame計時~報 ) ◎ Run steps given scriptTimingInfo and frameTimingInfo.
- %~script計時~報 の`~window$stI ~SET %設定群 ◎ Set scriptTimingInfo’s window to settings.
- %~frame計時~報 の`処理待ち~script$ftI ~SET %~script計時~報 ◎ Set frameTimingInfo’s pending script to scriptTimingInfo.
`小task~checkpoint用に計時~報を記録する@ ときは: ◎ To record timing info for microtask checkpoint:
- %~script ~LET `走っている~script$ ◎ Let script be the running script.
- %設定群 ~LET %~script の`設定群~obj$sC ◎ Let settings be script’s settings object.
- %文書 ~LET %設定群 【の`大域~obj$enV】に`結付けられた文書$ ◎ Let document be settings’s document.
- ~IF[ %文書 は`全部的に作動中$でない ]~OR[ %文書 の`可視性~状態$doc ~EQ `hidden^l ] ⇒ ~RET ◎ If document is not fully active or hidden, then return.
- %~frame計時~報 ~LET %文書 に`関連な~frame計時~報$ ◎ Let frameTimingInfo be document’s relevant frame timing info.
- %~script計時~報 ~LET %~frame計時~報 の`処理待ち~script$ftI ◎ Let scriptTimingInfo be frameTimingInfo’s pending script.
- %~frame計時~報 の`処理待ち~script$ftI ~SET ~NULL ◎ Set frameTimingInfo’s pending script to null.
- ~IF[ %~script計時~報 ~EQ ~NULL ] ⇒ ~RET ◎ If scriptTimingInfo is null, then return.
- %~script計時~報 の`終了~時刻$stI ~SET `安全でない共有される現在の時刻$ ◎ Set scriptTimingInfo’s end time to the unsafe shared current time.
- ~IF[ %~script は `古典~script$である ]~AND[ %~script の`~errorは黙秘するか$sC ~EQ ~T ] ⇒ %~script計時~報 の ⇒# `~source~URL$stI ~SET 空~文字列, `~source文字~位置$stI ~SET −1, `~source関数~名$stI ~SET 空~文字列 ◎ If script is a classic script whose muted errors is true, then: • set scriptTimingInfo’s source url to the empty string. • set scriptTimingInfo’s source character position to -1. • set scriptTimingInfo’s source function name to the empty string.
- ~IF[ %~script計時~報 の`開始~時刻$stIから %~script計時~報 の`終了~時刻$stIまでの`所要時間$ ~GT 5ms ] ⇒ %~frame計時~報 の`~script群$ftIに %~script計時~報 を`付加する$ ◎ If the duration between scriptTimingInfo’s start time and scriptTimingInfo’s end time is greater than 5 milliseconds, then append scriptTimingInfo to frameTimingInfo’s scripts.
`~source所在を適用する@ ときは、 所与の ( `~script計時~報$ %~script計時~報, [ `~callback関数$/`Function$I ] %~callback ) に対し: ◎ To apply source location to a script timing info scriptTimingInfo given a callback function or Function callback:
- 任意選択で ⇒ %~script計時~報 の`~source~URL$stI ~SET %~callback を定義した~scriptの~source~URL ◎ The user agent may set scriptTimingInfo’s source url to the source URL of the script where callback was defined.
- 任意選択で ⇒ %~script計時~報 の`~source関数~名$stI ~SET %~callback の関数~名 ◎ The user agent may set scriptTimingInfo’s source function name to the function name of callback.
- 任意選択で ⇒ %~script計時~報 の`~source文字~位置$stI ~SET %~callback を定義した所の文字~位置 ◎ The user agent may set scriptTimingInfo’s source character position to the character position where callback was defined.
`静止-所要時間を記録する@ ときは、 所与の ( `所要時間$ %所要時間 ) に対し: ◎ To record pause duration given a duration duration:
- %~script ~LET `走っている~script$ ◎ Let script be the running script.
- %設定群 ~LET %~script の`設定群~obj$sC ◎ Let settings be script’s settings object.
- ~IF[ %設定群 【の`大域~obj$enV】は`~window$でない ] ⇒ ~RET ◎ If settings is not a Window, then return.
- %文書 ~LET %設定群 【の`大域~obj$enV】に`結付けられた文書$ ◎ Let document be settings’s document.
- ~IF[ %文書 は`全部的に作動中$でない ]~OR[ %文書 の`可視性~状態$doc ~EQ `hidden^l ] ⇒ ~RET ◎ If document is not fully active or hidden, then return.
- %~frame計時~報 ~LET %文書 に`関連な~frame計時~報$ ◎ Let frameTimingInfo be document’s relevant frame timing info.
- ~IF[ %~frame計時~報 ~EQ ~NULL ] ⇒ ~RET ◎ If frameTimingInfo is null, then return.
- ~IF[ %~frame計時~報 の`処理待ち~script$ftI ~EQ ~NULL ] ⇒ ~RET ◎ If frameTimingInfo’s pending script is null, then return.
- %~frame計時~報 の`処理待ち~script$ftIの`静止-所要時間$stI ~INCBY %所要時間 ◎ Increment frameTimingInfo’s pending script's pause duration by the milliseconds value of duration.
4. 既存の標準に対する追加
4.1. ~Web~IDL標準に対する~monkey~patch
各 `Promise$I 【!~interface】には、 次が結付けられる: ◎ ↓
- `呼出元の作成-時の名前@ ⇒ 文字列 — 初期~時は `Promise^l とする。 ◎ The Promise interface has an associated string invoker name when created, initially "`Promise`".\
- `~scriptの作成-時の~URL@ ⇒ 文字列 — 初期~時は空~文字列とする。 ◎ The Promise interface has an associated string script url when created, initially the empty string.
`新たな~promise$を作成する手続きの中の[ 結果の `Promise$I %~promise を返す直前 ]に,次の手続きを挿入する: ◎ Append the following steps to creating a new promise, before returning the Promise:
【 以下の記述は、 ある~interfaceを成す[ ある `Promise$I 型の属性の取得子~手続き ]が,`新たな~promise$を~callしたものと見做している。 】
- %~interface ~LET %~promise を作成することを担当していた`~interface$ ◎ ↓
- %~interface名 ~LET %~interface を表現している文字列 ◎ Let interfaceName be a string representing the interface responsible for creating this promise.
- %属性~名 ~LET %~interface 内の当の`属性$を表現している文字列 ◎ Let attributeName be a string representing the attribute in the interface responsible for creating this promise.
- %~promise の`~scriptの作成-時の~URL$ ~SET `走っている~script$の`基底~URL$sC ◎ Set the created Promise's script url when created to the running script's base URL.
-
任意選択で ⇒ %~promise の`呼出元の作成-時の名前$ ~SET 最後に既知な次の結果 ⇒ 次を順に`連結する$ ⇒# %~interface名, `.^l, %属性~名 ◎ The user-agent may set the created Promise's invoker name when created to the last known concatenation of « interfaceName, ".", attributeName »
この段は、 規範的な仕方で行うのが困難なので,まだまだ~~曖昧である。 それを改善できるか否かを~~調べる必要があり、 ~promise~handler用の~source所在が【同じで】あり続けるか否かも,少しばかり実装定義である。 ◎ this is quite handwavy, because this is difficult to do in a normative way. Need to see if that can be improved, or if the source location for promise handlers would remain a bit implementation-defined.
5. ~securityと~privacyの考慮点
長い~animation~frame用の~APIは、[ 長い~taskの~sourceについて,生成元~安全な帰属~情報を含める ]ことにより,同一-生成元~施策を固守する。 また、 長い~task用には閾値 50ms がある。 所要時間は 1ms までの粒度で供される。 これらは組みで、 非同一-生成元への漏洩-に抗する必要十分な保護を供する。 【閾値 50ms は、~security用に導入されたものではないが,それでも。】 ◎ The Long Animation Frames API adheres to the same-origin policy by including origin-safe attribution information about the source of the long task. There is a 50ms threshold for long tasks. Durations are only provided in 1 ms granularity. Together this provides adequate protection against cross-origin leaks.
この~APIは、[ 利用者により実行される~taskの所要時間と種別についての計時~情報 ]および[ 関数~callを生じさせた閲覧~文脈などの`帰属$ ]を供する。 これは、 攻撃者が~side-channel計時~攻撃を遂行して,[ 利用者の動作を推測する/利用者を識別する ]ことも可能化し得る。 例えば,長い~scriptに後続して長い具現化を併せる~patternで、 利用者による~social~widgetとのヤリトリを推測することもできる。 詳細な[ 関数~callの`帰属$ ]は、 利用者の動作を決定するために利用されることになろう。 ◎ The Long Animation Frames API provides timing information about the duration and type of tasks executed by the user, as well as attribution such as the browsing context causing the function calls. This could enable an attacker to perform side-channel timing attacks to guess the user’s action, or identify the user. For example, a pattern of long script followed by a long render could be put together to guess user’s interaction with a social widget. Detailed function call attribution would be used to determine the user’s action.
5.1. 何が観測器に公開されるのか?
~top-level~pageの中にある すべての観測器 (すなわち,~pageと~main~frame内のすべての~iframe) は、 `長い~animation~frame$が在ることについて通知を受信することになる。 それは、 当の~taskの[ 開始~時刻, 所要時間, 元凶~frameへの~pointer ]を公開する (所要時間は粒度 1ms で)。 この情報は、 今日においてすでに, `setTimeout()^m を利用して より高-分解能に観測できる 【それは、閾値 50ms により制限されない】 。 攻撃者は、[ ~page上のすべてを~clearしてから,非同一-生成元に属する脆弱な資源を追加することで、 `setTimeout()^m からの遅延が,その資源により生じることを確保する ]ことにより,これを行える。 【元凶とは】異なる~page(~UItabや~UIwindow)内の観測器は、 ~UAの~architectureを問わず,通知【において`帰属$】を受信するベキでない。 ◎ All observers within the top level page (i.e. all iframes in the page and the main frame) will receive notifications about presence of long animation frames. We expose the start time of the task, its duration (with 1 ms granularity), and a pointer to the culprit frame. This information can already be observed today, and with higher resolution, using setTimeout. An attacker can do this by clearing everything else on the page and adding the vulnerable cross-origin resource to ensure that delays from the setTimeout are caused by that resource. Observers in other different pages (tabs or windows) should not receive notifications, regardless of the architecture of the user agent.
5.2. 考慮される攻撃~局面
考慮される計時~攻撃として,次が挙げられる: ◎ The following are the timing attacks considered:
- 伝統的な計時~攻撃 ⇒ 外部~資源の読込nにかかる時間を利用して,私的~dataの~sizeを露呈する。 例として、 ある展示における隠された絵図の個数, ~usernameは妥当かどうか, 等々。 `例@http://crypto.stanford.edu/%7edabo/papers/webtiming.pdf$ を見よ。 ◎ Traditional timing attacks: using external resource load time to reveal the size of private data. For instance the number of hidden pictures in a gallery, whether username is valid, etc. See an example.
- ~side-channel計時~攻撃 ⇒ [ 動画~構文解析/ ~script構文解析/ ~app~cache読取n【この特能は~HTMLから廃された】/ `Cache$I ~API(~sw) ]の利用度に関する時間を利用して、 利用者を一意に識別するか, 利用者の[ 年齢, 性別, 所在, 関心事, 等々 ]が成す~profileを作成する。 `一例として@https://tom.vg/papers/timing-attacks_ccs2015.pdf$, ~social~network内の ある~permalink用の~pageからの状態s更新は、 一定の対象層(例: 20 代の女性)に制限-【するように公開-】され得る。 その~permalink~pageの~file~sizeは、 利用者は当の対象層に属するかどうか決定するために利用され得る。 【対象層に属さないならば、当の~pageを読込まないので,時間がかからない。】 ◎ Side-channel timing attacks: using time for video parsing, script parsing, App Cache reads or Cache API (service workers) usage to uniquely identify a user, or to create a profile of the user’s age, gender, location, and interests etc. For instance, status updates from a social network can be limited to certain demographic (eg. females of age 20-30) the file size of the permalink page can be used to determine whether the user is in the target demographic.
これらの局面は、[ 50ms 閾値, 非同一-生成元に関する境界 ]の組みで取組まれる。 すなわち、 信用されない非同一-生成元に属する観測器には,~taskの種別や追加的な帰属は示されない。 ◎ These scenarios are addressed by the 50ms threshold AND respecting cross-origin boundary i.e. not showing task type or additional attribution to untrusted cross origin observers.
5.3. 長い~animation~frame~APIにより公開される追加的な情報
非同一-生成元に属するいくつかの文書が同じ~event~loopを共有し得るので、 それらも,同じ `sequence^en を成す一部として 【すなわち,`描画を更新する手続き$の中で同時に】 描画され得る — その結果、 互いの描画~時刻に波及する。 これらの計時は,すでに非同一-生成元からも いくぶん観測-可能であるが (例:~animation~frameを要請して,遅延されたか否か観測することにより)、 長い~animation~frame~API【!this】は,より高い忠実度でそれらを公開する。 ◎ Since several cross-origin documents can share the same event loop, they can also render as part of the same frame sequence and influence each other’s rendering time. This makes it so that these timings are already somewhat observable cross-origin, e.g. by requesting an animation frame and observing if it is delayed, though long animation frames exposes them at a higher fidelity.
これを軽減するため、 長い~animation~frameの報告-先は, “関与している局所的な根” に限られる: ◎ To mitigate this, long animation frames are only reported to "participating local roots":\
- 長い~animation~frameを観測する文書として適格になるものは、[ 当の `sequence^en に寄与した ある作業~taskに結付けられたもの/ 当の~frameを成す一部として描画されたもの ]に限られる。 ◎ only documents that are associated with a work task that contributed to the sequence, or that were rendered as part of the frame, are eligible to observe the long animation frame,\
- 長い~animation~frameが可用になる文書は、 前項の文書と`同一-生成元に属する最も近い根$に限られる。 【!前項の文書の先祖のうち[その親は[無い/非同一-生成元に属する]もの]のうち文書に最も近いもの】 ◎ and that long animation frame would be available only in their nearest ancestor that is either topmost or has a cross-origin parent.
5.4. `PerformanceScriptTiming$I と不透明な~script
`PerformanceScriptTiming$I は,~script実行についての情報を公開するので、[ 他では容易に演繹され得ない`~CORS非同一-生成元$な~script ]について,多過ぎる情報を公開しないようにする必要がある。 それを行うため、 そのような事例では, 既存の~flag `~errorは黙秘するか$sCを利用すると伴に空な `sourceURL$m を報告する。 ◎ Since PerformanceScriptTiming exposes information about script execution, we need to make sure it doesn’t expose too much information about CORS cross-origin scripts that cannot be easily deduced otherwise. To do that, we use the existing muted errors boolean, and report an empty sourceURL in such cases.