1. 序論
1.1. 概観
◎非規範的利用者は、 ~web~siteに携わるとき, 自身の動作に対し~web~siteが素早く変化することを期待する。 事実,`事実調査@https://www.nngroup.com/articles/response-times-3-important-limits/$から、 100ms 以内に取扱われない利用者~入力は,遅いものと見なされることが示唆された。 したがって、[ この指針を達成できなかった入力~eventについて,処理能~計時~情報を表面化する ]ことは,重要になる。 ◎ When a user engages with a website, they expect their actions to cause changes to the website quickly. In fact, research suggests that any user input that is not handled within 100ms is considered slow. Therefore, it is important to surface performance timing information about input events that could not achieve those guidelines.
~eventの待時間を監視するための共通的な仕方は、 ~event~listenerを登録することである。 開発者は: ◎ A common way to monitor event latency consists of registering an event listener.\
- 当の~eventの `timeStamp$m 属性を介して,その作成-時における時刻印を得せることに加え、 ~event~handler~logicの開始時と終了時にて `performance.now()$c を~callして,それらの時点における時刻印を得することもできる。 ◎ The timestamp at which the event was created can be obtained via the event’s timeStamp. In addition, performance.now() could be called both at the beginning and at the end of the event handler logic.\
-
~event~handlerの開始時に得された時刻印から~hardware時刻印†を 減算することにより, `入力~遅延^b — 入力の処理を開始するまでにかかった時間 — を算出できる。
【† おそらく,作成-時における時刻印( `timeStamp^m )と同じ。 意味としては、 何らかの装置により当の~eventが生じた時刻と思われるが。 】
◎ By subtracting the hardware timestamp from the timestamp obtained at the beginning of the event handler, the developer can compute the input delay: the time it takes for an input to start being processed.\ - 開始時の時刻印を終了時の時刻印から減算することにより, ~event~handler内で遂行された同期的な作業が成す量を算出できる。 ◎ By subtracting the timestamp obtained at the beginning of the event handler from the timestamp obtained at the end of the event handler, the developer can compute the amount of synchronous work performed in the event handler.\
- 一連の入力が同期的に 【すなわち,`~event~loop処理~model$における一回の反復~内で】 取扱われるとき, ~hardware時刻印から次回の塗り~eventが取扱われた後までの所要時間は、 利用者~体験の計量に有用になる。 ◎ Finally, when inputs are handled synchronously, the duration from event hardware timestamp to the next paint after the event is handled is a useful user experience metric.
この~approachには、 いくつか根本的な欠陥がある: ◎ This approach has several fundamental flaws.\
- ~event~listenerは,[ ~page読込nにおける ごく早期においては、 まだ登録されない見込みが高い ]ので 【~targetになる要素が~instance化されるまで待機する必要がある】、 ~event~listenerを要求することは,そのような時点で~event待時間を測定することを予め除外する。 ◎ First, requiring event listeners precludes measuring event latency very early in the page load because listeners will likely not be registered yet at that point in time.\
- 開発者は、 入力~遅延にしか関心がない場合でも, 元々は不要であった~eventに新たな~listenerを追加するよう強制されるかもしれない。 その結果、 ~event待時間の計算に不必要な処理能~overheadが加算される。 ◎ Second, developers that are only interested in the input delay might be forced to add new listeners to events that originally did not have one. This adds unnecessary performance overhead to the event latency calculation.\
- この~approachを介して[ ~eventにより生じた非同期的な作業 ]を測定することは、 ごく難しくなろう。 ◎ And lastly, it would be very hard to measure asynchronous work caused by the event via this approach.
この仕様は、 ~event待時間を監視するための代替を供して,これらの問題を成す一部を解く。 時刻印は,~UAが算出するので、 ~event~listener用に処理能を測定する必要は無い。 このことは、 次を意味する: ◎ This specification provides an alternative to event latency monitoring that solves some of these problems. Since the user agent computes the timestamps, there is no need for event listeners in order to measure performance. This means that\
- ~eventが~page読込nにおける ごく早期に生じる場合でも,捕捉できる。 ◎ even events that occur very early in the page load can be captured.\
- 遅い~eventが可視になることを — ~~考えられるあらゆる~eventに対し~patchして~subscribeするよう試みるための解析~器を要求することなく — 可能化する。 ◎ This also enables visibility into slow events without requiring analytics providers to attempt to patch and subscribe to every conceivable event.\
- ~web~siteの処理能には、 不要な~event~listenerによる~overheadの難はなくなる。 ◎ In addition to this, the website’s performance will not suffer from the overhead of unneeded event listeners.\
この仕様は、[ ~eventが処理された直後に生じた描画の計時についての詳細な情報を得する ]ことも開発者に許容する。 これは、 ~eventにより誘発された[ ~web~siteに対する改変 ]による~overheadを測定するために有用になり得る。 ◎ Finally, this specification allows developers to obtain detailed information about the timing of the rendering that occurs right after the event has been processed. This can be useful to measure the overhead of website modifications that are triggered by events.
1.2. ヤリトリ
◎非規範的1 回の`利用者-ヤリトリ$ (~gesture【!Gesture】と称されることもある)は、 概して,複数の[ 物理的な~hardware入力~event ]からなる。 各[ 物理的な入力~event ]は, いくつかの `UIEvent$I を~UAに配送させるかもしれず、 それら各~eventは,複数の[ ~custom~event~listener/別個な既定~動作 ]を誘発することもある。 ◎ A single user Interaction (sometimes called a Gesture) is typically made up of multiple physical hardware input events. Each physical input event might cause the User Agent to dispatch several UIEvents, and each of those might trigger multiple custom event listeners, or trigger distinct default actions.
例えば,利用者による~touch~screen装置との 1 回の “~tap” ヤリトリは、 実際には,物理的な入力~eventたちが成す連列からなる: ◎ For example, a single user "tap" interaction with a touchscreen device is actually made up of a sequence of physical input events:
- ~touch開始 ◎ a touch start,
- ~touchの少量な動き ◎ a tiny amount of touch movement,
- ~touch終了 ◎ a touch end.
これらの物理的な入力~eventは、 一連の `UIEvent$I を配送するかもしれない: ◎ Those physical input events might dispatch a series of UIEvents:
- `pointerdown$et ◎ pointerdown,
- `touchstart$et ◎ touchstart,
- `pointermove$et ◎ pointermove,
- `touchmove$et ◎ touchmove,
- `pointerup$et ◎ pointerup,
- `touchend$et ◎ touchend,
- `click$et ◎ click,
加えて、 これらの合間には,何らかの各種[ ~focus~event, 入力~event, 等々 ]も挟まれ得る。 ◎ • ...and potentially some Focus events, Input events, etc, in between.
これら個々の `UIEvent$I は、 各自の自前の[ 詳細な計時~用に有用な `PerformanceEventTiming$I ~entry ]を報告するための候補になる。 ◎ These individual UIEvents will each become candidates for their own PerformanceEventTiming entry reporting, which is useful for detailed timing.
注記: [ `pointermove$et, `touchmove$et ]は、 現時点では,`~event計時~用に考慮されるべき$でない。 ◎ Note: pointermove and touchmove are not currently considered for Event Timing.
しかしながら,この仕様は、[ 互いに関係する `PerformanceEventTiming$I たちを `interactionId$mET 属性を介して`利用者-ヤリトリ$たちへ~group分けする ]ための仕組みも定義する。 この仕組みは、 `次回の塗りまでのヤリトリ@https://developer.mozilla.org/en-US/docs/Glossary/Interaction_to_next_paint$ ( `Interaction to Next Paint^en, 略称 INP ) と呼ばれ,~page応答性の計量を定義するために利用できる。 ◎ However, this specification also defines a mechanism for grouping related PerformanceEventTimings into Interactions via an interactionId. This mechanism can be used to define a page responsiveness metric called Interaction to Next Paint (INP).
1.3. 初回~入力
◎非規範的初回の`利用者-ヤリトリ$は、 概して,利用者~体験に突出した影響iがあり, 突出して遅いことも多い。 ◎ The very first user Interaction typically has a disproportionate impact on user experience, and is also often disproportionately slow.
そのため、 `~event計時~API^cite ( `Event Timing API^en ) 【以下,略して “この~API” 】 は, `Window$I の`初回~入力^b( `the first input^en )についての計時~情報を公開する — それは、 0 でない `interactionId$mET を伴う最初の `PerformanceEventTiming$I ~entryとして定義される。 ◎ To that effect, the Event Timing API exposes timing information about the first input of a Window, defined as the first PerformanceEventTiming entry with a non-0 interactionId.
ほとんどの `PerformanceEventTiming$I と違って, `初回~入力^b用の~entryは、 供された `durationThreshold$mb を超過しない場合でも報告され, 所要時間~用の既定の閾値 104ms を超過しない場合でも~bufferされる。 この仕組みは、 `初回~入力の遅延@https://developer.mozilla.org/en-US/docs/Glossary/First_input_delay$ ( `First Input Delay^en, 略称 FID ) 呼ばれ,~page応答性の計量を定義するために利用できる。 ◎ Unlike most PerformanceEventTimings, the first input entry is reported even if it does not exceed a provided durationThreshold, and is buffered even if it does not exceed the default duration threshold of 104ms. This mechanism can be used to define a page responsiveness metric called First Input Delay (FID).
このことは、[ ~pageが常に即答可能な場合でも,そこからの~dataを含める ]ことにより,[ ~event~handlerを登録しなくとも,百分率順位と処理能の改善をより良く測定する ]ことを開発者に許容する。 ◎ This also allows developers to better measure percentiles and performance improvements, by including data even from pages which are always very responsive, without having to register event handlers.
1.4. 公開される~event
この~APIは、 ある種の~event用に限り,計時~情報を公開する。 ◎ The Event Timing API exposes timing information only for certain events.
所与の `Event$I ~obj %~event が `~event計時~用に考慮されるべき@ であるとは、 ~AND↓ が満たされることをいう: ◎ Given an event, to determine if it should be considered for Event Timing, run the following steps:
- %~event の `isTrusted$m 属性の値 ~EQ ~T ◎ If event’s isTrusted attribute value is set to false, return false.
- %~event の `type$m 属性の値は、 次に挙げるいずれかである ⇒# `auxclick$et, `click$et, `contextmenu$et, `dblclick$et, `mousedown$et, `mouseenter$et, `mouseleave$et, `mouseout$et, `mouseover$et, `mouseup$et, `pointerover$et, `pointerenter$et, `pointerdown$et, `pointerup$et, `pointercancel$et, `pointerout$et, `pointerleave$et, `gotpointercapture$et, `lostpointercapture$et, `touchstart$et, `touchend$et, `touchcancel$et, `keydown$et, `keypress$et, `keyup$et, `beforeinput$et, `input$et, `compositionstart$et, `compositionupdate$et, `compositionend$et, `dragstart$et, `dragend$et, `dragenter$et, `dragleave$et, `dragover$et, `drop$et ◎ If event’s type is one of the following: auxclick, click, contextmenu, dblclick, mousedown, mouseenter, mouseleave, mouseout, mouseover, mouseup, pointerover, pointerenter, pointerdown, pointerup, pointercancel, pointerout, pointerleave, gotpointercapture, lostpointercapture, touchstart, touchend, touchcancel, keydown, keypress, keyup, beforeinput, input, compositionstart, compositionupdate, compositionend, dragstart, dragend, dragenter, dragleave, dragover, drop, return true. ◎ Return false.
注記: [ `mousemove$et, `pointermove$et, `pointerrawupdate$et, `touchmove$et, `wheel$et, `drag$et ]は、 “継続的” な~eventなので,除外される。 現在の~APIは、[ ~entryたちに基づく有意義な処理能~計量を得する ]ために[ ~eventたちを数えて集成する方法 ]に関して,十分な指導がないので。 したがって、 これらの~event型【の計時】は公開されない。 ◎ Note: mousemove, pointermove, pointerrawupdate, touchmove, wheel, and drag are excluded because these are "continuous" events. The current API does not have enough guidance on how to count and aggregate these events to obtain meaningful performance metrics based on entries. Therefore, these event types are not exposed.
1.5. ~eventは いつ測定されるか
◎非規範的この節では、 — `§ 処理~model@#sec-processing-model$にて公開される高-~levelな情報を説明する。 ◎ It explains at a high level the information that is exposed in the § 3 Processing model section.
~event計時~情報は、 ある種の~event【~event型】用に限り公開される。 それは、[ 利用者-入力から入力~処理に後続する塗り演算までの時間~差が, ある種の所要時間~閾値を超過するとき ]に限り,公開される。 ◎ Event timing information is only exposed for certain events, and only when the time difference between user input and paint operations that follow input processing exceeds a certain duration threshold.
この~APIは、 `duration$m 値を公開する。 それは、 物理的な利用者-入力が生じたとき ( `Event$I ~eventの `timeStamp$m を介して見積もられる)から次回の[ 当の~eventに`関連な大域~obj$に`結付けられた文書$の描画 ]が更新されるまでの時間【~milli秒】が意味される。 この値は、 粒度 8ms で供される。 ◎ The Event Timing API exposes a duration value, which is meant to be the time from when the physical user input occurs (estimated via the Event’s timeStamp) to the next time the rendering of the Event’s relevant global object’s associated Document’s is updated. This value is provided with 8 millisecond granularity.
この~APIは、 既定では `duration$m が 104 以上になるとき,~entryを~bufferして公開するが、 開発者は,[ 未来の~entryを異なる閾値で観測する ]よう `PerformanceObserver$I を設定しておける。 この設定は、 ~buffer済みな~entryたちを変更しないことに注意 — よって, `buffered$mb ~flagは、[ 過去の~entryのうち,既定の閾値~以上の所要時間を伴うもの ]に限り受取ることを可能化する。 ◎ By default, the Event Timing API buffers and exposes entries when the duration is 104 or greater, but a developer can set up a PerformanceObserver to observe future entries with a different threshold. Note that this does not change the entries that are buffered and hence the buffered flag only enables receiving past entries with duration greater than or equal to the default threshold.
`Event$I ~obj %~event の`遅延^bは、 %~event の `timeStamp$m から~browserが %~event 用の~event~handlerを走らせ始める時点までの時間~差である。 [ 前者/後者【!原文は逆】 ]の時刻は、 `PerformanceEventTiming$I の[ `startTime$m / `processingStart$mET ]属性として公開される。 したがって、 %~event の遅延は,後者から前者を減算した結果として算出できる。 ◎ An Event’s delay is the difference between the time when the browser is about to run event handlers for the event and the Event’s timeStamp. The former point in time is exposed as the PerformanceEventTiming’s processingStart, whereas the latter is exposed as PerformanceEventTiming’s startTime. Therefore, an Event’s delay can be computed as processingStart - startTime.
この~APIは、 各~eventに対し,[ それ用の~event~listenerが有っても無くても, それ用に【計時】~entryを作成する ]ことに注意。 特に,最初の[ ~click/~UIkey ]は、 利用者が実際に~pageの機能性とヤリトリするよう試行したものではないかもしれない — 多くの利用者は、[ 自身が読んでいる間に~textを選定する/ ~focusを制御するために何も無い区画~内を~clickする ]様なものを行う。 この設計は、[ ~event~listenerを登録する~~時期が遅過ぎる~pageに伴われる問題を捕捉する ]および[ ~event~listenerが無い下でも,入力の有意義な処理能 — ~hover効果のそれなど — を捕捉する ]ために選ばれた。 開発者は、 そのような~entryを無視することを[ 各~entryのうち ( `processingEnd$mET ~MINUS `processingStart$mET ) が ほぼ 0 になるものを無視する ]ことにより選べる — `processingEnd$mET は、 `~eventを配送する~algo$が~~完結したときの時刻なので。 ◎ Note that the Event Timing API creates entries for events regardless of whether they have any event listeners. In particular, the first click or the first key might not be the user actually trying to interact with the page functionality; many users do things like select text while they’re reading or click in blank areas to control what has focus. This is a design choice to capture problems with pages which register their event listeners too late and to capture performance of inputs that are meaningful despite not having event listeners, such as hover effects. Developers can choose to ignore such entries by ignoring those with essentially zero values of processingEnd - processingStart, as processingEnd is the time when the event dispatch algorithm algorithm has concluded.
1.6. 用法~例
const %observer = new PerformanceObserver(function(%list, %obs) { for (let %entry of %list.getEntries()) { /* 入力の遅延 ◎ Input Delay */ const %inputDelay = %entry.processingStart - %entry.startTime; /* 処理の所要時間 ◎ Processing duration */ const %processingDuration = %entry.processingEnd - %entry.processingStart; /* 処理の遅延(近似) ◎ Presentation Delay (approximate) */ const %presentationDelay = Math.max(0, %entry.startTime + %entry.duration - %entry.processingEnd); /* この~eventの~targetについて何らかの情報 — ~IDなど — を得する。 ◎ Obtain some information about the target of this event, such as the id. */ const %targetId = %entry.target ? %entry.target.id : 'unknown-target'; console.log(%entry.entryType, %entry.name, %entry.duration, { %inputDelay, %processingDuration, %presentationDelay }); } }); observer.observe({ type: 'first-input', buffered: true }); observer.observe({ type: 'event', buffered: true, durationThreshold: 40 });
次の例は、 各 %id から[ `interactionId$mET 属性が %id をとる~eventたちの最大な所要時間( `duration$m ) ]へ対応付ける辞書を算出する。 この辞書は、 後で集成され,解析へ報告され得る。 ◎ The following example computes a dictionary mapping interactionId to the maximum duration of any of its events. This dictionary can later be aggregated and reported to analytics.
let %maxDurations = {}; new PerformanceObserver(%list => { for (let %entry of %list.getEntries()) { if (%entry.interactionId > 0) { let %id = %entry.interactionId; if (!%maxDurations[%id]) { %maxDurations[%id] = %entry.duration; } else { %maxDurations[%id] = Math.max(%maxDurations[id], %entry.duration); } } } }).observe({ type: 'event', buffered: true, %durationThreshold: 16 });
この~APIを利用して達成することもできる利用事例の見本: ◎ The following are sample use cases that could be achieved by using this API:
- ある~web~site上で`初回~入力の~遅延^b~dataを集めて, その処理能を時間~越しに追跡する。 ◎ Gather first input delay data on a website and track its performance over time.
- ~buttonが~clickされたとき,~tableを~sortする順序を変更する際に、 ~clickされてから並替られた内容を表示するまでにかかった~~時間を測定する。 ◎ Clicking a button changes the sorting order on a table. Measure how long it takes from the click until we display reordered content.
- 利用者が音量を制御する~sliderを~dragしたときの待時間を測定する。 ◎ A user drags a slider to control volume. Measure the latency to drag the slider.
- 利用者が,ある~menu~itemに~hoverして その下位-~menuを誘発したとき、 それが現れるまでの待時間を測定する。 ◎ Hovering a menu item triggers a flyout menu. Measure the latency for the flyout to appear.
- 利用者による最初の~click (が利用者による初回のヤリトリであったとき) に対し,その待時間の百分率順位 75 位【 100 回の初回~clickのうち 75 番目に長い(短い?)待時間】を測定する。 ◎ Measure the 75’th percentile of the latency of the first user click (whenever click happens to be the first user interaction).
2. ~event計時
この~APIは、 以下に挙げる~interfaceを追加する: ◎ Event Timing adds the following interfaces:
2.1. `PerformanceEventTiming^I ~interface
[`Exposed$=Window] interface `PerformanceEventTiming@I : `PerformanceEntry$I { readonly attribute `DOMHighResTimeStamp$I `processingStart$mET; readonly attribute `DOMHighResTimeStamp$I `processingEnd$mET; readonly attribute `boolean$ `cancelable$mET; readonly attribute `Node$I? `target$mET; readonly attribute `unsigned long long$ `interactionId$mET; [`Default$] `object$ `toJSON@mET(); };
各 `PerformanceEventTiming$I ~objは、 次に挙げるものを有する: ◎ ↓
- `結付けられた~event@ ⇒ 【ある `UIEvent$I 】 — 当の~objは、 この~eventについての計時~情報を報告する。 ◎ A PerformanceEventTiming object reports timing information about one associated Event.
- `結付けられた~event~target@ ⇒ ~NULL /ある `Node$I — 初期~時は ~NULL とする。 ◎ Each PerformanceEventTiming object has these associated concepts, all of which are initially set to null: • An eventTarget containing the associated Node.
注記: この~APIを実装している~UAは、 `Window$I 文脈が`~supportする~entry型~群$に[ `first-input^l, `event^l ]を含める必要がある。 これは、 ~event計時~用の~supportを検出することを開発者に許容する。 ◎ Note: A user agent implementing the Event Timing API would need to include "first-input" and "event" in supportedEntryTypes for Window contexts. This allows developers to detect support for event timing.
この節を成す以降は、 規範的でない。 `PerformanceEventTiming$I を成す各~属性の値は, `§ 処理~model@#sec-processing-model$において設定される。 この節は、 それらが どう設定されるかに関する規範的でない要約を供する。 ◎ This remainder of this section is non-normative. The values of the attributes of PerformanceEventTiming are set in the processing model in § 3 Processing model. This section provides an informative summary of how they will be set.
`PerformanceEventTiming$I は、 `PerformanceEntry$I ~interfaceを成す次に挙げる属性を拡張する: ◎ PerformanceEventTiming extends the following attributes of the PerformanceEntry interface:
- `name$m
- この属性の取得子は、 `結付けられた~event$の `type$m を供する。 ◎ The name attribute’s getter provides the associated event’s type.
- `entryType$m
- この属性の取得子は、[ (長くかかかった~event用には) `event^l / (利用者による初回のヤリトリ用には) `first-input^l ]を返す。 ◎ The entryType attribute’s getter returns "event" (for long events) or "first-input" (for the first user interaction).
- `startTime$m
- この属性の取得子は、 `結付けられた~event$の `timeStamp$m を返す。 ◎ The startTime attribute’s getter returns the associated event’s timeStamp.
- `duration$m
- この属性の取得子は、 `startTime$m から[ `結付けられた~event$が配送された後,その`文書$【その`~target$の`~node文書$】に対し次回の`描画を更新する$手続きが完了する ]までの差を返す — 結果は最も近い 8ms の整数倍に丸められる。 ◎ The duration attribute’s getter returns the difference between the next time the update the rendering steps are completed for the associated event’s Document after the associated event has been dispatched, and the startTime, rounded to the nearest 8ms.
`PerformanceEventTiming$I は、 次に挙げる追加的な属性を有する: ◎ PerformanceEventTiming has the following additional attributes:
- `processingStart@mET
- この属性の取得子は、 `~eventを配送する~algo$の開始時に捕捉された時刻印を返す。 これが、 ~event~handlerを実行し始めたときになる。 ◎ The processingStart attribute’s getter returns a timestamp captured at the beginning of the event dispatch algorithm. This is when event handlers are about to be executed.
- `processingEnd@mET
- この属性の取得子は、 `~eventを配送する~algo$の終了時に捕捉された時刻印を返す。 これが、 ~event~handlerを実行し終えたときになる。 そのような~event~handlerが無いときは、 `processingStart$mET に等しくなる。 ◎ The processingEnd attribute’s getter returns a timestamp captured at the end of the event dispatch algorithm. This is when event handlers have finished executing. It’s equal to processingStart when there are no such event handlers.
- `cancelable@mET
- この属性の取得子は、 `結付けられた~event$の `cancelable$m 属性の値を返す。 ◎ The cancelable attribute’s getter returns the associated event’s cancelable attribute value.
- `target@mET
- この属性の取得子は、 `結付けられた~event$の `target$m — そのような `Node$I が`接続されて$いる, かつ~shadow~DOM内にはないときの最後のそれ — を返す。 ◎ The target attribute’s getter returns the associated event’s last target when such Node is not disconnected nor in the shadow DOM.
- 【 と記されているが、 `§ 処理~model@#sec-processing-model$ の中から参照されておらず, 具体的に どう設定されるのか わからない。 】
- `interactionId@mET
-
この属性の取得子は、 `結付けられた~event$を誘発した `利用者-ヤリトリ@ を一意に識別する無符号整数を返す。 この属性は、 `結付けられた~event$が ~OR↓ を満たさない場合には 0 になる: ◎ The interactionId attribute’s getter returns the ID that uniquely identifies the user interaction which triggered the associated event. This attribute is 0 unless the associated event’s type attribute value is one of:
-
[ その `type$m 属性の値 ~IN { `pointerdown$et, `pointerup$et, `click$et } ]~AND[ 利用者-[ ~tap/~drag ]~gestureから生じた ]
~scrollの終了における `pointerdown$et 【?】は除外されることに注意。
◎ A pointerdown, pointerup, or click belonging to a user tap or drag. Note that pointerdown that ends in scroll is excluded. - [ その `type$m 属性の値 ~IN { `keydown$et, `keyup$et } ]~AND[ 利用者-~UIkeyの押下げから生じた ] ◎ A keydown or keyup belonging to a user key press.
-
2.2. `EventCounts^I ~interface
[`Exposed$=Window] interface `EventCounts@I { readonly maplike<`DOMString$, `unsigned long long$>; };
`EventCounts$I ~objは、 `~event回数~map$wを表現する。 【以下,この段落を成す他の内容は、`~event回数~map$wの記述と重複するので省略する。】 ◎ The EventCounts object is a map where the keys are event types and the values are the number of events that have been dispatched that are of that type. Only events whose type is supported by PerformanceEventTiming entries (see section § 1.4 Events exposed) are counted via this map.
2.3. `Performance^I ~interfaceに対する拡張
[`Exposed$=Window] partial interface `Performance$I { [`SameObject$] readonly attribute `EventCounts$I `eventCounts$m; readonly attribute `unsigned long long$ `interactionCount$m; };
3. 処理~model
3.1. ~DOM仕様に対する改変
この節は、 `DOM$r が【この仕様を組入れるよう】改変されたなら除去されることになる。 ◎ This section will be removed once [DOM] has been modified.
`~eventを配送する~algo$を次に従うよう改変する: ◎ We modify the event dispatch algorithm as follows.
-
最初の段【!step 1】の直後に次を遂行する段たちを挿入する【!add】: ◎ Right after step 1, we add the following steps:
- %ヤリトリ~ID ~LET `ヤリトリ~IDを算出する$( %~event ) ◎ Let interactionId be the result of computing interactionId given event.
- %計時~entry ~LET `~event計時を作成する$( %~event, `現在の高分解能~時刻$, %ヤリトリ~ID ) ◎ Let timingEntry be the result of initializing event timing given event, the current high resolution time, and interactionId.
-
値を返す段【最後の段】の直前に次を遂行する段を挿入する【!add】: ◎ Right before the returning step of that algorithm, add the following step:
- `~event計時を完結する$( %計時~entry, %~event, %~target, `現在の高分解能~時刻$ ) ◎ Finalize event timing passing timingEntry, event, target, and the current high resolution time as inputs.
注記: ~UAは、 `~eventを配送する~algo$を飛ばす場合でも, 当の `Event$I 用の~entryを含めるよう選べる。 ~UAは,この事例では、 `processingStart$mET の値を見積もって, `processingEnd$mET を同じ値に設定することになる。 ◎ Note: If a user agent skips the event dispatch algorithm, it can still choose to include an entry for that Event. In this case, it will estimate the value of processingStart and set the processingEnd to the same value.
3.2. ~HTML仕様に対する改変
この節は、 `HTML$r が【この仕様を組入れるよう】改変されたなら,除去されることになる。 ◎ This section will be removed once [HTML] has been modified.
各 `Window$I には、 次に挙げる概念が結付けられる: ◎ Each Window has the following associated concepts:
- `~queueされることになる~entry群@w ⇒ `PerformanceEventTiming$I ~objたちが成す`~list$ — 初期~時は空とする。 ◎ entries to be queued, a list that stores PerformanceEventTiming objects, which will initially be empty.
- `入力~eventは配送-済みか@w ⇒ 真偽値 — 初期~時は ~F とする。 ◎ has dispatched input event, a boolean which is initially set to false.
-
`利用者ヤリトリ値@w ⇒ 整数 — 初期~時は 100 以上 10000 以下の~randomな整数とする。 ◎ user interaction value, an integer which is initially set to a random integer between 100 and 10000.
注記: `利用者ヤリトリ値$wは、 0 ではなく ~randomな整数に設定される — 開発者が[ それに依拠して,~pageにおいて何回ヤリトリされたか数えない ]ようにするために。 ~randomな値から開始することにより、 開発者は,それを[ 当の~page内で生じたヤリトリの回数 ]用の真実を成す~sourceとして利用しなくなると見込まれる。 ◎ Note: the user interaction value is set to a random integer instead of 0 so that developers do not rely on it to count the number of interactions in the page. By starting at a random value, developers are less likely to use it as the source of truth for the number of interactions that have occurred in the page.
-
`処理待ちな~keydown~map@w ⇒ 整数†から `PerformanceEventTiming$I への`有順序~map$ — 初期~時は空とする。 ◎ pending key downs, a map of integers to PerformanceEventTimings which is initially empty.
【† 押された~UIkeyを識別する `keyCode$m 属性の値。 `code$m ではなく旧来の `keyCode^m が利用されているのは、 ~IMEにより生じた `keydown$et ( `keyCode^m は 229 になる)を特別に取扱うためでしかない (これらの整数は、 ~APIには,公開されない)。 しかしながら, `keyCode^m 属性の挙動は実装定義なので、 `code^m 属性の値と — 229 以外において — 一対一に対応しないかもしれない (代わりに `code^m 属性を利用することにした場合と挙動が異なる結果、 相互運用能が得られないかもしれない)。 】
-
`~pointerヤリトリ値~map@w ⇒ 整数†から整数††への`有順序~map$ — 初期~時は空とする。 ◎ pointer interaction value map, a map of integers which is initially empty.
【† ~eventを生じさせた~pointerを一意に識別する `pointerId$m 属性の値。 】【†† `ある回のヤリトリ@#sec-event-timing-interactions$を識別する整数。 】
- `処理待ちな~pointerdown~map@w ⇒ 整数から `PerformanceEventTiming$I への`有順序~map$ — 初期~時は空とする。 ◎ pending pointer downs, a map of integers to PerformanceEventTimings which is initially empty.
- `~contextmenuを誘発したか@w ⇒ 真偽値 — 初期~時は ~F とする。 ◎ is contextmenu triggered, a boolean which is initially set to false.
-
`~event回数~map@w ⇒ 文字列から整数への`有順序~map$【順序は有意でない】 — 各~entryの:
- ~keyは、 `PerformanceEventTiming$I ~entryが~supportする~event型【!types@Event/type$】 — `§ 公開される~event@#sec-events-exposed$にて挙げられたもの — をとる。
- 値は、[ `type$m として当の~keyを伴う~event ]が何回~配送されたかを数える。
この~map %~map は、 初期~時【!Upon construction of a Performance object whose relevant global object is a Window,】には,次の~algoに従って初期化するモノトスル ⇒ `§ 公開される~event@#sec-events-exposed$にて挙げられた ~EACH( ~event型 %型 ) に対し ⇒ ~IF[ ~UAは %型 を~event型として~supportする ] ⇒ %~map[ %型 ] ~SET 0◎ eventCounts, a map with entries of the form type → numEvents. This means that there have been numEvents dispatched such that their type attribute value is equal to type. Upon construction of a Performance object whose relevant global object is a Window, its eventCounts must be initialized to a map containing 0s for all event types that the user agent supports from the list described in § 1.4 Events exposed. - `ヤリトリ回数@w ⇒ ある整数 — 利用者による別個なヤリトリたちの総数を数える。 これ以下の各~回数と`ヤリトリ~IDを算出する$ことを介して算出される `interactionId$mET 【`利用者ヤリトリ値$w】 は、 一対一に対応する。 ◎ interactionCount, an integer which counts the total number of distinct user interactions, for which there was a unique interactionId computed via computing interactionId.
3.3. 処理能~時列線 仕様に対する改変
この節は、 `PERFORMANCE-TIMELINE-2$r が【この仕様を組入れるよう】改変されたなら,除去されることになる。 ◎ This section will be removed once [PERFORMANCE-TIMELINE-2] had been modified.
`PerformanceObserverInit$I 辞書は,次のように増補される: ◎ The PerformanceObserverInit dictionary is augmented:
partial dictionary `PerformanceObserverInit$I { `DOMHighResTimeStamp$I `durationThreshold@mb; };
3.4. `PerformanceEventTiming^I を追加するべきか
注記: 次の~algoは、 `PERFORMANCE-TIMELINE-2$r において[ `PerformanceObserver$I の~buffer/当の処理能~時列線 ]に `PerformanceEventTiming$I ~entryを追加する必要があるか否かを決定するために利用される — `計時~entry名~registry@~TETregistry$cite における`~entryを追加するべきか?@~TETregistry#dfn-should-add-entry$にて述べられるとおり。 ◎ Note: The following algorithm is used in the [PERFORMANCE-TIMELINE-2] specification to determine when a PerformanceEventTiming entry needs to be added to the buffer of a PerformanceObserver or to the performance timeline, as described in the registry.
`PerformanceEventTiming$I 用の`~entryを追加するべきか?@~TETregistry#dfn-should-add-entry$ を決定する~algoは、 所与の ( `PerformanceEventTiming$I %~entry, `PerformanceObserverInit$I %~option群 (省略時は ε ) ) に対し: ◎ Given a PerformanceEventTiming entry and a PerformanceObserverInit options, to determine if we should add PerformanceEventTiming, with entry and optionally options as inputs, run the following steps:
- ~IF[ %~entry の `entryType$m 属性の値 ~EQ `first-input^l ] ⇒ ~RET ~T ◎ If entry’s entryType attribute value equals to "first-input", return true.
- ~Assert: %~entry の `entryType$m 属性の値 ~EQ `event^l ◎ Assert that entry’s entryType attribute value equals "event".
- %最小~所要時間 ~LET %~option群 に応じて ⇒# ε ならば ε / ~ELSE_ %~option群[ "`durationThreshold$mb" ] ◎ Let minDuration be computed as follows: ◎ ↓
- %最小~所要時間 ~SET %最小~所要時間 に応じて ⇒# ε ならば 104 / ~ELSE_ `max^op( 16, %最小~所要時間 ) ◎ If options is not present or if options’s durationThreshold is not present,let minDuration be 104. ◎ Otherwise, let minDuration be the maximum between 16 and options’s durationThreshold value.
- ~RET ~IS[ %~entry の `duration$m 属性の値 ~GTE %最小~所要時間 ] ◎ If entry’s duration attribute value is greater than or equal to minDuration, return true. ◎ Otherwise, return false.
3.5. ヤリトリ回数を増やす
`ヤリトリ回数を増やす@ ~algoは、 所与の ( `Window$I ~obj %~window ) に対し: ◎ When asked to increase interaction count given a Window window object, perform the following steps:
- %~window の`利用者ヤリトリ値$w ~INCBY ~UAにより選ばれる小さな無符号整数 ◎ Increase window’s user interaction value value by a small number chosen by the user agent.
- %~window の`ヤリトリ回数$w ~INCBY 1 ◎ Let interactionCount be window’s interactionCount. ◎ Set interactionCount to interactionCount + 1.
注記: `利用者ヤリトリ値$wは、 それを開発者が[ ~web~app内に生じた利用者-ヤリトリ回数の計数器 ]と見なすことを忌避するため, 1 の代わりに~UAにより選ばれる小さな無符号整数で増やされる。 これは、 次を選ぶことを~UAに許容する ⇒ `利用者ヤリトリ値$wを — それを後回しに算出するのではなく — 早急に(すなわち, `pointerdown$et にて)アテガってから, それを後で(すなわち, `pointercancel$et の後に)破棄する。 ◎ Note: The user interaction value is increased by a small number chosen by the user agent instead of 1 to discourage developers from considering it as a counter of the number of user interactions that have occurred in the web application. This allows the user agent to choose to eagerly assign a user interaction value (i.e. at pointerdown) and then discard it (i.e. after pointercancel), rather than to lazily compute it.
~UAは、 `利用者ヤリトリ値$wを増やす小さな整数を[ 毎回~randomに選んでも,定数を選んでもヨイ。 ~UAは、 利用する`利用者ヤリトリ値$wを すべての `Window$I にわたって大域的に共有しないモノトスル — さもなければ、 非同一-生成元への漏洩も導入し得るので。 ◎ A user agent may choose to increase it by a small random integer every time, or choose a constant. A user agent must not use a shared global user interaction values for all Windows, because this could introduce cross-origin leaks.
3.6. ヤリトリ~IDを算出する
`ヤリトリ~IDを算出する@ ~algoは、 所与の ( `Event$I %~event ) に対し: ◎ When asked to compute interactionId with event as input, run the following steps:
- ~IF[ %~event の `isTrusted$m 属性の値 ~EQ ~F ] ⇒ ~RET 0 ◎ If event’s isTrusted attribute value is false, return 0.
- %型 ~LET %~event の `type$m 属性の値 ◎ Let type be event’s type attribute value.
-
~IF[ %型 ~NIN { `keyup$et, `compositionstart$et, `input$et, `pointercancel$et, `pointerup$et, `click$et, `contextmenu$et } ] ⇒ ~RET 0 ◎ If type is not one among keyup, compositionstart, input, pointercancel, pointerup, click, or contextmenu, return 0.
注記: [ `keydown$et, `pointerdown$et ]に対しては、 `~event計時を完結する$ときに処理待ちとして~markされてから, 後でに未来の~event( `keyup$et, `pointerup$et など)用に`ヤリトリ~IDを算出する$ときに更新される。 ◎ Note: keydown and pointerdown are marked pending in finalize event timing, and then updated later when computing interactionId for future events (like keyup and pointerup).
- %~window ~LET %~event に`関連な大域~obj$ ◎ Let window be event’s relevant global object.
- %処理待ちな~keydown~map ~LET %~window の`処理待ちな~keydown~map$w ◎ Let pendingKeyDowns be window’s pending key downs.
- %~pointer~map ~LET %~window の`~pointerヤリトリ値~map$w ◎ Let pointerMap be window’s pointer interaction value map.
- %処理待ちな~pointerdown~map ~LET %~window の`処理待ちな~pointerdown~map$w ◎ Let pendingPointerDowns be window’s pending pointer downs.
-
~IF[ %型 ~EQ `keyup$et ]: ◎ If type is keyup:
- ~IF[ %~event の `isComposing$m 属性の値 ~EQ ~T ] ⇒ ~RET 0 ◎ If event’s isComposing attribute value is true, return 0.
- %~code ~LET %~event の `keyCode$m 属性の値 ◎ Let code be event’s keyCode attribute value.
- ~IF[ %処理待ちな~keydown~map[ %~code ] ~EQ ε ] ⇒ ~RET 0 ◎ If pendingKeyDowns[code] does not exist, return 0.
- %~entry ~LET %処理待ちな~keydown~map[ %~code ] ◎ Let entry be pendingKeyDowns[code].
- `ヤリトリ回数を増やす$( %~window ) ◎ Increase interaction count on window.
- %ヤリトリ~ID ~LET %~window の`利用者ヤリトリ値$w ◎ Let interactionId be window’s user interaction value value.
- %~entry の `interactionId$mET ~SET %ヤリトリ~ID ◎ Set entry’s interactionId to interactionId.
- %~window の`~queueされることになる~entry群$wに %~entry を`付加する$【!add】 ◎ Add entry to window’s entries to be queued.
- %処理待ちな~keydown~map[ %~code ] ~SET ε ◎ Remove pendingKeyDowns[code].
- ~RET %ヤリトリ~ID ◎ Return interactionId.
-
~IF[ %型 ~EQ `compositionstart$et ]: ◎ If type is compositionstart:
-
%処理待ちな~keydown~map の`値~群$mapを成す ~EACH( %~entry ) に対し ⇒ %~window の`~queueされることになる~entry群$wに %~entry を`付加する$ ◎ For each entry in the values of pendingKeyDowns: • Append entry to window’s entries to be queued.
- %処理待ちな~keydown~map を`~clearする$map ◎ Clear pendingKeyDowns.
- ~RET 0 ◎ Return 0.
-
-
~IF[ %型 ~EQ `input$et ]: ◎ If type is input:
-
~IF[ %~event は `InputEvent$I を`実装-$しない【!is not an instance of】 ] ⇒ ~RET 0 ◎ If event is not an instance of InputEvent, return 0.\
注記: この検査は、 `Event$I のうち[ `type$m ~EQ `input$et を満たす ]が[ 改変された~text内容についてではない ]ものを除外するために行われる。 ◎ Note: this check is done to exclude Events for which the type is input but that are not about modified text content.
- ~IF[ %~event の `isComposing@~UIEVENTS#dom-inputevent-iscomposing$m 属性の値 ~EQ ~F ] ⇒ ~RET 0 ◎ If event’s isComposing attribute value is false, return 0.
- `ヤリトリ回数を増やす$( %~window ) ◎ Increase interaction count on window.
- ~RET %~window の`利用者ヤリトリ値$w ◎ Return window’s user interaction value.
-
- ~Assert: %型 ~IN { `pointercancel$et, `pointerup$et, `click$et, `contextmenu$et } ◎ Otherwise (type is pointercancel, pointerup, click, or contextmenu):
- ~Assert: %~event は `PointerEvent$I を`実装-$する。 【この段は、この訳による補完。】
- %~pointer~ID ~LET %~event の `pointerId$m 属性の値 ◎ • Let pointerId be event’s pointerId attribute value.
-
~IF[ %型 ~EQ `click$et ]: ◎ • If type is click:
- %値 ~LET %~pointer~map[ %~pointer~ID ] ◎ • ↓
- ~IF[ %値 ~EQ ε ] ⇒ ~RET 0 ◎ • If pointerMap[pointerId] does not exist, return 0. ◎ • Let value be pointerMap[pointerId].
- %~pointer~map[ %~pointer~ID ] ~SET ε ◎ • Remove pointerMap[pointerId].
- ~RET %値 ◎ • Return value.
- ~Assert: %型 ~IN { `pointerup$et, `pointercancel$et, `contextmenu$et } ◎ • Assert that type is pointerup, pointercancel, or contextmenu.
- %~pointerdown~entry ~LET %処理待ちな~pointerdown~map[ %~pointer~ID ] ◎ • ↓
-
~IF[ %~pointerdown~entry ~EQ ε ]: ◎ • If pendingPointerDowns[pointerId] does not exist:
- ~IF[ %型 ~EQ `contextmenu$et ] ⇒ ~RET %~window の`利用者ヤリトリ値$w ◎ • If type is contextmenu, return window’s user interaction value.
-
~IF[ %型 ~EQ `pointerup$et ]~AND[ %~window の`~contextmenuを誘発したか$w ~EQ ~T ]: ◎ • If type is pointerup and window’s is contextmenu triggered flag is true:
- %~window の`~contextmenuを誘発したか$w ~SET ~F ◎ • Set window’s is contextmenu triggered flag to false.
- ~RET %~window の`利用者ヤリトリ値$w ◎ • Return window’s user interaction value.
- ~RET 0 ◎ • Otherwise, return 0.
- ~Assert: %~pointerdown~entry は `PerformanceEventTiming$I を`実装-$する。 ◎ • Let pointerDownEntry be pendingPointerDowns[pointerId]. ◎ • Assert that pointerDownEntry is a PerformanceEventTiming entry.
-
~IF[ %型 ~IN { `pointerup$et, `contextmenu$et } ]: ◎ • If type is pointerup or contextmenu:
- `ヤリトリ回数を増やす$( %~window ) ◎ • Increase interaction count on window.
- %~pointer~map[ %~pointer~ID ] ~SET %~window の`利用者ヤリトリ値$w ◎ • Set pointerMap[pointerId] to window’s user interaction value.
- %~pointerdown~entry の `interactionId$mET ~SET %~pointer~map[ %~pointer~ID ] ◎ • Set pointerDownEntry’s interactionId to pointerMap[pointerId].
- %~window の`~queueされることになる~entry群$wに %~pointerdown~entry を`付加する$ ◎ • Append pointerDownEntry to window’s entries to be queued.
- %処理待ちな~pointerdown~map[ %~pointer~ID ] ~SET ε ◎ • Remove pendingPointerDowns[pointerId].
- ~IF[ %型 ~EQ `contextmenu$et ] ⇒ %~window の`~contextmenuを誘発したか$w ~SET ~T ◎ • If type is contextmenu, set window’s is contextmenu triggered to true.
- ~IF[ %型 ~EQ `pointercancel$et ] ⇒ ~RET 0 ◎ • If type is pointercancel, return 0.
- ~RET %~pointer~map[ %~pointer~ID ] ◎ • Return pointerMap[pointerId].
注記: この~algoは、 各~eventに対応するヤリトリ~ID( `interactionId$mET )をアテガうよう試みる: ◎ Note: the algorithm attempts to assign events to the corresponding interactiond IDs.\
- ~keyboard~event用には: `keydown$et は,新たなヤリトリ~IDを誘発する一方で、 `keyup$et 用のヤリトリ~IDは,以前の `keydown$et 用のそれと合致する必要がある。 ◎ For keyboard events, a keydown triggers a new interaction ID, whereas a keyup has to match its ID with a previous keydown.\
- ~pointer~event用には: `pointerdown$et の時点で それ用のヤリトリ~IDを知るためには、[ `pointercancel$et / `pointerup$et ]が生じるまで待機する必要がある。 `click$et 用のヤリトリ~IDは,以前の `pointerdown$et 用のそれと合致するよう試行する。 [ `pointercancel^et / `pointerup^et ]が生じたとき、[ 格納-済みな~entryのうち `pointerdown$et に対応するもの ]用にヤリトリ~IDを設定するに準備済みになる。 それが `pointercancel^et である場合、 当の `pointerdown$et には新たなヤリトリ~IDをアテガうよう求まれないことを意味する。 それが `pointerup^et である場合、 新たなヤリトリ~IDを算出して,それを[ `pointerdown$et, `pointerup$et ]両者に(後で `click$et が生じた場合には それにも)設定する。 ◎ For pointer events, when we get a pointerdown we have to wait until pointercancel or pointerup occur to know its interactionId. We try to match click with a previous interaction ID from a pointerdown. If pointercancel or pointerup happens, we’ll be ready to set the interactionId for the stored entry corresponding to pointerdown. If it is pointercancel, this means we do not want to assign a new interaction ID to the pointerdown. If it is pointerup, we compute a new interaction ID and set it on both the pointerdown and the pointerup (and later, the click if it occurs).
3.7. ~event計時を作成する
`~event計時を作成する@ ~algoは、 所与の ⇒# `Event$I %~event, `DOMHighResTimeStamp$I %処理~開始, 無符号整数 %ヤリトリ~ID ◎終 に対し: ◎ When asked to initialize event timing, with event, processingStart, and interactionId as inputs, run the following steps:
- ~IF[ %~event は`~event計時~用に考慮されるべき$でない ] ⇒ ~RET ~NULL ◎ If the algorithm to determine if event should be considered for Event Timing returns false, then return null.
- %計時~entry ~LET `新たな~obj$( `PerformanceEventTiming$I, %~event に`関連な~realm$ ) ◎ Let timingEntry be a new PerformanceEventTiming object with event’s relevant realm.
- %計時~entry の ⇒# `name$m ~SET %~event の `type$m 属性の値, `entryType$m ~SET `event^l, `startTime$m ~SET %~event の `timeStamp$m 属性の値, `processingStart$mET ~SET %処理~開始, `cancelable$mET ~SET %~event の `cancelable$m 属性の値, `interactionId$mET ~SET %ヤリトリ~ID, ◎ Set timingEntry’s name to event’s type attribute value. ◎ Set timingEntry’s entryType to "event". ◎ Set timingEntry’s startTime to event’s timeStamp attribute value. ◎ Set timingEntry’s processingStart to processingStart. ◎ Set timingEntry’s cancelable to event’s cancelable attribute value. ◎ Set timingEntry’s interactionId to interactionId.
- ~RET %計時~entry ◎ Return timingEntry.
【 この~algoは, 原文では “~event計時を初期化する” と命名されているが、 実際には作成した上で初期化するので,この訳では名前を改める。 】
3.8. ~event計時を完結する
`~event計時を完結する@ ~algoは、 所与の ⇒# `PerformanceEventTiming$I %計時~entry, `Event$I %~event, `EventTarget$I %~target, `DOMHighResTimeStamp$I %処理~終了 ◎終 に対し: ◎ When asked to finalize event timing, with timingEntry, event, target, and processingEnd as inputs, run the following steps:
- ~IF[ %計時~entry ~EQ ~NULL ] ⇒ ~RET ◎ If timingEntry is null, return.
- %関連な大域~obj ~LET %~target に`関連な大域~obj$ ◎ Let relevantGlobal be target’s relevant global object.
- ~IF[ %関連な大域~obj は `Window$I を`実装-$しない ] ⇒ ~RET ◎ If relevantGlobal does not implement Window, return.
- %計時~entry の `processingEnd$mET ~SET %処理~終了 ◎ Set timingEntry’s processingEnd to processingEnd.
-
~Assert: %~target は `Node$I を`実装-$する。 ◎ Assert that target implements Node.
注記: この表明は、 この~APIが~supportする~event型たちに因り,満たされる。 ◎ Note: this assertion holds due to the types of events supported by the Event Timing API.
-
%計時~entry に`結付けられた~event~target$ ~SET %~target ◎ Set timingEntry’s associated eventTarget to target.
注記: これは、 `結付けられた~event~target$を最後の~event~targetに設定することになる。 なので、 `~targetし直す$が生じた場合、 最後の~target — `根$に最も近いもの — が利用されることになる。 ◎ Note: This will set eventTarget to the last event target. So if retargeting occurs, the last target, closest to the root, will be used.
- ~IF[ %~event の `type$m 属性の値 ~NIN { `keydown$et, `pointerdown$et } ] ⇒ %関連な大域~obj の`~queueされることになる~entry群$wに %計時~entry を`付加する$ ◎ If event’s type attribute value is not keydown nor pointerdown, append timingEntry to relevantGlobal’s entries to be queued.
-
~IF[ %~event の `type$m 属性の値 ~EQ `pointerdown$et ]: ◎ If event’s type attribute value is pointerdown:
- %処理待ちな~pointerdown~map ~LET %関連な大域~obj の`処理待ちな~pointerdown~map$w ◎ Let pendingPointerDowns be relevantGlobal’s pending pointer downs.
- %~pointer~ID ~LET %~event の `pointerId$m 属性の値 ◎ Let pointerId be event’s pointerId.
- %前回の~pointerdown~entry ~LET %処理待ちな~pointerdown~map[ %~pointer~ID ] ◎ ↓
- ~IF[ %前回の~pointerdown~entry ~NEQ ε ] ⇒ %関連な大域~obj の`~queueされることになる~entry群$wに %前回の~pointerdown~entry を`付加する$【!add】 ◎ If pendingPointerDowns[pointerId] exists: • Let previousPointerDownEntry be pendingPointerDowns[pointerId]. • Add previousPointerDownEntry to relevantGlobal’s entries to be queued.
- %処理待ちな~pointerdown~map[ %~pointer~ID ] ~SET %計時~entry ◎ Set pendingPointerDowns[pointerId] to timingEntry.
- %~window の`~contextmenuを誘発したか$w ~SET ~F ◎ Set window’s is contextmenu triggered to false.
-
~ELIF[ %~event の `type$m 属性の値 ~EQ `keydown$et ]: ◎ Otherwise, if event’s type attribute value is keydown:
-
~IF[ %~event の `isComposing$m 属性の値 ~EQ ~T ]: ◎ If event’s isComposing attribute value is true:
- %関連な大域~obj の`~queueされることになる~entry群$wに %計時~entry を`付加する$ ◎ Append timingEntry to relevantGlobal’s entries to be queued.
- ~RET ◎ Return.
- %処理待ちな~keydown~map ~LET %関連な大域~obj の`処理待ちな~keydown~map$w ◎ Let pendingKeyDowns be relevantGlobal’s pending key downs.
- %~code ~LET %~event の `keyCode$m 属性の値 ◎ Let code be event’s keyCode attribute value.
- %前回の~keydown~entry ~LET %処理待ちな~keydown~map[ %~code ] ◎ ↓
-
~IF[ %前回の~keydown~entry ~NEQ ε ]: ◎ If pendingKeyDowns[code] exists: • Let previousKeyDownEntry be pendingKeyDowns[code].
-
~IF[ %~code ~NEQ 229 ]: ◎ If code is not 229:
- %~window の`利用者ヤリトリ値$w 値 ~INCBY ~UAにより選ばれる小さな無符号整数 ◎ Increase window’s user interaction value value by a small number chosen by the user agent.
- %前回の~keydown~entry の `interactionId$mET ~SET %~window の`利用者ヤリトリ値$w ◎ Set previousKeyDownEntry’s interactionId to window’s user interaction value.
注記: 229 は、 ~IME~keyboard~eventに対応するので,特別な事例である。 ~UAは,この場合に複数の `keydown$et を送信することもあるが、 それは~UIkeyを押し続けることには対応しない。 ◎ Note: 229 is a special case since it corresponds to IME keyboard events. Sometimes multiple of these are sent by the user agent, and they do not correspond to holding a key down repeatedly.
- %~window の`~queueされることになる~entry群$wに %前回の~keydown~entry を`付加する$【!add】 ◎ Add previousKeyDownEntry to window’s entries to be queued.
-
- %処理待ちな~keydown~map[ %~code ] ~SET %計時~entry ◎ Set pendingKeyDowns[code] to timingEntry.
-
- ~ELSE ⇒ %関連な大域~obj の`~queueされることになる~entry群$w に %計時~entry を`付加する$ ◎ Otherwise: • Append timingEntry to relevantGlobal’s entries to be queued.
3.9. 処理待ちな各~event計時~entryを配送する
`処理待ちな各~event計時~entryを配送する@ ~algoは、 所与の ( `文書$ %文書 ) に対し: ◎ When asked to dispatch pending Event Timing entries for a Document doc, run the following steps:
- %~window ~LET %文書 に`関連な大域~obj$ ◎ Let window be doc’s relevant global object.
- %描画~時刻印 ~LET `現在の高分解能~時刻$ ◎ Let renderingTimestamp be the current high resolution time.
-
%~window の`~queueされることになる~entry群$wを成す ~EACH( %計時~entry ) に対し: ◎ For each timingEntry in window’s entries to be queued:
- `~event計時~entryの所要時間を設定する$( %計時~entry, %~window, %描画~時刻印 ) ◎ Set event timing entry duration passing timingEntry, window, and renderingTimestamp.
- ~IF[ %計時~entry の `duration$m 属性の値 ~GTE 16 ] ⇒ `処理能~entryを~queueする$( %計時~entry ) ◎ If timingEntry’s duration attribute value is greater than or equal to 16, then queue timingEntry.
- %~window の`~queueされることになる~entry群$wを`空にする$【!clear】 ◎ Clear window’s entries to be queued.
- %~window の`処理待ちな~pointerdown~map$wの`値~群$mapを成す ~EACH( %処理待ち~pointerdown~entry ) に対し ⇒ `~event計時~entryの所要時間を設定する$( %処理待ち~pointerdown~entry, %~window, %描画~時刻印 ) ◎ For each pendingPointerDownEntry in the values from window’s pending pointer downs: • Set event timing entry duration passing pendingDown, window, and renderingTimestamp.
- %~window の`処理待ちな~keydown~map$wの`値~群$mapを成す ~EACH( %処理待ち~keydown~entry ) に対し ⇒ `~event計時~entryの所要時間を設定する$( %処理待ち~keydown~entry, %~window, %描画~時刻印 ) ◎ For each pendingKeyDownEntry in the values from window’s pending key downs: • Set event timing entry duration passing pendingKeyDownEntry, window, and renderingTimestamp.
`~event計時~entryの所要時間を設定する@ ~algoは、 所与の ( `PerformanceEventTiming$I %計時~entry, `Window$I %~window, `DOMHighResTimeStamp$I %描画~時刻印 ) に対し: ◎ When asked to set event timing entry duration given a PerformanceEventTiming timingEntry, a Window window, and a DOMHighResTimeStamp renderingTimestamp, perform the following steps:
- ~IF[ %計時~entry の `duration$m 属性の値 ~NEQ 0 ] ⇒ ~RET ◎ If timingEntry’s duration attribute value is nonzero, return.
- %開始 ~LET %計時~entry の `startTime$m 属性の値 ◎ Let start be timingEntry’s startTime attribute value.
- %計時~entry の `duration$m ~SET ( %描画~時刻印 ~MINUS %開始 ) を 8ms 以下の粒度にした結果【すなわち,最も近い 8 の整数倍に丸めた結果】 ◎ Set timingEntry’s duration to a DOMHighResTimeStamp resulting from renderingTimestamp - start, with granularity of 8ms or less.
- %名前 ~LET %計時~entry の `name$m 属性の値 ◎ Let name be timingEntry’s name attribute value.
- ~Assert: %~window の`~event回数~map$w[ %名前 ] ~NEQ ε ◎ Perform the following steps to update the event counts: • Let eventCounts be window’s eventCounts. • Assert that eventCounts contains name.
- %~window の`~event回数~map$w[ %名前 ] ~INCBY 1 ◎ • Set eventCounts[name] to eventCounts[name] + 1.
-
~IF[ %~window の`入力~eventは配送-済みか$w ~EQ ~F ]~AND[ %計時~entry の `interactionId$mET 属性の値 ~NEQ 0 ]: ◎ If window’s has dispatched input event is false, and timingEntry’s interactionId is not 0, run the following steps:
- %初回~入力~entry ~SET %計時~entry の複製 ◎ Let firstInputEntry be a copy of timingEntry.
- %初回~入力~entry の `entryType$m ~SET `first-input^l ◎ Set firstInputEntry’s entryType to "first-input".
- `処理能~entryを~queueする$( %初回~入力~entry ) ◎ queue firstInputEntry.
- %~window の`入力~eventは配送-済みか$w ~SET ~T ◎ Set window’s has dispatched input event to true.
4. ~security/~privacyの考慮点
より高分解能な計時器は、 ~securityの懸念が必然的に伴われるので,~web~platformには導入したくない。 ~event~handlerの時刻印の正確度は、 `performance.now()$c と同じになる。 [ `processingStart$mET, `processingEnd$mET ]属性は,この~APIを利用しなくても算出できるので、 公開されても,新たな攻撃~表口は生産されない。 したがって、 更なる考慮が要求されるものは `duration$m 属性しかない。 ◎ We would not like to introduce more high resolution timers to the web platform due to the security concerns entailed by such timers. Event handler timestamps have the same accuracy as performance.now(). Since processingStart and processingEnd could be computed without using this API, exposing these attributes does not produce new attack surfaces. Thus, duration is the only one which requires further consideration.
`duration$m の粒度は 8ms である (丸めを遂行することにより,そのように算出される)。 したがって,高分解能な計時器は,この時刻印からは生産され得ない。 しかしながら,それは、 ~web開発者には可用でなかった新たな情報 — ~eventが処理された後に画素を描くまでの時間 — を導入する。 時刻印を公開することに対する[ ~security/~privacy ]の懸念は — とりわけ,この粒度の下では — 見出されていない。 粒度 8ms は、 有用になる新たな情報として必要最小限な量を公開する労の下で,裁定された。 これは、 120Hz ~displayにおいても,それなりに精確な計時を許容する。 ◎ The duration has an 8 millisecond granularity (it is computed as such by performing rounding). Thus, a high resolution timer cannot be produced from this timestamps. However, it does introduce new information that is not readily available to web developers: the time pixels draw after an event has been processed. We do not find security or privacy concerns on exposing the timestamp, especially given its granularity. In an effort to expose the minimal amount of new information that is useful, we decided to pick 8 milliseconds as the granularity. This allows relatively precise timing even for 120Hz displays.
`duration$m 用の既定の閾値 104ms は、 100ms 以上になる最~小な 8 の整数倍として選ばれた。 丸めらた後の所要時間が 104ms 以上になる~eventは、 丸められる前の所要時間が 100ms 以上であったことになる。 そのような~eventは、 100ms 以内には取扱われず,利用者~体験に負に影響iする見込みが高い。 ◎ The choice of 104ms as the default cutoff value for the duration is just the first multiple of 8 greater than 100ms. An event whose rounded duration is greater than or equal to 104ms will have its pre-rounded duration greater than or equal to 100ms. Such events are not handled within 100ms and will likely negatively impact user experience.
`durationThreshold$mb 用の最小~値 16ms は、 代表的な利用事例において応答が常に滑らかになることを可能化するので,許容される。 120Hz ~displayにおいては[ 複数の~frameを飛ばす応答は 16ms 以上になる【 8ms 以下にならない】 ]ので、 この~APIにおいては,[ この【どの?】利用者~入力に対応している~entryは,この最小~値の下では表面化される ]ことになる。 ◎ The choice of 16ms as the minimum value allowed for durationThreshold is because it enables the typical use-case of making sure that the response is smooth. In 120Hz displays, a response that skips more than a single frame will be at least 16ms, so the entry corresponding to this user input will be surfaced in the API under the minimum value.