1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "WorkletFetchHandler.h"
8 #include "js/loader/ModuleLoadRequest.h"
9 #include "js/ContextOptions.h"
10 #include "mozilla/dom/Document.h"
11 #include "mozilla/dom/Fetch.h"
12 #include "mozilla/dom/Request.h"
13 #include "mozilla/dom/RequestBinding.h"
14 #include "mozilla/dom/Response.h"
15 #include "mozilla/dom/RootedDictionary.h"
16 #include "mozilla/dom/ScriptLoader.h"
17 #include "mozilla/dom/ScriptLoadHandler.h" // ScriptDecoder
18 #include "mozilla/dom/Worklet.h"
19 #include "mozilla/dom/WorkletBinding.h"
20 #include "mozilla/dom/WorkletGlobalScope.h"
21 #include "mozilla/dom/WorkletImpl.h"
22 #include "mozilla/dom/WorkletThread.h"
23 #include "mozilla/dom/worklet/WorkletModuleLoader.h"
24 #include "mozilla/CycleCollectedJSContext.h"
25 #include "mozilla/ScopeExit.h"
26 #include "mozilla/TaskQueue.h"
27 #include "nsIInputStreamPump.h"
28 #include "nsIThreadRetargetableRequest.h"
29 #include "xpcpublic.h"
31 using JS::loader::ModuleLoadRequest
;
32 using JS::loader::ParserMetadata
;
33 using JS::loader::ScriptFetchOptions
;
34 using mozilla::dom::loader::WorkletModuleLoader
;
36 namespace mozilla::dom
{
38 // A Runnable to call ModuleLoadRequest::StartModuleLoad on a worklet thread.
39 class StartModuleLoadRunnable final
: public Runnable
{
41 StartModuleLoadRunnable(
42 WorkletImpl
* aWorkletImpl
,
43 const nsMainThreadPtrHandle
<WorkletFetchHandler
>& aHandlerRef
,
44 nsCOMPtr
<nsIURI
> aURI
, nsIURI
* aReferrer
,
45 const nsTArray
<nsString
>& aLocalizedStrs
)
46 : Runnable("Worklet::StartModuleLoadRunnable"),
47 mWorkletImpl(aWorkletImpl
),
48 mHandlerRef(aHandlerRef
),
49 mURI(std::move(aURI
)),
51 mLocalizedStrs(aLocalizedStrs
),
53 JS_GetParentRuntime(CycleCollectedJSContext::Get()->Context())) {
54 MOZ_ASSERT(NS_IsMainThread());
55 MOZ_ASSERT(mParentRuntime
);
56 xpc::SetPrefableContextOptions(mContextOptions
);
59 ~StartModuleLoadRunnable() = default;
61 NS_IMETHOD
Run() override
;
64 NS_IMETHOD
RunOnWorkletThread();
66 RefPtr
<WorkletImpl
> mWorkletImpl
;
67 nsMainThreadPtrHandle
<WorkletFetchHandler
> mHandlerRef
;
68 nsCOMPtr
<nsIURI
> mURI
;
69 nsCOMPtr
<nsIURI
> mReferrer
;
70 const nsTArray
<nsString
>& mLocalizedStrs
;
71 JSRuntime
* mParentRuntime
;
72 JS::ContextOptions mContextOptions
;
76 StartModuleLoadRunnable::Run() {
77 // WorkletThread::IsOnWorkletThread() cannot be used here because it depends
78 // on a WorkletJSContext having been created for this thread. That does not
79 // happen until the global scope is created the first time
80 // RunOnWorkletThread() is called.
81 MOZ_ASSERT(!NS_IsMainThread());
82 return RunOnWorkletThread();
85 NS_IMETHODIMP
StartModuleLoadRunnable::RunOnWorkletThread() {
86 // This can be called on a GraphRunner thread or a DOM Worklet thread.
87 WorkletThread::EnsureCycleCollectedJSContext(mParentRuntime
, mContextOptions
);
89 WorkletGlobalScope
* globalScope
= mWorkletImpl
->GetGlobalScope();
91 return NS_ERROR_DOM_UNKNOWN_ERR
;
94 // To fetch a worklet/module worker script graph:
95 // https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-worklet/module-worker-script-graph
96 // Step 1. Let options be a script fetch options whose cryptographic nonce is
97 // the empty string, integrity metadata is the empty string, parser metadata
98 // is "not-parser-inserted", credentials mode is credentials mode, referrer
99 // policy is the empty string, and fetch priority is "auto".
100 RefPtr
<ScriptFetchOptions
> fetchOptions
= new ScriptFetchOptions(
101 CORSMode::CORS_NONE
, /* aNonce = */ u
""_ns
, RequestPriority::Auto
,
102 ParserMetadata::NotParserInserted
,
103 /*triggeringPrincipal*/ nullptr);
105 WorkletModuleLoader
* moduleLoader
=
106 static_cast<WorkletModuleLoader
*>(globalScope
->GetModuleLoader());
107 MOZ_ASSERT(moduleLoader
);
109 if (!moduleLoader
->HasSetLocalizedStrings()) {
110 moduleLoader
->SetLocalizedStrings(&mLocalizedStrs
);
113 RefPtr
<WorkletLoadContext
> loadContext
= new WorkletLoadContext(mHandlerRef
);
115 // Part of Step 2. This sets the Top-level flag to true
116 RefPtr
<ModuleLoadRequest
> request
= new ModuleLoadRequest(
117 mURI
, ReferrerPolicy::_empty
, fetchOptions
, SRIMetadata(), mReferrer
,
118 loadContext
, true, /* is top level */
119 false, /* is dynamic import */
120 moduleLoader
, ModuleLoadRequest::NewVisitedSetForTopLevelImport(mURI
),
123 request
->mURL
= request
->mURI
->GetSpecOrDefault();
124 request
->NoCacheEntryFound();
126 return request
->StartModuleLoad();
129 StartFetchRunnable::StartFetchRunnable(
130 const nsMainThreadPtrHandle
<WorkletFetchHandler
>& aHandlerRef
, nsIURI
* aURI
,
132 : Runnable("Worklet::StartFetchRunnable"),
133 mHandlerRef(aHandlerRef
),
135 mReferrer(aReferrer
) {
136 MOZ_ASSERT(!NS_IsMainThread());
140 StartFetchRunnable::Run() {
141 MOZ_ASSERT(NS_IsMainThread());
143 nsCOMPtr
<nsIGlobalObject
> global
=
144 do_QueryInterface(mHandlerRef
->mWorklet
->GetParentObject());
148 if (NS_WARN_IF(!jsapi
.Init(global
))) {
149 return NS_ERROR_FAILURE
;
152 JSContext
* cx
= jsapi
.cx();
153 nsresult rv
= mHandlerRef
->StartFetch(cx
, mURI
, mReferrer
);
155 mHandlerRef
->HandleFetchFailed(mURI
);
156 return NS_ERROR_FAILURE
;
162 // A Runnable to call ModuleLoadRequest::OnFetchComplete on a worklet thread.
163 class FetchCompleteRunnable final
: public Runnable
{
165 FetchCompleteRunnable(WorkletImpl
* aWorkletImpl
, nsIURI
* aURI
,
167 UniquePtr
<uint8_t[]> aScriptBuffer
= nullptr,
168 size_t aScriptLength
= 0)
169 : Runnable("Worklet::FetchCompleteRunnable"),
170 mWorkletImpl(aWorkletImpl
),
173 mScriptBuffer(std::move(aScriptBuffer
)),
174 mScriptLength(aScriptLength
) {
175 MOZ_ASSERT(NS_IsMainThread());
178 ~FetchCompleteRunnable() = default;
180 NS_IMETHOD
Run() override
;
183 NS_IMETHOD
RunOnWorkletThread();
185 RefPtr
<WorkletImpl
> mWorkletImpl
;
186 nsCOMPtr
<nsIURI
> mURI
;
188 UniquePtr
<uint8_t[]> mScriptBuffer
;
189 size_t mScriptLength
;
193 FetchCompleteRunnable::Run() {
194 MOZ_ASSERT(WorkletThread::IsOnWorkletThread());
195 return RunOnWorkletThread();
198 NS_IMETHODIMP
FetchCompleteRunnable::RunOnWorkletThread() {
199 WorkletGlobalScope
* globalScope
= mWorkletImpl
->GetGlobalScope();
201 return NS_ERROR_DOM_UNKNOWN_ERR
;
204 WorkletModuleLoader
* moduleLoader
=
205 static_cast<WorkletModuleLoader
*>(globalScope
->GetModuleLoader());
206 MOZ_ASSERT(moduleLoader
);
208 ModuleLoadRequest
* request
= moduleLoader
->GetRequest(mURI
);
211 // Set the Source type to "text" for decoding.
212 request
->SetTextSource(request
->mLoadContext
.get());
216 UniquePtr
<ScriptDecoder
> decoder
= MakeUnique
<ScriptDecoder
>(
217 UTF_8_ENCODING
, ScriptDecoder::BOMHandling::Remove
);
218 rv
= decoder
->DecodeRawData(request
, mScriptBuffer
.get(), mScriptLength
,
220 NS_ENSURE_SUCCESS(rv
, rv
);
223 request
->mBaseURL
= mURI
;
224 request
->OnFetchComplete(mResult
);
226 if (NS_FAILED(mResult
)) {
227 if (request
->IsTopLevel()) {
228 request
->LoadFailed();
234 moduleLoader
->RemoveRequest(mURI
);
238 //////////////////////////////////////////////////////////////
239 // WorkletFetchHandler
240 //////////////////////////////////////////////////////////////
241 NS_IMPL_CYCLE_COLLECTING_ADDREF(WorkletFetchHandler
)
242 NS_IMPL_CYCLE_COLLECTING_RELEASE(WorkletFetchHandler
)
244 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WorkletFetchHandler
)
245 NS_INTERFACE_MAP_ENTRY(nsISupports
)
248 NS_IMPL_CYCLE_COLLECTION_CLASS(WorkletFetchHandler
)
250 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(WorkletFetchHandler
)
251 NS_IMPL_CYCLE_COLLECTION_UNLINK(mWorklet
, mPromises
)
252 tmp
->mErrorToRethrow
.setUndefined();
253 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
255 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(WorkletFetchHandler
)
256 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWorklet
, mPromises
)
257 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
259 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(WorkletFetchHandler
)
260 NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mErrorToRethrow
)
261 NS_IMPL_CYCLE_COLLECTION_TRACE_END
264 already_AddRefed
<Promise
> WorkletFetchHandler::AddModule(
265 Worklet
* aWorklet
, JSContext
* aCx
, const nsAString
& aModuleURL
,
266 const WorkletOptions
& aOptions
, ErrorResult
& aRv
) {
267 MOZ_ASSERT(aWorklet
);
268 MOZ_ASSERT(NS_IsMainThread());
270 aWorklet
->Impl()->OnAddModuleStarted();
272 auto promiseSettledGuard
=
273 MakeScopeExit([&] { aWorklet
->Impl()->OnAddModulePromiseSettled(); });
275 nsCOMPtr
<nsIGlobalObject
> global
=
276 do_QueryInterface(aWorklet
->GetParentObject());
279 RefPtr
<Promise
> promise
= Promise::Create(global
, aRv
);
280 if (NS_WARN_IF(aRv
.Failed())) {
284 nsCOMPtr
<nsPIDOMWindowInner
> window
= aWorklet
->GetParentObject();
287 nsCOMPtr
<Document
> doc
;
288 doc
= window
->GetExtantDoc();
290 promise
->MaybeReject(NS_ERROR_FAILURE
);
291 return promise
.forget();
294 nsCOMPtr
<nsIURI
> resolvedURI
;
295 nsresult rv
= NS_NewURI(getter_AddRefs(resolvedURI
), aModuleURL
, nullptr,
297 if (NS_WARN_IF(NS_FAILED(rv
))) {
298 // https://html.spec.whatwg.org/multipage/worklets.html#dom-worklet-addmodule
299 // Step 3. If this fails, then return a promise rejected with a
300 // "SyntaxError" DOMException.
301 rv
= NS_ERROR_DOM_SYNTAX_ERR
;
303 promise
->MaybeReject(rv
);
304 return promise
.forget();
308 rv
= resolvedURI
->GetSpec(spec
);
309 if (NS_WARN_IF(NS_FAILED(rv
))) {
310 rv
= NS_ERROR_DOM_SYNTAX_ERR
;
312 promise
->MaybeReject(rv
);
313 return promise
.forget();
316 // Maybe we already have an handler for this URI
318 WorkletFetchHandler
* handler
= aWorklet
->GetImportFetchHandler(spec
);
320 handler
->AddPromise(aCx
, promise
);
321 return promise
.forget();
325 RefPtr
<WorkletFetchHandler
> handler
=
326 new WorkletFetchHandler(aWorklet
, promise
, aOptions
.mCredentials
);
328 nsMainThreadPtrHandle
<WorkletFetchHandler
> handlerRef
{
329 new nsMainThreadPtrHolder
<WorkletFetchHandler
>("FetchHandler", handler
)};
331 // Determine request's Referrer
332 // https://w3c.github.io/webappsec-referrer-policy/#determine-requests-referrer
333 // Step 3. Switch on request’s referrer:
335 // Step 1.4. Let referrerSource be document’s URL.
336 nsIURI
* referrer
= doc
->GetDocumentURIAsReferrer();
337 nsCOMPtr
<nsIRunnable
> runnable
= new StartModuleLoadRunnable(
338 aWorklet
->mImpl
, handlerRef
, std::move(resolvedURI
), referrer
,
339 aWorklet
->GetLocalizedStrings());
341 if (NS_FAILED(aWorklet
->mImpl
->SendControlMessage(runnable
.forget()))) {
345 promiseSettledGuard
.release();
347 aWorklet
->AddImportFetchHandler(spec
, handler
);
348 return promise
.forget();
351 WorkletFetchHandler::WorkletFetchHandler(Worklet
* aWorklet
, Promise
* aPromise
,
352 RequestCredentials aCredentials
)
353 : mWorklet(aWorklet
), mStatus(ePending
), mCredentials(aCredentials
) {
354 MOZ_ASSERT(aWorklet
);
355 MOZ_ASSERT(aPromise
);
356 MOZ_ASSERT(NS_IsMainThread());
358 mPromises
.AppendElement(aPromise
);
361 WorkletFetchHandler::~WorkletFetchHandler() { mozilla::DropJSObjects(this); }
363 void WorkletFetchHandler::ExecutionFailed() {
364 MOZ_ASSERT(NS_IsMainThread());
365 RejectPromises(NS_ERROR_DOM_ABORT_ERR
);
368 void WorkletFetchHandler::ExecutionFailed(JS::Handle
<JS::Value
> aError
) {
369 MOZ_ASSERT(NS_IsMainThread());
370 RejectPromises(aError
);
373 void WorkletFetchHandler::ExecutionSucceeded() {
374 MOZ_ASSERT(NS_IsMainThread());
378 void WorkletFetchHandler::AddPromise(JSContext
* aCx
, Promise
* aPromise
) {
379 MOZ_ASSERT(aPromise
);
380 MOZ_ASSERT(NS_IsMainThread());
384 mPromises
.AppendElement(aPromise
);
389 JS::Rooted
<JS::Value
> error(aCx
, mErrorToRethrow
);
390 aPromise
->MaybeReject(error
);
392 aPromise
->MaybeReject(NS_ERROR_DOM_ABORT_ERR
);
397 aPromise
->MaybeResolveWithUndefined();
402 void WorkletFetchHandler::RejectPromises(nsresult aResult
) {
403 MOZ_ASSERT(mStatus
== ePending
);
404 MOZ_ASSERT(NS_FAILED(aResult
));
405 MOZ_ASSERT(NS_IsMainThread());
407 mWorklet
->Impl()->OnAddModulePromiseSettled();
409 for (uint32_t i
= 0; i
< mPromises
.Length(); ++i
) {
410 mPromises
[i
]->MaybeReject(aResult
);
418 void WorkletFetchHandler::RejectPromises(JS::Handle
<JS::Value
> aValue
) {
419 MOZ_ASSERT(mStatus
== ePending
);
420 MOZ_ASSERT(NS_IsMainThread());
422 mWorklet
->Impl()->OnAddModulePromiseSettled();
424 for (uint32_t i
= 0; i
< mPromises
.Length(); ++i
) {
425 mPromises
[i
]->MaybeReject(aValue
);
430 mErrorToRethrow
= aValue
;
432 mozilla::HoldJSObjects(this);
438 void WorkletFetchHandler::ResolvePromises() {
439 MOZ_ASSERT(mStatus
== ePending
);
440 MOZ_ASSERT(NS_IsMainThread());
442 mWorklet
->Impl()->OnAddModulePromiseSettled();
444 for (uint32_t i
= 0; i
< mPromises
.Length(); ++i
) {
445 mPromises
[i
]->MaybeResolveWithUndefined();
453 nsresult
WorkletFetchHandler::StartFetch(JSContext
* aCx
, nsIURI
* aURI
,
456 nsresult res
= aURI
->GetSpec(spec
);
457 if (NS_WARN_IF(NS_FAILED(res
))) {
458 return NS_ERROR_FAILURE
;
461 RequestOrUTF8String requestInput
;
462 requestInput
.SetAsUTF8String().ShareOrDependUpon(spec
);
464 RootedDictionary
<RequestInit
> requestInit(aCx
);
465 requestInit
.mCredentials
.Construct(mCredentials
);
467 // https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-single-module-script
468 // Step 8. mode is "cors"
469 requestInit
.mMode
.Construct(RequestMode::Cors
);
472 res
= aReferrer
->GetSpec(requestInit
.mReferrer
.Construct());
473 if (NS_WARN_IF(NS_FAILED(res
))) {
474 return NS_ERROR_FAILURE
;
478 nsCOMPtr
<nsIGlobalObject
> global
=
479 do_QueryInterface(mWorklet
->GetParentObject());
482 // Note: added to infer a default credentials mode in the Request setup,
483 // but we always pass an explicit credentials value in requestInit, so
484 // this has no effect right now. Bug 1887862 covers fixing worklets to behave
485 // the same as "normal" fetch calls.
486 nsIPrincipal
* p
= global
->PrincipalOrNull();
487 CallerType callerType
= (p
&& p
->IsSystemPrincipal() ? CallerType::System
488 : CallerType::NonSystem
);
489 IgnoredErrorResult rv
;
490 SafeRefPtr
<Request
> request
= Request::Constructor(
491 global
, aCx
, requestInput
, requestInit
, callerType
, rv
);
493 return NS_ERROR_FAILURE
;
496 request
->OverrideContentPolicyType(mWorklet
->Impl()->ContentPolicyType());
498 RequestOrUTF8String finalRequestInput
;
499 finalRequestInput
.SetAsRequest() = request
.unsafeGetRawPtr();
501 RefPtr
<Promise
> fetchPromise
= FetchRequest(
502 global
, finalRequestInput
, requestInit
, CallerType::System
, rv
);
503 if (NS_WARN_IF(rv
.Failed())) {
504 return NS_ERROR_FAILURE
;
507 RefPtr
<WorkletScriptHandler
> scriptHandler
=
508 new WorkletScriptHandler(mWorklet
, aURI
);
509 fetchPromise
->AppendNativeHandler(scriptHandler
);
513 void WorkletFetchHandler::HandleFetchFailed(nsIURI
* aURI
) {
514 nsCOMPtr
<nsIRunnable
> runnable
= new FetchCompleteRunnable(
515 mWorklet
->mImpl
, aURI
, NS_ERROR_FAILURE
, nullptr, 0);
518 NS_FAILED(mWorklet
->mImpl
->SendControlMessage(runnable
.forget())))) {
519 NS_WARNING("Failed to dispatch FetchCompleteRunnable to a worklet thread.");
523 //////////////////////////////////////////////////////////////
524 // WorkletScriptHandler
525 //////////////////////////////////////////////////////////////
526 NS_IMPL_ISUPPORTS(WorkletScriptHandler
, nsIStreamLoaderObserver
)
528 WorkletScriptHandler::WorkletScriptHandler(Worklet
* aWorklet
, nsIURI
* aURI
)
529 : mWorklet(aWorklet
), mURI(aURI
) {}
531 void WorkletScriptHandler::ResolvedCallback(JSContext
* aCx
,
532 JS::Handle
<JS::Value
> aValue
,
534 MOZ_ASSERT(NS_IsMainThread());
536 if (!aValue
.isObject()) {
537 HandleFailure(NS_ERROR_FAILURE
);
541 RefPtr
<Response
> response
;
542 nsresult rv
= UNWRAP_OBJECT(Response
, &aValue
.toObject(), response
);
543 if (NS_WARN_IF(NS_FAILED(rv
))) {
544 HandleFailure(NS_ERROR_FAILURE
);
548 // https://html.spec.whatwg.org/multipage/worklets.html#dom-worklet-addmodule
549 // Step 6.4.1. If script is null, then:
550 // Step 1.1.2. Reject promise with an "AbortError" DOMException.
551 if (!response
->Ok()) {
552 HandleFailure(NS_ERROR_DOM_ABORT_ERR
);
556 nsCOMPtr
<nsIInputStream
> inputStream
;
557 response
->GetBody(getter_AddRefs(inputStream
));
559 HandleFailure(NS_ERROR_DOM_NETWORK_ERR
);
563 nsCOMPtr
<nsIInputStreamPump
> pump
;
564 rv
= NS_NewInputStreamPump(getter_AddRefs(pump
), inputStream
.forget());
565 if (NS_WARN_IF(NS_FAILED(rv
))) {
570 nsCOMPtr
<nsIStreamLoader
> loader
;
571 rv
= NS_NewStreamLoader(getter_AddRefs(loader
), this);
572 if (NS_WARN_IF(NS_FAILED(rv
))) {
577 rv
= pump
->AsyncRead(loader
);
578 if (NS_WARN_IF(NS_FAILED(rv
))) {
583 nsCOMPtr
<nsIThreadRetargetableRequest
> rr
= do_QueryInterface(pump
);
585 nsCOMPtr
<nsIEventTarget
> sts
=
586 do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID
);
587 RefPtr
<TaskQueue
> queue
= TaskQueue::Create(
588 sts
.forget(), "WorkletScriptHandler STS Delivery Queue");
589 rv
= rr
->RetargetDeliveryTo(queue
);
591 NS_WARNING("Failed to dispatch the nsIInputStreamPump to a IO thread.");
596 NS_IMETHODIMP
WorkletScriptHandler::OnStreamComplete(nsIStreamLoader
* aLoader
,
597 nsISupports
* aContext
,
600 const uint8_t* aString
) {
601 MOZ_ASSERT(NS_IsMainThread());
603 if (NS_FAILED(aStatus
)) {
604 HandleFailure(aStatus
);
608 // Copy the buffer and decode it on worklet thread, as we can only access
609 // ModuleLoadRequest on worklet thread.
610 UniquePtr
<uint8_t[]> scriptTextBuf
= MakeUnique
<uint8_t[]>(aStringLen
);
611 memcpy(scriptTextBuf
.get(), aString
, aStringLen
);
613 nsCOMPtr
<nsIRunnable
> runnable
= new FetchCompleteRunnable(
614 mWorklet
->mImpl
, mURI
, NS_OK
, std::move(scriptTextBuf
), aStringLen
);
616 if (NS_FAILED(mWorklet
->mImpl
->SendControlMessage(runnable
.forget()))) {
617 HandleFailure(NS_ERROR_FAILURE
);
623 void WorkletScriptHandler::RejectedCallback(JSContext
* aCx
,
624 JS::Handle
<JS::Value
> aValue
,
626 MOZ_ASSERT(NS_IsMainThread());
628 // https://html.spec.whatwg.org/multipage/worklets.html#dom-worklet-addmodule
629 // Step 6.4.1. If script is null, then:
630 // Step 1.1.2. Reject promise with an "AbortError" DOMException.
631 HandleFailure(NS_ERROR_DOM_ABORT_ERR
);
634 void WorkletScriptHandler::HandleFailure(nsresult aResult
) {
635 DispatchFetchCompleteToWorklet(aResult
);
638 void WorkletScriptHandler::DispatchFetchCompleteToWorklet(nsresult aRv
) {
639 nsCOMPtr
<nsIRunnable
> runnable
=
640 new FetchCompleteRunnable(mWorklet
->mImpl
, mURI
, aRv
, nullptr, 0);
643 NS_FAILED(mWorklet
->mImpl
->SendControlMessage(runnable
.forget())))) {
644 NS_WARNING("Failed to dispatch FetchCompleteRunnable to a worklet thread.");
648 } // namespace mozilla::dom