Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(412)

Unified Diff: third_party/WebKit/Source/core/workers/MainThreadWorklet.cpp

Issue 2840523002: [DONT COMMIT] Worklet: Implement "addModule()" algorithm for main thread worklets (Closed)
Patch Set: Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/core/workers/MainThreadWorklet.cpp
diff --git a/third_party/WebKit/Source/core/workers/MainThreadWorklet.cpp b/third_party/WebKit/Source/core/workers/MainThreadWorklet.cpp
index 1c7e06f83015b15769eed29befdbf54df2911f3f..59ecef3c7ed778f90922d2b98fe8ac2386fdb6c0 100644
--- a/third_party/WebKit/Source/core/workers/MainThreadWorklet.cpp
+++ b/third_party/WebKit/Source/core/workers/MainThreadWorklet.cpp
@@ -26,10 +26,27 @@ int32_t GetNextRequestId() {
} // namespace
+// Implementation of the "pending tasks struct":
+// https://drafts.css-houdini.org/worklets/#pending-tasks-struct
+struct MainThreadWorklet::PendingTasks : public GarbageCollected<PendingTasks> {
kouhei (in TOK) 2017/04/25 11:55:17 please make this a proper class
+ PendingTasks(int counter, ScriptPromiseResolver* resolver)
+ : counter(counter), resolver(resolver) {}
+ ~PendingTasks() = default;
+
+ // The number of pending tasks.
+ int counter;
+
+ Member<ScriptPromiseResolver> resolver;
+
+ DEFINE_INLINE_VIRTUAL_TRACE() { visitor->Trace(resolver); }
+};
+
MainThreadWorklet::MainThreadWorklet(LocalFrame* frame) : Worklet(frame) {
- DCHECK(resolver_map_.IsEmpty());
+ DCHECK(pending_tasks_map_.IsEmpty());
kouhei (in TOK) 2017/04/25 11:55:18 I think we can safely omit this DCHECK.
}
+// Implementation of the "addModule" algorithm:
+// https://drafts.css-houdini.org/worklets/#dom-worklet-addmodule
ScriptPromise MainThreadWorklet::addModule(ScriptState* script_state,
const String& url) {
DCHECK(IsMainThread());
kouhei (in TOK) 2017/04/25 11:55:17 Optional: I'd prefer to have all the steps in the
@@ -39,6 +56,8 @@ ScriptPromise MainThreadWorklet::addModule(ScriptState* script_state,
"This frame is already detached"));
}
+ // Step 4: "If moduleURLRecord is failure, then reject promise with a
kouhei (in TOK) 2017/04/25 11:55:18 Can we rename the script_url var to module_url_rec
+ // "SyntaxError" DOMException and return promise."
KURL script_url = GetExecutionContext()->CompleteURL(url);
kouhei (in TOK) 2017/04/25 11:55:17 Looks like CompleteURL part is the Step 3?
if (!script_url.IsValid()) {
return ScriptPromise::RejectWithDOMException(
@@ -46,39 +65,81 @@ ScriptPromise MainThreadWorklet::addModule(ScriptState* script_state,
kSyntaxError, "'" + url + "' is not a valid URL."));
}
- if (!IsInitialized())
- Initialize();
+ // Step 10: "If the worklet's WorkletGlobalScopes is empty, run the following
+ // steps:"
+ // 10.1: "Create a WorkletGlobalScope given workletGlobalScopeType,
+ // moduleResponsesMap, and outsideSettings."
kouhei (in TOK) 2017/04/25 11:55:18 Add TODO(nhiroki) comment about the workletGlobalS
+ // 10.2: "Add the WorkletGlobalScope to worklet's WorkletGlobalScopes."
+ if (global_scope_proxies_.IsEmpty())
+ CreateWorkletGlobalScope();
+ DCHECK(!global_scope_proxies_.IsEmpty());
- int32_t request_id = GetNextRequestId();
+ // Step 11: "Let pendingTaskStruct be a new pending tasks struct with counter
+ // initialized to the length of worklet' s WorkletGlobalScopes."
+ const int32_t request_id = GetNextRequestId();
ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
+ pending_tasks_map_.Set(
+ request_id, new PendingTasks(global_scope_proxies_.size(), resolver));
+
+ // Step 12: "For each workletGlobalScope in the worklet's
+ // WorkletGlobalScopes, queue a task on the workletGlobalScope to fetch and
+ // invoke a worklet script given workletGlobalScope, moduleURLRecord,
+ // moduleResponsesMap, credentialOptions, outsideSettings, pendingTaskStruct,
+ // and promise."
ScriptPromise promise = resolver->Promise();
- resolver_map_.Set(request_id, resolver);
- GetWorkletGlobalScopeProxy()->FetchAndInvokeScript(request_id, script_url);
+ for (const auto& proxy : global_scope_proxies_)
+ proxy->FetchAndInvokeScript(request_id, script_url);
+
return promise;
}
+// Worklet-side implementation of the "fetch and invoke a worklet script"
+// algorithm:
+// https://drafts.css-houdini.org/worklets/#fetch-and-invoke-a-worklet-script
void MainThreadWorklet::DidFetchAndInvokeScript(int32_t request_id,
bool success) {
DCHECK(IsMainThread());
- ScriptPromiseResolver* resolver = resolver_map_.at(request_id);
- if (!resolver)
+ PendingTasks* pending_tasks = pending_tasks_map_.at(request_id);
kouhei (in TOK) 2017/04/25 11:55:18 Optional: map_.Find here to get iterator
+ if (!pending_tasks)
return;
- resolver_map_.erase(request_id);
+
+ // Step 3: "If script is null, then queue a task on outsideSettings's
+ // responsible event loop to run these steps:"
kouhei (in TOK) 2017/04/25 11:55:18 Add TODO(nhiroki) or add note to justify not queui
+ // 3.1.2: "Reject promise with an "AbortError" DOMException."
if (!success) {
- resolver->Reject(DOMException::Create(kNetworkError));
+ pending_tasks_map_.erase(request_id);
kouhei (in TOK) 2017/04/25 11:55:18 and trigger erase on the iterator?
+ // TODO(nhiroki): This should be kAbortError.
+ pending_tasks->resolver->Reject(DOMException::Create(kNetworkError));
return;
}
- resolver->Resolve();
+
+ // Step 5: "Queue a task on outsideSettings's responsible event loop to run
+ // these steps:"
kouhei (in TOK) 2017/04/25 11:55:17 Ditto.
+ // 5.1.1: "Decrement pendingTaskStruct's counter by 1."
+ // 5.1.2: "If pendingTaskStruct's counter is 0, then resolve promise."
+ DCHECK_GT(0, pending_tasks->counter);
+ --pending_tasks->counter;
+ if (pending_tasks->counter == 0) {
+ pending_tasks_map_.erase(request_id);
+ pending_tasks->resolver->Resolve();
+ }
+}
+
+void MainThreadWorklet::CreateWorkletGlobalScope() {
+ if (!IsInitialized())
+ Initialize();
}
void MainThreadWorklet::ContextDestroyed(ExecutionContext* execution_context) {
DCHECK(IsMainThread());
- resolver_map_.clear();
+ pending_tasks_map_.clear();
+ for (const auto& proxy : global_scope_proxies_)
+ proxy->TerminateWorkletGlobalScope();
Worklet::ContextDestroyed(execution_context);
}
DEFINE_TRACE(MainThreadWorklet) {
- visitor->Trace(resolver_map_);
+ visitor->Trace(pending_tasks_map_);
Worklet::Trace(visitor);
}

Powered by Google App Engine
This is Rietveld 408576698