Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/dom/worklet/   (Firefox Browser Version 153.0.1©)  Datei vom 27.6.2026 mit Größe 21 kB image not shown  

Quelle  WorkletFetchHandler.cpp

  Sprache: C
 

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "WorkletFetchHandler.h"

#include "js/ContextOptions.h"
#include "js/loader/ModuleLoadRequest.h"
#include "mozilla/CycleCollectedJSContext.h"
#include "mozilla/ScopeExit.h"
#include "mozilla/StaticPrefs_javascript.h"
#include "mozilla/TaskQueue.h"
#include "mozilla/dom/Document.h"
#include "mozilla/dom/Fetch.h"
#include "mozilla/dom/Request.h"
#include "mozilla/dom/RequestBinding.h"
#include "mozilla/dom/Response.h"
#include "mozilla/dom/RootedDictionary.h"
#include "mozilla/dom/ScriptLoadHandler.h"  // ScriptDecoder
#include "mozilla/dom/ScriptLoader.h"
#include "mozilla/dom/Worklet.h"
#include "mozilla/dom/WorkletBinding.h"
#include "mozilla/dom/WorkletGlobalScope.h"
#include "mozilla/dom/WorkletImpl.h"
#include "mozilla/dom/WorkletThread.h"
#include "mozilla/dom/worklet/WorkletModuleLoader.h"
#include "nsIInputStreamPump.h"
#include "nsIThreadRetargetableRequest.h"
#include "xpcpublic.h"

using JS::loader::ModuleLoadRequest;
using JS::loader::ParserMetadata;
using JS::loader::ScriptFetchOptions;
using mozilla::dom::loader::WorkletModuleLoader;

namespace mozilla::dom {

// A Runnable to call ModuleLoadRequest::StartModuleLoad on a worklet thread.
class StartModuleLoadRunnable final : public Runnable {
 public:
  StartModuleLoadRunnable(
      WorkletImpl* aWorkletImpl,
      const nsMainThreadPtrHandle<WorkletFetchHandler>& aHandlerRef,
      nsCOMPtr<nsIURI> aURI, nsIURI* aReferrer,
      nsTArray<nsString>&& aLocalizedStrs)
      : Runnable("Worklet::StartModuleLoadRunnable"),
        mWorkletImpl(aWorkletImpl),
        mHandlerRef(aHandlerRef),
        mURI(std::move(aURI)),
        mReferrer(aReferrer),
        mLocalizedStrs(std::move(aLocalizedStrs)),
        mParentRuntime(
            JS_GetParentRuntime(CycleCollectedJSContext::Get()->Context())) {
    MOZ_ASSERT(NS_IsMainThread());
    MOZ_ASSERT(mParentRuntime);
    xpc::SetPrefableContextOptions(mContextOptions);
  }

  ~StartModuleLoadRunnable() = default;

  NS_IMETHOD Run() override;

 private:
  NS_IMETHOD RunOnWorkletThread();

  RefPtr<WorkletImpl> mWorkletImpl;
  nsMainThreadPtrHandle<WorkletFetchHandler> mHandlerRef;
  nsCOMPtr<nsIURI> mURI;
  nsCOMPtr<nsIURI> mReferrer;
  nsTArray<nsString> mLocalizedStrs;
  JSRuntime* mParentRuntime;
  JS::ContextOptions mContextOptions;
};

NS_IMETHODIMP
StartModuleLoadRunnable::Run() {
  // WorkletThread::IsOnWorkletThread() cannot be used here because it depends
  // on a WorkletJSContext having been created for this thread.  That does not
  // happen until the global scope is created the first time
  // RunOnWorkletThread() is called.
  MOZ_ASSERT(!NS_IsMainThread());
  return RunOnWorkletThread();
}

NS_IMETHODIMP StartModuleLoadRunnable::RunOnWorkletThread() {
  // This can be called on a GraphRunner thread or a DOM Worklet thread.
  WorkletThread::EnsureCycleCollectedJSContext(mParentRuntime, mContextOptions);

  WorkletGlobalScope* globalScope = mWorkletImpl->GetGlobalScope();
  if (!globalScope) {
    return NS_ERROR_DOM_UNKNOWN_ERR;
  }

  // To fetch a worklet/module worker script graph:
  // https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-worklet/module-worker-script-graph
  // Step 1. Let options be a script fetch options whose cryptographic nonce is
  // the empty string, integrity metadata is the empty string, parser metadata
  // is "not-parser-inserted", credentials mode is credentials mode, referrer
  // policy is the empty string, and fetch priority is "auto".
  RefPtr<ScriptFetchOptions> fetchOptions = new ScriptFetchOptions(
      CORSMode::CORS_NONE, /* aNonce = */ u""_ns, RequestPriority::Auto,
      ParserMetadata::NotParserInserted,
      /*triggeringPrincipal*/ nullptr);

  WorkletModuleLoader* moduleLoader =
      static_cast<WorkletModuleLoader*>(globalScope->GetModuleLoader());
  MOZ_ASSERT(moduleLoader);

  if (!moduleLoader->HasSetLocalizedStrings()) {
    moduleLoader->SetLocalizedStrings(mLocalizedStrs.Clone());
  }

  RefPtr<WorkletLoadContext> loadContext = new WorkletLoadContext(mHandlerRef);

  // Part of Step 2. This sets the Top-level flag to true
  RefPtr<ModuleLoadRequest> request = new ModuleLoadRequest(
      JS::ModuleType::JavaScript, SRIMetadata(), mReferrer, loadContext,
      ModuleLoadRequest::Kind::TopLevel, moduleLoader, nullptr);

  request->mURL = mURI->GetSpecOrDefault();
  request->NoCacheEntryFound(ReferrerPolicy::_empty, fetchOptions, mURI);

  return request->StartModuleLoad();
}

StartFetchRunnable::StartFetchRunnable(
    const nsMainThreadPtrHandle<WorkletFetchHandler>& aHandlerRef, nsIURI* aURI,
    nsIURI* aReferrer)
    : Runnable("Worklet::StartFetchRunnable"),
      mHandlerRef(aHandlerRef),
      mURI(aURI),
      mReferrer(aReferrer) {
  MOZ_ASSERT(!NS_IsMainThread());
}

NS_IMETHODIMP
StartFetchRunnable::Run() {
  MOZ_ASSERT(NS_IsMainThread());

  nsCOMPtr<nsIGlobalObject> global =
      do_QueryInterface(mHandlerRef->mWorklet->GetParentObject());
  MOZ_ASSERT(global);

  AutoJSAPI jsapi;
  if (NS_WARN_IF(!jsapi.Init(global))) {
    return NS_ERROR_FAILURE;
  }

  JSContext* cx = jsapi.cx();
  nsresult rv = mHandlerRef->StartFetch(cx, mURI, mReferrer);
  if (NS_FAILED(rv)) {
    mHandlerRef->HandleFetchFailed(mURI);
    return NS_ERROR_FAILURE;
  }

  return NS_OK;
}

// A Runnable to call ModuleLoadRequest::OnFetchComplete on a worklet thread.
class FetchCompleteRunnable final : public Runnable {
 public:
  FetchCompleteRunnable(WorkletImpl* aWorkletImpl, nsIURI* aURI,
                        nsresult aResult,
#ifdef NIGHTLY_BUILD
                        bool aHasWasmMimeTypeEssence,
#endif
                        UniquePtr<uint8_t[]> aScriptBuffer = nullptr,
                        size_t aScriptLength = 0)
      : Runnable("Worklet::FetchCompleteRunnable"),
        mWorkletImpl(aWorkletImpl),
        mURI(aURI),
        mResult(aResult),
#ifdef NIGHTLY_BUILD
        mHasWasmMimeTypeEssence(aHasWasmMimeTypeEssence),
#endif
        mScriptBuffer(std::move(aScriptBuffer)),
        mScriptLength(aScriptLength) {
    MOZ_ASSERT(NS_IsMainThread());
  }

  ~FetchCompleteRunnable() = default;

  NS_IMETHOD Run() override;

 private:
  NS_IMETHOD RunOnWorkletThread();

  RefPtr<WorkletImpl> mWorkletImpl;
  nsCOMPtr<nsIURI> mURI;
  nsresult mResult;
#ifdef NIGHTLY_BUILD
  bool mHasWasmMimeTypeEssence;
#endif
  UniquePtr<uint8_t[]> mScriptBuffer;
  size_t mScriptLength;
};

NS_IMETHODIMP
FetchCompleteRunnable::Run() {
  MOZ_ASSERT(WorkletThread::IsOnWorkletThread());
  return RunOnWorkletThread();
}

NS_IMETHODIMP FetchCompleteRunnable::RunOnWorkletThread() {
  WorkletGlobalScope* globalScope = mWorkletImpl->GetGlobalScope();
  if (!globalScope) {
    return NS_ERROR_DOM_UNKNOWN_ERR;
  }

  WorkletModuleLoader* moduleLoader =
      static_cast<WorkletModuleLoader*>(globalScope->GetModuleLoader());
  MOZ_ASSERT(moduleLoader);
  MOZ_ASSERT(mURI);
  ModuleLoadRequest* request = moduleLoader->GetRequest(mURI);
  MOZ_ASSERT(request);

#ifdef NIGHTLY_BUILD
  // https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-single-module-script
  // Extract the content-type. If its essence is wasm, we'll attempt to
  // compile this module as a wasm module. (Steps 13.2, 13.6)
  if (mHasWasmMimeTypeEssence) {
    request->SetHasWasmMimeTypeEssence();
    request->SetWasmBytes();
    request->SetBaseURL(mURI);
    request->OnFetchComplete(mResult);
    moduleLoader->RemoveRequest(mURI);
    return NS_OK;
  }
#endif

  // Set the Source type to "text" for decoding.
  request->SetTextSource(request->mLoadContext.get());

  nsresult rv;
  if (mScriptBuffer) {
    UniquePtr<ScriptDecoder> decoder = MakeUnique<ScriptDecoder>(
        UTF_8_ENCODING, ScriptDecoder::BOMHandling::Remove);
    rv = decoder->DecodeRawData(request, mScriptBuffer.get(), mScriptLength,
                                true);
    NS_ENSURE_SUCCESS(rv, rv);
  }

  request->SetBaseURL(mURI);
  request->OnFetchComplete(mResult);
  moduleLoader->RemoveRequest(mURI);
  return NS_OK;
}

//////////////////////////////////////////////////////////////
// WorkletFetchHandler
//////////////////////////////////////////////////////////////
NS_IMPL_CYCLE_COLLECTING_ADDREF(WorkletFetchHandler)
NS_IMPL_CYCLE_COLLECTING_RELEASE(WorkletFetchHandler)

NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WorkletFetchHandler)
  NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END

NS_IMPL_CYCLE_COLLECTION_CLASS(WorkletFetchHandler)

NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(WorkletFetchHandler)
  NS_IMPL_CYCLE_COLLECTION_UNLINK(mWorklet, mPromises)
  tmp->mErrorToRethrow.setUndefined();
NS_IMPL_CYCLE_COLLECTION_UNLINK_END

NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(WorkletFetchHandler)
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWorklet, mPromises)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END

NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(WorkletFetchHandler)
  NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mErrorToRethrow)
NS_IMPL_CYCLE_COLLECTION_TRACE_END

// static
already_AddRefed<Promise> WorkletFetchHandler::AddModule(
    Worklet* aWorklet, JSContext* aCx, const nsAString& aModuleURL,
    const WorkletOptions& aOptions, ErrorResult& aRv) {
  MOZ_ASSERT(aWorklet);
  MOZ_ASSERT(NS_IsMainThread());

  aWorklet->Impl()->OnAddModuleStarted();

  auto promiseSettledGuard =
      MakeScopeExit([&] { aWorklet->Impl()->OnAddModulePromiseSettled(); });

  nsCOMPtr<nsIGlobalObject> global =
      do_QueryInterface(aWorklet->GetParentObject());
  MOZ_ASSERT(global);

  RefPtr<Promise> promise = Promise::Create(global, aRv);
  if (NS_WARN_IF(aRv.Failed())) {
    return nullptr;
  }

  nsCOMPtr<nsPIDOMWindowInner> window = aWorklet->GetParentObject();
  MOZ_ASSERT(window);

  nsCOMPtr<Document> doc;
  doc = window->GetExtantDoc();
  if (!doc) {
    promise->MaybeReject(NS_ERROR_FAILURE);
    return promise.forget();
  }

  nsCOMPtr<nsIURI> resolvedURI;
  nsresult rv = NS_NewURI(getter_AddRefs(resolvedURI), aModuleURL, nullptr,
                          doc->GetBaseURI());
  if (NS_WARN_IF(NS_FAILED(rv))) {
    // https://html.spec.whatwg.org/multipage/worklets.html#dom-worklet-addmodule
    // Step 3. If this fails, then return a promise rejected with a
    // "SyntaxError" DOMException.
    rv = NS_ERROR_DOM_SYNTAX_ERR;

    promise->MaybeReject(rv);
    return promise.forget();
  }

  nsAutoCString spec;
  rv = resolvedURI->GetSpec(spec);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    rv = NS_ERROR_DOM_SYNTAX_ERR;

    promise->MaybeReject(rv);
    return promise.forget();
  }

  // Maybe we already have an handler for this URI
  {
    WorkletFetchHandler* handler = aWorklet->GetImportFetchHandler(spec);
    if (handler) {
      handler->AddPromise(aCx, promise);
      return promise.forget();
    }
  }

  RefPtr<WorkletFetchHandler> handler =
      new WorkletFetchHandler(aWorklet, promise, aOptions.mCredentials);

  nsMainThreadPtrHandle<WorkletFetchHandler> handlerRef{
      new nsMainThreadPtrHolder<WorkletFetchHandler>("FetchHandler", handler)};

  // Determine request's Referrer
  // https://w3c.github.io/webappsec-referrer-policy/#determine-requests-referrer
  // Step 3.  Switch on request’s referrer:
  //    "client"
  //    Step 1.4. Let referrerSource be document’s URL.
  nsIURI* referrer = doc->GetDocumentURIAsReferrer();
  nsCOMPtr<nsIRunnable> runnable = new StartModuleLoadRunnable(
      aWorklet->mImpl, handlerRef, std::move(resolvedURI), referrer,
      aWorklet->GetLocalizedStrings().Clone());

  if (NS_FAILED(aWorklet->mImpl->SendControlMessage(runnable.forget()))) {
    return nullptr;
  }

  promiseSettledGuard.release();

  aWorklet->AddImportFetchHandler(spec, handler);
  return promise.forget();
}

WorkletFetchHandler::WorkletFetchHandler(Worklet* aWorklet, Promise* aPromise,
                                         RequestCredentials aCredentials)
    : mWorklet(aWorklet), mStatus(ePending), mCredentials(aCredentials) {
  MOZ_ASSERT(aWorklet);
  MOZ_ASSERT(aPromise);
  MOZ_ASSERT(NS_IsMainThread());

  mPromises.AppendElement(aPromise);
}

WorkletFetchHandler::~WorkletFetchHandler() { mozilla::DropJSObjects(this); }

void WorkletFetchHandler::ExecutionFailed() {
  MOZ_ASSERT(NS_IsMainThread());
  RejectPromises(NS_ERROR_DOM_ABORT_ERR);
}

void WorkletFetchHandler::ExecutionFailed(JS::Handle<JS::Value> aError) {
  MOZ_ASSERT(NS_IsMainThread());
  RejectPromises(aError);
}

void WorkletFetchHandler::ExecutionSucceeded() {
  MOZ_ASSERT(NS_IsMainThread());
  ResolvePromises();
}

void WorkletFetchHandler::AddPromise(JSContext* aCx, Promise* aPromise) {
  MOZ_ASSERT(aPromise);
  MOZ_ASSERT(NS_IsMainThread());

  switch (mStatus) {
    case ePending:
      mPromises.AppendElement(aPromise);
      return;

    case eRejected:
      if (mHasError) {
        JS::Rooted<JS::Value> error(aCx, mErrorToRethrow);
        aPromise->MaybeReject(error);
      } else {
        aPromise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
      }
      return;

    case eResolved:
      aPromise->MaybeResolveWithUndefined();
      return;
  }
}

void WorkletFetchHandler::RejectPromises(nsresult aResult) {
  MOZ_ASSERT(mStatus == ePending);
  MOZ_ASSERT(NS_FAILED(aResult));
  MOZ_ASSERT(NS_IsMainThread());

  mWorklet->Impl()->OnAddModulePromiseSettled();

  for (uint32_t i = 0; i < mPromises.Length(); ++i) {
    mPromises[i]->MaybeReject(aResult);
  }
  mPromises.Clear();

  mStatus = eRejected;
  mWorklet = nullptr;
}

void WorkletFetchHandler::RejectPromises(JS::Handle<JS::Value> aValue) {
  MOZ_ASSERT(mStatus == ePending);
  MOZ_ASSERT(NS_IsMainThread());

  mWorklet->Impl()->OnAddModulePromiseSettled();

  for (uint32_t i = 0; i < mPromises.Length(); ++i) {
    mPromises[i]->MaybeReject(aValue);
  }
  mPromises.Clear();

  mHasError = true;
  mErrorToRethrow = aValue;

  mozilla::HoldJSObjects(this);

  mStatus = eRejected;
  mWorklet = nullptr;
}

void WorkletFetchHandler::ResolvePromises() {
  MOZ_ASSERT(mStatus == ePending);
  MOZ_ASSERT(NS_IsMainThread());

  mWorklet->Impl()->OnAddModulePromiseSettled();

  for (uint32_t i = 0; i < mPromises.Length(); ++i) {
    mPromises[i]->MaybeResolveWithUndefined();
  }
  mPromises.Clear();

  mStatus = eResolved;
  mWorklet = nullptr;
}

nsresult WorkletFetchHandler::StartFetch(JSContext* aCx, nsIURI* aURI,
                                         nsIURI* aReferrer) {
  RequestOrUTF8String requestInput;
  nsresult res = aURI->GetSpec(requestInput.SetAsUTF8String());
  if (NS_WARN_IF(NS_FAILED(res))) {
    return NS_ERROR_FAILURE;
  }

  RootedDictionary<RequestInit> requestInit(aCx);
  requestInit.mCredentials.Construct(mCredentials);

  // https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-single-module-script
  // Step 8. mode is "cors"
  requestInit.mMode.Construct(RequestMode::Cors);

  if (aReferrer) {
    res = aReferrer->GetSpec(requestInit.mReferrer.Construct());
    if (NS_WARN_IF(NS_FAILED(res))) {
      return NS_ERROR_FAILURE;
    }
  }

  nsCOMPtr<nsIGlobalObject> global =
      do_QueryInterface(mWorklet->GetParentObject());
  MOZ_ASSERT(global);

  // Note: added to infer a default credentials mode in the Request setup,
  // but we always pass an explicit credentials value in requestInit, so
  // this has no effect right now. Bug 1887862 covers fixing worklets to behave
  // the same as "normal" fetch calls.
  nsIPrincipal* p = global->PrincipalOrNull();
  CallerType callerType = (p && p->IsSystemPrincipal() ? CallerType::System
                                                       : CallerType::NonSystem);
  IgnoredErrorResult rv;
  SafeRefPtr<Request> request = Request::Constructor(
      global, aCx, requestInput, requestInit, callerType, rv);
  if (rv.Failed()) {
    return NS_ERROR_FAILURE;
  }

  request->OverrideContentPolicyType(mWorklet->Impl()->ContentPolicyType());

  RequestOrUTF8String finalRequestInput;
  finalRequestInput.SetAsRequest() = request.unsafeGetRawPtr();

  RefPtr<Promise> fetchPromise = FetchRequest(
      global, finalRequestInput, requestInit, CallerType::System, rv);
  if (NS_WARN_IF(rv.Failed())) {
    return NS_ERROR_FAILURE;
  }

  RefPtr<WorkletScriptHandler> scriptHandler =
      new WorkletScriptHandler(mWorklet, aURI);
  fetchPromise->AppendNativeHandler(scriptHandler);
  return NS_OK;
}

void WorkletFetchHandler::HandleFetchFailed(nsIURI* aURI) {
  nsCOMPtr<nsIRunnable> runnable =
      new FetchCompleteRunnable(mWorklet->mImpl, aURI, NS_ERROR_FAILURE,
#ifdef NIGHTLY_BUILD
                                false,
#endif
                                nullptr, 0);

  if (NS_WARN_IF(
          NS_FAILED(mWorklet->mImpl->SendControlMessage(runnable.forget())))) {
    NS_WARNING("Failed to dispatch FetchCompleteRunnable to a worklet thread.");
  }
}

//////////////////////////////////////////////////////////////
// WorkletScriptHandler
//////////////////////////////////////////////////////////////
NS_IMPL_ISUPPORTS(WorkletScriptHandler, nsIStreamLoaderObserver)

WorkletScriptHandler::WorkletScriptHandler(Worklet* aWorklet, nsIURI* aURI)
    : mWorklet(aWorklet), mURI(aURI) {}

void WorkletScriptHandler::ResolvedCallback(JSContext* aCx,
                                            JS::Handle<JS::Value> aValue,
                                            ErrorResult& aRv) {
  MOZ_ASSERT(NS_IsMainThread());

  if (!aValue.isObject()) {
    HandleFailure(NS_ERROR_FAILURE);
    return;
  }

  RefPtr<Response> response;
  nsresult rv = UNWRAP_OBJECT(Response, &aValue.toObject(), response);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    HandleFailure(NS_ERROR_FAILURE);
    return;
  }

  // https://html.spec.whatwg.org/multipage/worklets.html#dom-worklet-addmodule
  // Step 6.4.1. If script is null, then:
  //   Step 1.1.2. Reject promise with an "AbortError" DOMException.
  if (!response->Ok()) {
    HandleFailure(NS_ERROR_DOM_ABORT_ERR);
    return;
  }

#ifdef NIGHTLY_BUILD
  nsAutoCString contentType;
  ErrorResult result;
  if (response->GetInternalHeaders()) {
    response->GetInternalHeaders()->Get("Content-Type"_ns, contentType, result);
    if (!result.Failed()) {
      mHasWasmMimeTypeEssence = nsContentUtils::HasWasmMimeTypeEssence(
          NS_ConvertUTF8toUTF16(contentType));
    }
  }
#endif

  nsCOMPtr<nsIInputStream> inputStream;
  response->GetBody(getter_AddRefs(inputStream));
  if (!inputStream) {
    HandleFailure(NS_ERROR_DOM_NETWORK_ERR);
    return;
  }

  nsCOMPtr<nsIInputStreamPump> pump;
  rv = NS_NewInputStreamPump(getter_AddRefs(pump), inputStream.forget());
  if (NS_WARN_IF(NS_FAILED(rv))) {
    HandleFailure(rv);
    return;
  }

  nsCOMPtr<nsIStreamLoader> loader;
  rv = NS_NewStreamLoader(getter_AddRefs(loader), this);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    HandleFailure(rv);
    return;
  }

  rv = pump->AsyncRead(loader);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    HandleFailure(rv);
    return;
  }

  nsCOMPtr<nsIThreadRetargetableRequest> rr = do_QueryInterface(pump);
  if (rr) {
    nsCOMPtr<nsIEventTarget> sts =
        do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
    RefPtr<TaskQueue> queue = TaskQueue::Create(
        sts.forget(), "WorkletScriptHandler STS Delivery Queue");
    rv = rr->RetargetDeliveryTo(queue);
    if (NS_FAILED(rv)) {
      NS_WARNING("Failed to dispatch the nsIInputStreamPump to a IO thread.");
    }
  }
}

NS_IMETHODIMP WorkletScriptHandler::OnStreamComplete(nsIStreamLoader* aLoader,
                                                     nsISupports* aContext,
                                                     nsresult aStatus,
                                                     uint32_t aStringLen,
                                                     const uint8_t* aString) {
  MOZ_ASSERT(NS_IsMainThread());

  if (NS_FAILED(aStatus)) {
    HandleFailure(aStatus);
    return NS_OK;
  }

  // Copy the buffer and decode it on worklet thread, as we can only access
  // ModuleLoadRequest on worklet thread.
  UniquePtr<uint8_t[]> scriptTextBuf = MakeUnique<uint8_t[]>(aStringLen);
  memcpy(scriptTextBuf.get(), aString, aStringLen);

  nsCOMPtr<nsIRunnable> runnable =
      new FetchCompleteRunnable(mWorklet->mImpl, mURI, NS_OK,
#ifdef NIGHTLY_BUILD
                                mHasWasmMimeTypeEssence,
#endif
                                std::move(scriptTextBuf), aStringLen);

  if (NS_FAILED(mWorklet->mImpl->SendControlMessage(runnable.forget()))) {
    HandleFailure(NS_ERROR_FAILURE);
  }

  return NS_OK;
}

void WorkletScriptHandler::RejectedCallback(JSContext* aCx,
                                            JS::Handle<JS::Value> aValue,
                                            ErrorResult& aRv) {
  MOZ_ASSERT(NS_IsMainThread());

  // https://html.spec.whatwg.org/multipage/worklets.html#dom-worklet-addmodule
  // Step 6.4.1. If script is null, then:
  //   Step 1.1.2. Reject promise with an "AbortError" DOMException.
  HandleFailure(NS_ERROR_DOM_ABORT_ERR);
}

void WorkletScriptHandler::HandleFailure(nsresult aResult) {
  DispatchFetchCompleteToWorklet(aResult);
}

void WorkletScriptHandler::DispatchFetchCompleteToWorklet(nsresult aRv) {
  nsCOMPtr<nsIRunnable> runnable =
      new FetchCompleteRunnable(mWorklet->mImpl, mURI, aRv,
#ifdef NIGHTLY_BUILD
                                mHasWasmMimeTypeEssence,
#endif
                                nullptr, 0);

  if (NS_WARN_IF(
          NS_FAILED(mWorklet->mImpl->SendControlMessage(runnable.forget())))) {
    NS_WARNING("Failed to dispatch FetchCompleteRunnable to a worklet thread.");
  }
}

}  // namespace mozilla::dom

Messung V0.5 in Prozent
C=91 H=95 G=92

¤ Dauer der Verarbeitung: 0.15 Sekunden  (vorverarbeitet am  2026-08-25) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.