11. ~worklet
11.1. 序論
◎非規範的~workletは、 特定0の実装~modelを要求することなく,~main~JS実行~環境とは独立に~scriptを走らすために利用できるような,仕様の基盤を成す~~部品である。 ◎ Worklets are a piece of specification infrastructure which can be used for running scripts independent of the main JavaScript execution environment, while not requiring any particular implementation model.
ここに指定される~worklet基盤は、 ~web開発者が直に利用できるものではない。 代わりに,この基盤の上に築かれる他の仕様が、 直に利用-可能な — ~browserの実装~pipelineを成す特定0の~~部位で走らすよう特化された — ~worklet型を作成する。 ◎ The worklet infrastructure specified here cannot be used directly by web developers. Instead, other specifications build upon it to create directly-usable worklet types, specialized for running in particular parts of the browser implementation pipeline.
11.1.1. 動機
◎非規範的描画, あるいは[ 音声~出力など,実装~pipelineを成す他の敏感な各部 ]に対し,拡張~地点を許容することは、 困難である。 拡張~地点で行われる何かに, `Window$I に可用な~APIへの全部的な~accessを与えた場合、 ~engineは,[ それら各~相の途中で何が起こり得るかについて,それまで保持していた前提 ]を放棄する必要があろう。 例えば,描画~engineは、 ~layout相の間は,~DOMは改変されないものと見做す。 ◎ Allowing extension points to rendering, or other sensitive parts of the implementation pipeline such as audio output, is difficult. If extension points were done with full access to the APIs available on Window, engines would need to abandon previously-held assumptions for what could happen in the middle of those phases. For example, during the layout phase, rendering engines assume that no DOM will be modified.
加えて, `Window$I 環境~内に拡張~地点を定義することは、 `Window$I ~objと同じ~thread内で作業を遂行するよう,~UAを制約することになる (実装が,複階的かつ~overheadが高い基盤 — ~thread~join時の保証( `thread joining guarantee^en )†に加えて, ~thread安全( `thread-safe^en )な~API††を許容するような基盤 — を追加しない限り)。 ◎ Additionally, defining extension points in the Window environment would restrict user agents to performing work in the same thread as the Window object. (Unless implementations added complex, high-overhead infrastructure to allow thread-safe APIs, as well as thread-joining guarantees.)
【† ある~threadを別の~threadが終了するまで待機するよう “~joinして” も, ~deadlockは生じない保証と思われる。 】【†† 当の~APIに複数の~threadから~accessされても,その結果は予測-可能になることと思われる。 】
~workletは、[ ~UAが現在~依拠している保証を保つ一方で,拡張~地点も許容する ]ように設計されている。 これは、 `WorkletGlobalScope$I の下位classたちに基づく,新たな大域~環境を通して行われる。 ◎ Worklets are designed to allow extension points, while keeping guarantees that user agents currently rely on. This is done through new global environments, based on subclasses of WorkletGlobalScope.
~workletは、 ~web~workerに類似する。 しかしながら,それらは: ◎ Worklets are similar to web workers. However, they:
- ~threadを問わない。 すなわち、[ 各~workerの様に,専用な別々の~thread内で走らす ]ように設計されてはいない。 実装は、 ~workletを自身が選ぶどこで走らすこともできる(~main~threadも含めて)。 ◎ Are thread-agnostic. That is, they are not designed to run on a dedicated separate thread, like each worker is. Implementations can run worklets wherever they choose (including on the main thread).
- 並列性の目的で、 複数個の[ 大域~scopeの~instance ]を重複して作成-可能である。 ◎ Are able to have multiple duplicate instances of the global scope created, for the purpose of parallelism.
- ~eventに基づく~APIを利用しない。 その代わり、 各~classは,大域~scopeに登録され、 その各~methodは,~UAにより呼出される。 ◎ Do not use an event-based API. Instead, classes are registered on the global scope, whose methods are invoked by the user agent.
-
大域~scope上に表面化される~APIは、 抑制される。 ◎ Have a reduced API surface on the global scope.
【 `WebIDL$r の用語で述べるなら、 `Exposed$ 拡張d属性を通して `WorkletGlobalScope$I に公開される~interfaceは, 他の大域~obj( `WorkerGlobalScope$I や `Window$I )に比して限られている。 】
- その`大域~obj$には存続期間がある。 それは、 他の仕様により定義され,`実装定義$な方式になることが多い。 ◎ Have a lifetime for their global object which is defined by other specifications, often in an implementation-defined manner.
~workletは、 ~overheadが他よりも高いので,控えめに利用することが最善である。 これに因り、 所与の `WorkletGlobalScope$I は,複数の別々な~scriptから共有されるものと期待される (これは、 単独の `Window$I が,複数の別々な~scriptから どう共有されるかに類似する)。 ◎ As worklets have relatively high overhead, they are best used sparingly. Due to this, a given WorkletGlobalScope is expected to be shared between multiple separate scripts. (This is similar to how a single Window is shared between multiple separate scripts.)
~workletは、 様々な利用事例を~serveする一般~技術である。 一部の~worklet — `CSSPAINT$r に定義されるものなど — が供する拡張~地点は、[ ~statelessかつ冪等かつ短く走る算出 ]用に意図される — それらには、 以下の少数の節に述べる特別な考慮点がある。 他の~worklet — `WEBAUDIO$r に定義されるものなど — は、[ ~statefulかつ長く走る演算 ]用に利用される。 ◎ Worklets are a general technology that serve different use cases. Some worklets, such as those defined in CSS Painting API, provide extension points intended for stateless, idempotent, and short-running computations, which have special considerations as described in the next couple of sections. Others, such as those defined in Web Audio API, are used for stateful, long-running operations. [CSSPAINT] [WEBAUDIO]
11.1.2. ~codeの冪等性
~workletを利用する一部の仕様は、 各~作業を[ 複数の~threadに並列化する/必要に応じて他の~threadへ移動する ]ことを~UAに許容するものと意図される。 そのような仕様においては、 ~UAは,~web開発者が供した~class上の~methodを`実装定義$な順序で呼出すかもしれない。 ◎ Some specifications which use worklets are intended to allow user agents to parallelize work over multiple threads, or to move work between threads as required. In these specifications, user agents might invoke methods on a web-developer-provided class in an implementation-defined order.
その結果による相互運用能の課題を防止するため、 そのような `WorkletGlobalScope$I に~classを登録する作者は, 自身の~codeが冪等になるようにするベキである。 すなわち,当の~class上の[ 各~method/~methodたちが成す組み ]は、 同じ入力に対し【副作用を伴うことなく】同じ出力を生産するベキである。 ◎ As a result of this, to prevent interoperability issues, authors who register classes on such WorkletGlobalScopes should make their code idempotent. That is, a method or set of methods on the class should produce the same output given a particular input.
この仕様は、 ~codeを冪等な仕方で書くよう作者に促すため,次に挙げる技法を利用する: ◎ This specification uses the following techniques in order to encourage authors to write code in an idempotent way:
-
当の大域~objへの参照は、 可用でない (すなわち, `WorkletGlobalScope$I には `self$m に相当するものは無い)。 ◎ No reference to the global object is available (i.e., there is no counterpart to self on WorkletGlobalScope).
これは,~workletが最初に仕様化されたときの意図nであったが、 `globalThis^c の導入により,もはや成立しなくなった。 さらなる論点は、 `課題 #6059@~HTMLissue/6059$ を見よ。 ◎ Although this was the intention when worklets were first specified, the introduction of globalThis has made it no longer true. See issue #6059 for more discussion.
- ~codeは`~module~script$として読込まれる。 その結果,~codeは、 厳密~mode【 `use strict^c 】の下で — [ 共有される,大域的な~proxyを参照している `this^c ]を伴うことなく — 実行される。 ◎ Code is loaded as a module script, which results in the code being executed in strict mode and with no shared this referencing the global proxy.
これらの制約は、 組みとして,[ 複数の異なる~scriptが,`大域~obj$の~propを利用して状態を共有する ]ことを防止する一助になる。 ◎ Together, these restrictions help prevent two different scripts from sharing state using properties of the global object.
加えて,~workletを利用する仕様は、 `実装定義$な挙動を許容するものと意図するならば,次を順守しなければナラナイ: ◎ Additionally, specifications which use worklets and intend to allow implementation-defined behavior must obey the following:
-
~UAに次を要求しなければナラナイ:
- 各 `Worklet$I 用に 2 個以上の `WorkletGlobalScope$I ~instanceが常に在ること
- ~class上の[ 各~method/~methodたちが成す組み ]を特定0の `WorkletGlobalScope$I ~instanceに~randomにアテガうこと
~memoryが拘束された下では,~opt-outを供しても 【これらの要件を~UAが~~任意で外せるようにしても】 ヨイ。
◎ They must require user agents to always have at least two WorkletGlobalScope instances per Worklet, and randomly assign a method or set of methods on a class to a particular WorkletGlobalScope instance. These specifications may provide an opt-out under memory constraints. - ~UAに次を許容しなければナラナイ ⇒ `WorkletGlobalScope$I 下位classの~instanceを,いつでも[ 作成する/破壊する ]こと ◎ These specifications must allow user agents to create and destroy instances of their WorkletGlobalScope subclasses at any time.
11.1.3. 投機的な評価
~workletを利用する一部の仕様は、[ ~web開発者が供した~class上の~method ]を~UAの状態に基づいて呼出し得る。 ~UAは,複数の~thread間の同時並行性を高めるためとして、 未来にあり得る状態に基づいて,~methodを投機的に呼出してもヨイ。 ◎ Some specifications which use worklets can invoke methods on a web-developer-provided class based on the state of the user agent. To increase concurrency between threads, a user agent may invoke a method speculatively, based on potential future states.
これらの仕様においては、 ~UAは,~methodを いつでも[ ~UAの現在の状態に対応するとは限らない引数たち ]を伴って呼出すかもしれない。 そのような投機的な評価の結果は、 即時には表示されないが,[ ~UAの状態が投機した状態に合致する場合 ]に利用できるよう~cacheできる。 これは、 ~UA【の~main~thread】と~worklet~thread間の同時並行性を高め得る。 ◎ In these specifications, user agents might invoke such methods at any time, and with any arguments, not just ones corresponding to the current state of the user agent. The results of such speculative evaluations are not displayed immediately, but can be cached for use if the user agent state matches the speculated state. This can increase the concurrency between the user agent and worklet threads.
この結果として各~UA間の相互運用能が得られなくなる~riskを防止するため、 そのような `WorkletGlobalScope$I に~classを登録する作者は,自身の~codeが~statelessになる — すなわち,ある~methodを呼出すことによる効果は、 それが返す結果に限られ,変異-可能な状態を更新するなどの副作用は無い — ようにするベキである。 ◎ As a result of this, to prevent interoperability risks between user agents, authors who register classes on such WorkletGlobalScopes should make their code stateless. That is, the only effect of invoking a method should be its result, and not any side effects such as updating mutable state.
`~codeの冪等性@#worklets-idempotent$を促す技法も、 ~statelessな~codeを書くことを,作者に促す。 ◎ The same techniques which encourage code idempotence also encourage authors to write stateless code.
11.2. 例
◎非規範的ここでは、 以下に与える各~例~用に,ある~fake~workletを利用する。 各 `Window$I ~objは、 2 個の `Worklet$I ~instanceを供する — それぞれが,自前の[ `FakeWorkletGlobalScope$I たちが成す~collection ]内で~codeを走らすことになる: ◎ For these examples, we'll use a fake worklet. The Window object provides two Worklet instances, which each run code in their own collection of FakeWorkletGlobalScopes:
partial interface `Window$I { [SameObject, SecureContext] readonly attribute `Worklet$I `fakeWorklet1$m; [SameObject, SecureContext] readonly attribute `Worklet$I `fakeWorklet2$m; };
各 `Window$I は, 2 個の `Worklet$I ~instance[ `fake-worklet-1@ `fake-worklet-2@ ]を有するとする — どちらも,[ その`~worklet大域~scope型$wL は `FakeWorkletGlobalScope$I, その`~worklet行先~種別$wL は `fakeworklet^l ]に設定されるとする。 ~UAは、 各~worklet用に `FakeWorkletGlobalScope$I ~instanceを 2 個以上~作成するベキである。 ◎ Each Window has two Worklet instances, fake worklet 1 and fake worklet 2. Both of these have their worklet global scope type set to FakeWorkletGlobalScope, and their worklet destination type set to "fakeworklet". User agents should create at least two FakeWorkletGlobalScope instances per worklet.
注記: `fakeworklet^l は,実際には `FETCH$r に従う妥当な`行先$rqではないが、 これは, 本物の~workletが[ 自前の,~worklet型に特有な行先 ]を[ 一般に,どう有することになるか ]を~~説明する。 ◎ "fakeworklet" is not actually a valid destination per Fetch. But this illustrates how real worklets would generally have their own worklet-type-specific destination. [FETCH]
[Global=(Worklet,FakeWorklet), Exposed=FakeWorklet, SecureContext] interface `FakeWorkletGlobalScope@I : `WorkletGlobalScope$I { undefined `registerFake$m(DOMString %type, `Function$I %classConstructor); };
各 `FakeWorkletGlobalScope$I は、 `登録-済み~class構築子~map@ を有する — それは、 `有順序~map$であり,初期~時は空とする。 ◎ Each FakeWorkletGlobalScope has a registered class constructors map, which is an ordered map, initially empty.
11.2.1. ~scriptの読込ng
◎非規範的~web開発者は、 `fake-worklet-1$の中へ~scriptを読込むために,次を書くことになろう: ◎ To load scripts into fake worklet 1, a web developer would write:
window.fakeWorklet1.addModule('script1.mjs'); window.fakeWorklet1.addModule('script2.mjs');
どちらの~scriptが,最初に~fetchingを完遂して走ることになるかは、 ~networkにかかる時間に依存することに注意。 それは、 `script1.mjs^c, `script2.mjs^c どちらにもなり得る。 このことは、[ ~worklet内に読込まれるものと意図された各~script ]が[ `投機的な評価@#worklets-speculative$用に準備することについての示唆に従う 【すなわち,~statelessになる】 ]よう きちんと書かれたならば,一般に問われることはない。 ◎ Note that which script finishes fetching and runs first is dependent on network timing: it could be either script1.mjs or script2.mjs. This generally won't matter for well-written scripts intended to be loaded in worklets, if they follow the suggestions about preparing for speculative evaluation.
~web開発者は、 ある~taskを[ 当の各~scriptが,いずれも、 成功裡に走って,何らかの~workletの中に読込まれた ]後に限り遂行するよう求めるならば,次のように書くこともできる: ◎ If a web developer wants to perform a task only after the scripts have successfully run and loaded into some worklets, they could write:
Promise.all([
window.fakeWorklet1.addModule('script1.mjs'),
window.fakeWorklet2.addModule('script2.mjs')
]).then(() => {
/*
[
どの~scriptも読込まれたこと
]に依拠する何かを行う。
◎
Do something which relies on those scripts being loaded.
*/
});
~scriptの読込ngについての別の重要な点は、 `§ ~codeの冪等性@#worklets-idempotent$にて論じたとおり,[ 読込まれた~scriptを走らす `WorkletGlobalScope$I は, `Worklet$I ごとに複数個あり得る ]ことである。 特に,上の[ `fake-worklet-1$, `fake-worklet-2$ ]用の仕様は、 これを要求する。 次のような局面を考える: ◎ Another important point about script-loading is that loaded scripts can be run in multiple WorkletGlobalScopes per Worklet, as discussed in the section on code idempotence. In particular, the specification above for fake worklet 1 and fake worklet 2 require this. So, consider a scenario such as the following:
// script.mjs console.log("Hello from a FakeWorkletGlobalScope!");
// app.mjs window.fakeWorklet1.addModule("script.mjs");
その結果、 ~UAの~consoleには次も出力され得る: ◎ This could result in output such as the following from a user agent's console:
[fakeWorklet1#1] Hello from a FakeWorkletGlobalScope! [fakeWorklet1#4] Hello from a FakeWorkletGlobalScope! [fakeWorklet1#2] Hello from a FakeWorkletGlobalScope! [fakeWorklet1#3] Hello from a FakeWorkletGlobalScope!
~UAが,ある時点で[ `FakeWorkletGlobalScope$I の 3 個目の~instanceを~killして開始し直す ]ものと裁定した場合、 ~consoleは,その開始-時に【!これが生じたとき】再び次を出力することになる ⇒ `[fakeWorklet1#3] Hello from a FakeWorkletGlobalScope!^c ◎ If the user agent at some point decided to kill and restart the third instance of FakeWorkletGlobalScope, the console would again print [fakeWorklet1#3] Hello from a FakeWorkletGlobalScope! when this occurs.
11.2.2. ~classの登録-法と その~methodの呼出ng
◎非規範的~fake~workletに意図される ある用法は、[ ~~高度に複階的な処理nを成す一部 (この例では、 ある真偽値を “~~反転する” だけでしかないが) を~custom化すること ]を[ ~web開発者に許容すること ]であるとする。 ~web開発者は、 そのような~custom化を,次のように登録するであろう: ◎ Let's say that one of the intended usages of our fake worklet by web developers is to allow them to customize the highly-complex process of boolean negation. They might register their customization as follows:
// script.mjs registerFake('negation-processor', class { process(%arg) { return !%arg; } });
// app.mjs window.fakeWorklet1.addModule("script.mjs");
そのように登録された~classを用立てるため、 ~fake~worklet用の仕様は, ~T の~~反転を見出す~algo を定義することもできる — それは、 所与の ( `Worklet$I %~worklet ) に対し: ◎ To make use of such registered classes, the specification for fake worklets could define a find the opposite of true algorithm, given a Worklet worklet:
- 任意選択で ⇒ `~worklet大域~scopeを作成する$( %~worklet ) ◎ Optionally, create a worklet global scope for worklet.
- %~worklet大域~scope ~LET `実装定義$な方式で選ばれる, %~worklet の`大域~scope~list$wL内の いずれかの~item ◎ Let workletGlobalScope be one of worklet's global scopes, chosen in an implementation-defined manner.
- %~class構築子 ~LET %~worklet大域~scope の`登録-済み~class構築子~map$[ `negation-processor^l ] ◎ Let classConstructor be workletGlobalScope's registered class constructors map["negation-processor"].
- %~class~instance ~LET `~callback関数で構築する$( %~class構築子, « » ) ◎ Let classInstance be the result of constructing classConstructor, with no arguments.
- %関数 ~LET `Get$jA( %~class~instance, `process^l ) (例外が投出され得る) ◎ Let function be Get(classInstance, "process"). Rethrow any exceptions.
- %~callback ~LET `~IDL値に変換する$( %関数, `Function$I ) ◎ Let callback be the result of converting function to a Web IDL Function instance.
- ~RET `~callback関数を呼出す$( %~callback, « ~T », `投出し直す^i, %~class~instance ) ◎ Return the result of invoking callback with « true » and "rethrow", and with callback this value set to classInstance.
注記: たぶん,次のようにした方が、 別の,もっと良い仕様~architectureになろう ⇒ `registerFake()$m ~method手続きを成す一部として、 登録~時に `process^l ~propを抽出して `Function$I に変換する。 ◎ Another, perhaps better, specification architecture would be to extract the "process" property and convert it into a Function at registration time, as part of the registerFake() method steps.
11.3. 基盤
11.3.1. 大域~scope
`WorkletGlobalScope$I の下位classは、 `大域~obj$ — 特定0の `Worklet$I の中へ読込まれた~codeを その中で実行できるような,それ — を作成するために利用される。 【そのような各 下位classは、 “~worklet型” とも総称される。】 ◎ Subclasses of WorkletGlobalScope are used to create global objects wherein code loaded into a particular Worklet can execute.
[Exposed=Worklet, SecureContext] interface `WorkletGlobalScope@I {};
注記: 他の仕様は、 `WorkletGlobalScope$I を下位class化して,~classを登録するための~APIを — 当の~worklet型に特有な他の~APIに加えて — 追加するものと意図される。 ◎ Other specifications are intended to subclass WorkletGlobalScope, adding APIs to register a class, as well as other APIs specific for their worklet type.
各 `WorkletGlobalScope$I には `~module~map@wL が結付けられる。 それは、 `~module~map$であり,初期~時は空とする。 ◎ Each WorkletGlobalScope has an associated module map. It is a module map, initially empty.
11.3.1.1. ~agentと~event~loop
◎非規範的各 `WorkletGlobalScope$I は、 自前の`~worklet~agent$内に包含され,それには対応する`~event~loop$aGがある。 しかしながら,実施においては、 これらの~agentと~event~loopの実装は,他のほとんどのそれらとは異なるものになると予期される。 ◎ Each WorkletGlobalScope is contained in its own worklet agent, which has its corresponding event loop. However, in practice, implementation of these agents and event loops is expected to be different from most others.
各 `WorkletGlobalScope$I 用には,ある`~worklet~agent$が存在する — 理論~上は,実装は[ `WorkletGlobalScope$I の各~instanceごとに別々の~threadを利用する ]こともでき、 この~levelの並列性は,~agentを利用して許容するのが最善になるので。 しかしながら,それら~agentの `CanBlock^sl の値は ~F になるので、 各~agentと各~threadが一対一になるとする要件は無い。 これは、 ~workletの中に読込まれる~scriptを どの~thread上でも実行する自由度を実装に許容する — [ `CanBlock^sl の値が ~F をとるような,他の~agent ]からの~codeを走らせているものも含め (`生成元が類似な~window~agent$用の~thread( “~main~thread” )など)。 対照的に,`専用~worker~agent$は、 `CanBlock^sl の値が ~T になるので,実質的に[ 専用な~OS~threadを取得する ]ことが要求される。 ◎ A worklet agent exists for each WorkletGlobalScope since, in theory, an implementation could use a separate thread for each WorkletGlobalScope instance, and allowing this level of parallelism is best done using agents. However, because their [[CanBlock]] value is false, there is no requirement that agents and threads are one-to-one. This allows implementations the freedom to execute scripts loaded into a worklet on any thread, including one running code from other agents with [[CanBlock]] of false, such as the thread of a similar-origin window agent ("the main thread"). Contrast this with dedicated worker agents, whose true value for [[CanBlock]] effectively requires them to get a dedicated operating system thread.
~worklet`~event~loop$は、 いくぶん特別でもあり,次に該当する`~task$用に限り利用される ⇒# `addModule()$m で結付けられるもの/ その中で~UAが作者が定義した~methodを呼出すもの/ `小task$ ◎終 したがって、 `~event~loop処理~model$は[ すべての~event~loopを継続的に走らす ]ものと指定しているが, 実装は[ もっと単純な策 ]を利用して[ 観測される結果が等価になること ]を達成できる — 単に,作者が供した~methodを`呼出して@~WEBIDLjs#invoke-a-callback-function$、 その処理nが`小task~checkpointを遂行する$ことに依拠するような。 ◎ Worklet event loops are also somewhat special. They are only used for tasks associated with addModule(), tasks wherein the user agent invokes author-defined methods, and microtasks. Thus, even though the event loop processing model specifies that all event loops run continuously, implementations can achieve observably-equivalent results using a simpler strategy, which just invokes author-provided methods and then relies on that process to perform a microtask checkpoint.
11.3.1.2. 作成と終了n
`~worklet大域~scopeを作成する@ ときは、 所与の ( `Worklet$I %~worklet ) に対し: ◎ To create a worklet global scope for a Worklet worklet:
- %外側~設定群 ~LET %~worklet に`関連な設定群~obj$ ◎ Let outsideSettings be worklet's relevant settings object.
- %~agent ~LET `~worklet~agentを得する$( %外側~設定群 ) ◎ Let agent be the result of obtaining a worklet agent given outsideSettings.\
- この手続きの以降は、 %~agent 内で走らすようにする ◎ Run the rest of these steps in that agent.
-
%~realm実行~文脈 ~LET `新たな~realmを作成する$( %~agent ) — 次に従って~custom化する下で ⇒ 大域~obj用には、[ %~worklet の`~worklet大域~scope型$wL ]の新たな~objを作成する ◎ Let realmExecutionContext be the result of creating a new realm given agent and the following customizations: • For the global object, create a new object of the type given by worklet's worklet global scope type.
- %~worklet大域~scope ~LET %~realm実行~文脈 の~Realm成分の`大域~obj$rM ◎ Let workletGlobalScope be the global object of realmExecutionContext's Realm component.
- %内側~設定群 ~LET `~workletの環境~設定群~objを設定しておく$( %~realm実行~文脈, %外側~設定群 ) ◎ Let insideSettings be the result of setting up a worklet environment settings object given realmExecutionContext and outsideSettings.
- %処理待ちな追加された~module群 ~LET %~worklet の`追加された~module~list$wLを`~cloneする$ ◎ Let pendingAddedModules be a clone of worklet's added modules list.
-
%その次の追加された~moduleを走らす ~LET 次を走らす手続き: ◎ Let runNextAddedModule be the following steps:
-
~IF[ %処理待ちな追加された~module群 は`空$でない ]: ◎ If pendingAddedModules is not empty, then:
- %~module~URL ~LET %処理待ちな追加された~module群 から`~dequeueする$ ◎ Let moduleURL be the result of dequeueing from pendingAddedModules.
-
`~worklet~script~graphを~fetchする$( ↓ ) ⇒# %~module~URL, %内側~設定群, %~worklet の`~worklet行先~種別$wL, 資格証~modeは何か?, %内側~設定群, %~worklet の`~module応答~map$wL, 次の手続き ◎ Fetch a worklet script graph given moduleURL, insideSettings, worklet's worklet destination type, what credentials mode?, insideSettings, worklet's module responses map, and with\
手続きは、 所与の ( `~module~script$ %~script ) に対し: ◎ the following steps given script:
注記: これは、 ~network要請を実際に遂行することはない — %~worklet の`~module応答~map$wL内の`応答$を再利用するだけなので。 この段の主~目的は、 この`応答$から[ %~worklet大域~scope に特有な,新たな`~module~script$ ]を作成することにある。 ◎ This will not actually perform a network request, as it will just reuse responses from worklet's module responses map. The main purpose of this step is to create a new workletGlobalScope-specific module script from the response.
- ~Assert: %~script ~NEQ ~NULL — %~worklet の`~module応答~map$wLが初期~時に %~module~URL で拡充された時点で、 ~fetchは成功して,~source~textは成功裡に構文解析されたはずなので。 ◎ Assert: script is not null, since the fetch succeeded and the source text was successfully parsed when worklet's module responses map was initially populated with moduleURL.
- `~module~scriptを走らす$( %~script ) ◎ Run a module script given script.
- %その次の追加された~moduleを走らす() ◎ Run runNextAddedModule.
- ~RET ◎ Abort these steps.
- %外側~設定群 の`大域~obj$enVに`結付けられた文書$の`~worklet大域~scope~list$doc に %~worklet大域~scope を`付加する$ ◎ Append workletGlobalScope to outsideSettings's global object's associated Document's worklet global scopes.
- %~worklet の`大域~scope~list$wLに %~worklet大域~scope を`付加する$ ◎ Append workletGlobalScope to worklet's global scopes.
- %内側~設定群 により指定される`担当の~event~loop$enVを走らす ◎ Run the responsible event loop specified by insideSettings.
-
- %その次の追加された~moduleを走らす() ◎ Run runNextAddedModule.
`~worklet大域~scopeを終了させる@ ときは、 所与の ( `WorkletGlobalScope$I %~worklet大域~scope ) に対し: ◎ To terminate a worklet global scope given a WorkletGlobalScope workletGlobalScope:
- %~event~loop ~LET %~worklet大域~scope に`関連な~agent$の`~event~loop$aG ◎ Let eventLoop be workletGlobalScope's relevant agent's event loop.
- %~event~loop の`~task~queue$内に~queueされた`~task$すべてを — 処理することなく — 破棄する ◎ If there are any tasks queued in eventLoop's task queues, discard them without processing them.
- %~event~loop の`現在~走っている~task$が完了するまで待機する ◎ Wait for eventLoop to complete the currently running task.
- ~IF[ 前~段は、 `実装定義$な期間~内に完了しなかった ] ⇒ 当の~worklet内で現在`走っている~scriptを中止する$ ◎ If the previous step doesn't complete within an implementation-defined period of time, then abort the script currently running in the worklet.
- %~event~loop を破壊する ◎ Destroy eventLoop.
- %~worklet大域~scope を それを包含している[ `Worklet$I の`大域~scope~list$wL ]から`除去する$ ◎ Remove workletGlobalScope from the global scopes of the Worklet whose global scopes contains workletGlobalScope.
- %~worklet大域~scope を それを包含している[ `文書$の`~worklet大域~scope~list$doc ]から`除去する$ ◎ Remove workletGlobalScope from the worklet global scopes of the Document whose worklet global scopes contains workletGlobalScope.
11.3.1.3. ~worklet用の~script設定群
`~workletの環境~設定群~objを設定しておく@ ときは、 所与の ( `~JS実行~文脈$ %実行~文脈, `環境~設定群~obj$ %外側~設定群 ) に対し: ◎ To set up a worklet environment settings object, given a JavaScript execution context executionContext and an environment settings object outsideSettings:
- %生成元 ~LET 一意かつ`不透明な生成元$ ◎ Let origin be a unique opaque origin.
- %継承される~API用~基底~URL ~LET %外側~設定群 の`~API用~基底~URL$enV ◎ Let inheritedAPIBaseURL be outsideSettings's API base URL.
- %継承される施策~容器 ~LET `施策~容器を~cloneする$( %外側~設定群 の`施策~容器$enV ) ◎ Let inheritedPolicyContainer be a clone of outsideSettings's policy container.
- %~realm ~LET %実行~文脈 の~Realm成分の値 ◎ Let realm be the value of executionContext's Realm component.
- %~worklet大域~scope ~LET %~realm の`大域~obj$rM ◎ Let workletGlobalScope be realm's global object.
-
%設定群~obj ~LET 新たな`環境~設定群~obj$ — その各種~algoは、 次に従って定義される: ◎ Let settingsObject be a new environment settings object whose algorithms are defined as follows:
- `~realm実行~文脈$enV ⇒ ~RET %実行~文脈 ◎ The realm execution context • Return executionContext.
- `~module~map$enV ⇒ ~RET %~worklet大域~scope の`~module~map$wL ◎ The module map • Return workletGlobalScope's module map.
-
`~API用~基底~URL$enV ⇒ ~RET %継承される~API用~基底~URL ◎ The API base URL • Return inheritedAPIBaseURL.
注記: [ ~worker/単独の資源から導出される他の大域~obj ]と違って、 ~workletには首な資源は無い — 代わりに,それぞれ自前の~URLを伴う複数の~scriptが、 `addModule()$m を介して大域~scopeの中に読込まれる。 なので、 この`~API用~基底~URL$enVは,他の大域~obj用のそれとは違ったものになる。 しかしながら,[ `~API用~基底~URL$enVを用立てる~APIとして~worklet~codeに可用になるもの ]は無いので、 これが問われることはない。 ◎ Unlike workers or other globals derived from a single resource, worklets have no primary resource; instead, multiple scripts, each with their own URL, are loaded into the global scope via worklet.addModule(). So this API base URL is rather unlike that of other globals. However, so far this doesn't matter, as no APIs available to worklet code make use of the API base URL.
- `生成元$enV ⇒ ~RET %生成元 ◎ The origin • Return origin.
- `施策~容器$enV ⇒ ~RET %継承される施策~容器 ◎ The policy container • Return inheritedPolicyContainer.
- `非同一-生成元~能力は隔離されるか?$enV ⇒ ~RET 未策定 ◎ The cross-origin isolated capability • Return TODO.
- `時刻~起点$enV ⇒ ~Assert: この~algoは、 決して~callされない — `時刻~起点$enVは、 ~worklet文脈においては可用でないので。 ◎ The time origin • Assert: this algorithm is never called, because the time origin is not available in a worklet context.
- %設定群~obj の ⇒# `~ID$enV ~SET 新たな一意かつ不透明な文字列, `作成時の~URL$enV ~SET %継承される~API用~基底~URL, `~top-level作成時の~URL$enV ~SET ~NULL, `~top-level生成元$enV ~SET %外側~設定群 の`~top-level生成元$enV, `~target閲覧~文脈$enV ~SET ~NULL, `作動中な~sw$enV ~SET ~NULL ◎ Set settingsObject's id to a new unique opaque string, creation URL to inheritedAPIBaseURL, top-level creation URL to null, top-level origin to outsideSettings's top-level origin, target browsing context to null, and active service worker to null.
- %~realm の `HostDefined^sl ~field ~SET %設定群~obj ◎ Set realm's [[HostDefined]] field to settingsObject.
- ~RET %設定群~obj ◎ Return settingsObject.
11.3.2. `Worklet^I ~class
`Worklet$I ~classは、 それに結付けられる各 `WorkletGlobalScope$I の中へ`~module~script$を追加する能力を供する。 ~UAは、 `WorkletGlobalScope$I に登録された各~classを作成して,それらの~methodを呼出せる。 ◎ The Worklet class provides the capability to add module scripts into its associated WorkletGlobalScopes. The user agent can then create classes registered on the WorkletGlobalScopes and invoke their methods.
[Exposed=Window, SecureContext] interface `Worklet@I { [NewObject] `Promise$<undefined> `addModule$m(USVString %moduleURL, optional `WorkletOptions$I %options = {}); }; dictionary `WorkletOptions@I { `RequestCredentials$I `credentials@m = "same-origin"; };
`Worklet$I ~instanceを作成する仕様は、 所与の各~instanceが有するものとして,次を指定しなければナラナイ: ◎ Specifications that create Worklet instances must specify the following for a given instance:
- `~worklet大域~scope型@wL ◎ its worklet global scope type,\
- `WorkletGlobalScope$I を`継承-$する~Web~IDL型でなければナラナイ。 ◎ which must be a Web IDL type that inherits from WorkletGlobalScope; and
- `~worklet行先~種別@wL ◎ its worklet destination type,\
- ~scriptを~fetchするときに利用される`行先$rqでなければナラナイ。 ◎ which must be a destination, and is used when fetching scripts.
- await %worklet.`addModule$m(%moduleURL[, { `credentials$m }])
- %moduleURL に与えられた`~module~script$を[ %worklet の`大域~scope~list$wLを成すすべて ]の中へ読込んで実行する。 また、 ~worklet型に依存して, この処理nを成す一部として,追加的な大域~scopeも作成し得る。 返される~promiseは、 ~scriptが成功裡に[ 読込まれ,すべての大域~scope内で走った ]とき充足されることになる。 ◎ Loads and executes the module script given by moduleURL into all of worklet's global scopes. It can also create additional global scopes as part of this process, depending on the worklet type. The returned promise will fulfill once the script has been successfully loaded and run in all global scopes.
- `credentials$m ~optionは、 既定では `same-origin^l になる — 他の`資格証~mode$rqに設定することで、 ~scriptを~fetchする処理nを改変できる。 ◎ The credentials option can be set to a credentials mode to modify the script-fetching process. It defaults to "same-origin".
-
返される~promiseは、[ ~script, または その依存物のうちいずれか ]において次のいずれかが生じた場合には,却下されることになる:
- `~fetch時@~WAPI#fetch-a-worklet-script-graph$における失敗に対しては、 `AbortError$E 例外で
- 構文解析-時の~errorに対しては、 それにより生成される例外で
各 `Worklet$I は、 次に挙げるものを有する: ◎ ↓
- `大域~scope~list@wL ◎ A Worklet has a list of global scopes,\
- [ 当の `Worklet$I の`~worklet大域~scope型$wL ]の~instanceたちが成す`~list$ — 初期~時は空とする。 ◎ which contains instances of the Worklet's worklet global scope type. It is initially empty.
- `追加された~module~list@wL ◎ A Worklet has an added modules list,\
- `~URL$たちが成す`~list$ — 初期~時は空とする。 ◎ which is a list of URLs, initially empty.\
- この~listへの~accessは、 ~thread安全になるベキである。 ◎ Access to this list should be thread-safe.
- `~module応答~map@wL ◎ A Worklet has a module responses map,\
-
`有順序~map$ — 初期~時は空とする。 この~mapを成す各~entryの:
- ~keyは、 ある`~URL$を与える
-
値は、[ `fetching^l / 次の 2 つからなる`~tuple$ ]を与える:
- ある`応答$
- ~NULL / `失敗^i / 当の応答の本体を表現している`~byte列$
- この~mapへの~accessは、 ~thread安全になるベキである。 ◎ and access to it should be thread-safe.
[ `追加された~module~list$wL, `~module応答~map$wL ]は、[ 異なる時点に作成される各 `WorkletGlobalScope$I が, 同じ~source~textに基づく等価な`~module~script$を走らすようになる ]ことを確保するために存在する。 これは、 作者からは透過的な,追加的な `WorkletGlobalScope$I の作成を許容する。 ◎ The added modules list and module responses map exist to ensure that WorkletGlobalScopes created at different times get equivalent module scripts run in them, based on the same source text. This allows the creation of additional WorkletGlobalScopes to be transparent to the author.
これらの~data構造は、 実施において[ それらを実装すること/ それらに諮る~algoが,~thread安全な~programming技法を利用すること ]は,~UAに期待されてはいない。 代わりに,~UAは、 `addModule()$m が~callされたとき,次を順に行える: ◎ In practice, user agents are not expected to implement these data structures, and the algorithms that consult them, using thread-safe programming techniques. Instead, when addModule() is called, user agents can\
- ~main~thread上で~module~graphを~fetchして、 ~fetchした~source~text (すなわち,`~module応答~map$wL内に包含される重要な~data) を `WorkletGlobalScope$I を有する各~threadへ送信する。 ◎ fetch the module graph on the main thread, and send the fetched source text (i.e., the important data contained in the module responses map) to each thread which has a WorkletGlobalScope.
- ~UAが所与の `Worklet$I 用に新たな `WorkletGlobalScope$I %大域~scope を`作成-$wLしたとき、 単純に[ ~fetchした~source~textが成す~map, 入口~地点たちが成す~list ]を~main~threadから[ %大域~scope を包含している~thread ]へ送信する。 ◎ Then, when a user agent creates a new WorkletGlobalScope for a given Worklet, it can simply send the map of fetched source text and the list of entry points from the main thread to the thread containing the new WorkletGlobalScope.
`addModule(moduleURL, options)@m ~method手続きは: ◎ The addModule(moduleURL, options) method steps are:
- %外側~設定群 ~LET コレに`関連な設定群~obj$ ◎ Let outsideSettings be the relevant settings object of this.
- %~module~URL~record ~LET `~URLを符号化法の下で相対的に構文解析する$( %moduleURL, %外側~設定群 ) ◎ Let moduleURLRecord be the result of encoding-parsing a URL given moduleURL, relative to outsideSettings.
- ~IF[ %~module~URL~record ~EQ `失敗^i ] ⇒ ~RET `却下される~promise$( `SyntaxError$E 例外 ) ◎ If moduleURLRecord is failure, then return a promise rejected with a "SyntaxError" DOMException.
- %~promise ~LET `新たな~promise$ ◎ Let promise be a new promise.
-
この段は、 `並列的$に走らす: ◎ Run the following steps in parallel:
-
~IF[ コレの`大域~scope~list$wLは`空$である ]: ◎ If this's global scopes is empty, then:
- `~worklet大域~scopeを作成する$( コレ ) ◎ Create a worklet global scope given this.
- 任意選択で ⇒ [ 当の特定の~worklet, その仕様 ]に依存して,何個かの大域~scopeの~instanceを追加的に`作成-$wLする ◎ Optionally, create additional global scope instances given this, depending on the specific worklet in question and its specification.
- `作成-$wLする処理n(たち)を成す手続きすべてが完了するまで待機する — `~worklet~agent$の中で場を占める段も含めて ◎ Wait for all steps of the creation process(es) — including those taking place within the worklet agents — to complete, before moving on.
- %処理待ち~task数 ~LET コレの`大域~scope~list$wLの`~size$ ◎ Let pendingTasks be this's global scopes's size.
- %成功裡に追加されたか ~LET ~F ◎ Let addedSuccessfully be false.
-
コレの`大域~scope~list$wLを成す ~EACH( %~worklet大域~scope ) に対し ⇒ `大域~taskを~queueする$( `~network用~task~source$, %~worklet大域~scope, 次の手続き ) ◎ For each workletGlobalScope of this's global scopes, queue a global task on the networking task source given workletGlobalScope to\
手続きは ⇒ `~worklet~script~graphを~fetchする$( ↓ ) ⇒# %~module~URL~record, %外側~設定群, コレの`~worklet行先~種別$wL, %options[ "`credentials$m" ], %~worklet大域~scope に`関連な設定群~obj$, コレの`~module応答~map$wL, 次の手続き ◎ fetch a worklet script graph given moduleURLRecord, outsideSettings, this's worklet destination type, options["credentials"], workletGlobalScope's relevant settings object, this's module responses map, and the following steps given script:
注記: これらの~fetchのうち,~network要請を実際に遂行することになるものは、 最初のものに限られる — 他の `WorkletGlobalScope$I 用のそれらは、 コレの`~module応答~map$wLからの`応答$を再利用することになる。 ◎ Only the first of these fetches will actually perform a network request; the ones for other WorkletGlobalScopes will reuse responses from this's module responses map.
手続きは: ◎ ↑
-
~IF[ %~script ~EQ ~NULL ]: ◎ If script is null, then:
-
`大域~taskを~queueする$( `~network用~task~source$, コレに`関連な大域~obj$, 次の手続き ): ◎ Queue a global task on the networking task source given this's relevant global object to perform\
手続きは: ◎ the following steps:
-
~IF[ %処理待ち~task数 ~NEQ −1 ]: ◎ If pendingTasks is not −1, then:
- %処理待ち~task数 ~SET −1 ◎ Set pendingTasks to −1.
- `~promiseを却下する$( %~promise, `AbortError$E 例外 ) ◎ Reject promise with an "AbortError" DOMException.
-
- ~RET ◎ Abort these steps.
-
-
~IF[ %~script の`再投出-用~error$sC ~NEQ ~NULL ]: ◎ If script's error to rethrow is not null, then:
-
`大域~taskを~queueする$( `~network用~task~source$, コレに`関連な大域~obj$, 次の手続き ): ◎ Queue a global task on the networking task source given this's relevant global object to perform\
手続きは: ◎ the following steps:
-
~IF[ %処理待ち~task数 ~NEQ −1 ]: ◎ If pendingTasks is not −1, then:
- %処理待ち~task数 ~SET −1 ◎ Set pendingTasks to −1.
- `~promiseを却下する$( %~promise, %~script の`再投出-用~error$sC ) ◎ Reject promise with script's error to rethrow.
-
- ~RET ◎ Abort these steps.
-
-
~IF[ %成功裡に追加されたか ~EQ ~F ]: ◎ If addedSuccessfully is false, then:
- コレの`追加された~module~list$wLに %~module~URL~record を`付加する$ ◎ Append moduleURLRecord to this's added modules list.
- %成功裡に追加されたか ~SET ~T ◎ Set addedSuccessfully to true.
- `~module~scriptを走らす$( %~script ) ◎ Run a module script given script.
-
`大域~taskを~queueする$( `~network用~task~source$, コレに`関連な大域~obj$, 次の手続き ) ◎ Queue a global task on the networking task source given this's relevant global object to perform\
手続きは: ◎ the following steps:
-
~IF[ %処理待ち~task数 ~NEQ −1 ]: ◎ If pendingTasks is not −1, then:
- %処理待ち~task数 ~DECBY 1 ◎ Set pendingTasks to pendingTasks − 1.
- ~IF[ %処理待ち~task数 ~EQ 0 ] ⇒ `~promiseを解決する$( %~promise ) ◎ If pendingTasks is 0, then resolve promise.
-
-
-
- ~RET %~promise ◎ Return promise.
11.3.3. ~workletの存続期間
`Worklet$I の存続期間には、 特別な考慮点は無い — 存続期間は、 当の `Worklet$I が属する~obj( `Window$I など)に束ねられる。 ◎ The lifetime of a Worklet has no special considerations; it is tied to the object it belongs to, such as the Window.
各`文書$は、 `~worklet大域~scope~list@doc を有する — それは,何個かの `WorkletGlobalScope$I が成す`有順序~集合$であり、 初期~時は空とする。 ◎ Each Document has a worklet global scopes, which is a set of WorkletGlobalScopes, initially empty.
`WorkletGlobalScope$I %G の存続期間は、 最低限,[ %G を包含する`~worklet大域~scope~list$docを有する`文書$ ]に束ねられる。 特に,当の`文書$が`破壊-@~HTMLlifecycle#destroy-a-document$されたときは、 %G は`終了-$wLされ,~garbage収集できるようになる。 ◎ The lifetime of a WorkletGlobalScope is, at a minimum, tied to the Document whose worklet global scopes contain it. In particular, destroying the Document will terminate the corresponding WorkletGlobalScope and allow it to be garbage-collected.
加えて,~UAは、 所与の `WorkletGlobalScope$I を いつでも`終了-$wLさせてヨイ — 対応する~worklet型を定義している仕様が,他を指定していない限り。 例えば,次のいずれかに該当する場合、 それを終了させることもあろう ⇒# `~worklet~agent$の`~event~loop$aGに~queueされた`~task$は無いとき/ 当の~workletを用立てるよう計画している処理待ち演算は無いとき/ 無限~loopや課される時間~制限sを超過する~callbackなど,異常な演算が検出されたとき ◎ Additionally, user agents may, at any time, terminate a given WorkletGlobalScope, unless the specification defining the corresponding worklet type says otherwise.\ For example, they might terminate them if the worklet agent's event loop has no tasks queued, or if the user agent has no pending operations planning to make use of the worklet, or if the user agent detects abnormal operations such as infinite loops or callbacks exceeding imposed time limits.
最後に,特定の~worklet型~用の仕様は、 その型の `WorkletGlobalScope$I を`作成-$wLするときに,より特定な詳細を与えれる。 例えば、 ~worklet~codeを~callする特定の処理nの間に,それを作成することもあろう — `§ ~classの登録-法と その~methodの呼出ng@#worklets-example-registering$の例のように。 ◎ Finally, specifications for specific worklet types can give more specific details on when to create WorkletGlobalScopes for a given worklet type. For example, they might create them during specific processes that call upon worklet code, as in the example.