File: Callbacks.cpp

package info (click to toggle)
firefox 142.0.1-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 4,591,884 kB
  • sloc: cpp: 7,451,570; javascript: 6,392,463; ansic: 3,712,584; python: 1,388,569; xml: 629,223; asm: 426,919; java: 184,857; sh: 63,439; makefile: 19,150; objc: 13,059; perl: 12,983; yacc: 4,583; cs: 3,846; pascal: 3,352; lex: 1,720; ruby: 1,003; exp: 762; php: 436; lisp: 258; awk: 247; sql: 66; sed: 53; csh: 10
file content (112 lines) | stat: -rw-r--r-- 4,329 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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 "nsPrintfCString.h"
#include "nsString.h"
#include "nsThreadUtils.h"
#include "mozilla/uniffi/OwnedRustBuffer.h"
#include "mozilla/dom/RootedDictionary.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/UniFFIBinding.h"
#include "mozilla/uniffi/Callbacks.h"
#include "mozilla/Maybe.h"
#include "mozilla/Logging.h"
#include "mozilla/RefPtr.h"
#include "mozilla/UniquePtr.h"

namespace mozilla::uniffi {
extern mozilla::LazyLogModule gUniffiLogger;

void AsyncCallbackMethodHandlerBase::ScheduleAsyncCall(
    UniquePtr<AsyncCallbackMethodHandlerBase> aHandler,
    StaticRefPtr<dom::UniFFICallbackHandler>* aJsHandler) {
  nsresult dispatchResult = NS_DispatchToMainThread(NS_NewRunnableFunction(
      "UniFFI callback", [handler = std::move(aHandler),
                          aJsHandler]() MOZ_CAN_RUN_SCRIPT_BOUNDARY mutable {
        auto reportError = MakeScopeExit([&handler] {
          dom::RootedDictionary<dom::UniFFIScaffoldingCallResult> callResult(
              dom::RootingCx());
          callResult.mCode = dom::UniFFIScaffoldingCallCode::Internal_error;
          handler->HandleReturn(callResult, IgnoreErrors());
        });

        // Take our own reference to the callback handler to ensure that it
        // stays alive for the duration of this call
        RefPtr<dom::UniFFICallbackHandler> jsHandler = *aJsHandler;
        if (!jsHandler) {
          MOZ_LOG(gUniffiLogger, LogLevel::Error,
                  ("[%s] called, but JS handler not registered",
                   handler->mUniffiMethodName));
          return;
        }

        JSObject* global = jsHandler->CallbackGlobalOrNull();
        if (!global) {
          MOZ_LOG(
              gUniffiLogger, LogLevel::Error,
              ("[%s] JS handler has null global", handler->mUniffiMethodName));
          return;
        }

        dom::AutoEntryScript aes(global, handler->mUniffiMethodName);

        IgnoredErrorResult error;
        RefPtr<dom::Promise> promise =
            handler->MakeCall(aes.cx(), jsHandler, error);
        if (error.Failed()) {
          MOZ_LOG(
              gUniffiLogger, LogLevel::Error,
              ("[%s] Error invoking JS handler", handler->mUniffiMethodName));
          return;
        }

        reportError.release();
        if (promise) {
          auto promiseHandler = MakeRefPtr<PromiseHandler>(std::move(handler));
          promise->AppendNativeHandler(promiseHandler);
        }
      }));

  if (NS_FAILED(dispatchResult)) {
    MOZ_LOG(gUniffiLogger, LogLevel::Error,
            ("[UniFFI] Error dispatching UniFFI callback task"));
  }
}

MOZ_CAN_RUN_SCRIPT
already_AddRefed<dom::Promise> CallbackFreeHandler::MakeCall(
    JSContext* aCx, dom::UniFFICallbackHandler* aJsHandler,
    ErrorResult& aError) {
  aJsHandler->Destroy(mUniffiHandle.IntoRust(), aError);
  // CallbackFreeHandler works like a fire-and-forget callback and returns
  // nullptr.  There's no Rust code that's awaiting this result.
  return nullptr;
}

NS_IMPL_ISUPPORTS0(AsyncCallbackMethodHandlerBase::PromiseHandler);

void AsyncCallbackMethodHandlerBase::PromiseHandler::ResolvedCallback(
    JSContext* aCx, JS::Handle<JS::Value> aValue, ErrorResult& aRv) {
  dom::RootedDictionary<dom::UniFFIScaffoldingCallResult> callResult(aCx);
  if (!callResult.Init(aCx, aValue)) {
    JS_ClearPendingException(aCx);
    MOZ_LOG(
        gUniffiLogger, LogLevel::Error,
        ("[%s] callback method did not return a UniFFIScaffoldingCallResult",
         mHandler->mUniffiMethodName));
    callResult.mCode = dom::UniFFIScaffoldingCallCode::Internal_error;
  }
  mHandler->HandleReturn(callResult, aRv);
}

void AsyncCallbackMethodHandlerBase::PromiseHandler::RejectedCallback(
    JSContext* aCx, JS::Handle<JS::Value>, ErrorResult& aRv) {
  dom::RootedDictionary<dom::UniFFIScaffoldingCallResult> callResult(aCx);
  callResult.mCode = dom::UniFFIScaffoldingCallCode::Internal_error;
  mHandler->HandleReturn(callResult, aRv);
}

}  // namespace mozilla::uniffi