File: Callbacks.h

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 (136 lines) | stat: -rw-r--r-- 5,054 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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/* -*- 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/. */

#ifndef mozilla_UniFFICallbacks_h
#define mozilla_UniFFICallbacks_h

#include "mozilla/StaticPtr.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/dom/PromiseNativeHandler.h"
#include "mozilla/dom/UniFFIScaffolding.h"
#include "mozilla/uniffi/FfiValue.h"
#include "mozilla/uniffi/Rust.h"

namespace mozilla::uniffi {

/**
 * Generated code to register a callback handler.
 *
 * This stores a reference to JS callback handler.  When Rust wants to invoke a
 * callback method, we will use this reference.
 *
 * Also, call the Rust FFI function to initialize the callback interface.
 */
void RegisterCallbackHandler(uint64_t aInterfaceId,
                             dom::UniFFICallbackHandler& aCallbackHandler,
                             ErrorResult& aError);

/**
 * Generated code to deregister a callback handler.
 *
 * This releases the reference to the JS callback handler. After this, our
 * vtable will still be registered with Rust, but all method calls will fail.
 */
void DeregisterCallbackHandler(uint64_t aInterfaceId, ErrorResult& aError);

/**
 * Base class for async callback interface method handlers
 *
 * In addition to handling actual async methods this also handles
 * fire-and-forget methods.  These are sync methods wrapped to be async, where
 * we ignore the return value.
 *
 * The generated subclass handles the specifics of each call, while the code in
 * the base class handles generic aspects of the call
 *
 * The generated subclass stores all data needed to make the call, including the
 * arguments passed from Rust internally. MakeCall must only be called
 * once-per-object, since it may consume some of the arguments. We create a new
 * UniffiCallbackMethodHandlerBase subclass instance for each callback interface
 * call from Rust.
 */
class AsyncCallbackMethodHandlerBase {
 public:
  AsyncCallbackMethodHandlerBase(const char* aUniffiMethodName,
                                 uint64_t aUniffiHandle)
      : mUniffiMethodName(aUniffiMethodName), mUniffiHandle(aUniffiHandle) {}

  // Invoke the callback method using a JS handler
  //
  // For fire-and-forget callbacks, this will return `nullptr`
  MOZ_CAN_RUN_SCRIPT
  virtual already_AddRefed<dom::Promise> MakeCall(
      JSContext* aCx, dom::UniFFICallbackHandler* aJsHandler,
      ErrorResult& aError) = 0;

  // Handle returning a value to Rust.
  //
  // The default implementation does nothing, this is what we use for the `free`
  // callback and also fire-and-forget callbacks.  For async callbacks, we
  // generate a subclass for each return type.
  //
  // HandleReturn will be called on the main thread, and can be invoked
  // synchronously in error cases.
  virtual void HandleReturn(const dom::RootedDictionary<
                                dom::UniFFIScaffoldingCallResult>& aReturnValue,
                            ErrorResult& aError) {}

  virtual ~AsyncCallbackMethodHandlerBase() = default;

  // ---- Generic entry points ----

  // Queue an async call on the JS main thread
  static void ScheduleAsyncCall(
      UniquePtr<AsyncCallbackMethodHandlerBase> aHandler,
      StaticRefPtr<dom::UniFFICallbackHandler>* aJsHandler);

 protected:
  // Name of the callback interface method
  const char* mUniffiMethodName;
  FfiValueInt<uint64_t> mUniffiHandle;

 private:
  // PromiseNativeHandler for async callback interface methods
  //
  // This is appended to the end of the JS promise chain to call the Rust
  // complete function.
  class PromiseHandler final : public dom::PromiseNativeHandler {
   public:
    NS_DECL_ISUPPORTS

    explicit PromiseHandler(UniquePtr<AsyncCallbackMethodHandlerBase> aHandler)
        : mHandler(std::move(aHandler)) {}

    MOZ_CAN_RUN_SCRIPT
    virtual void ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue,
                                  ErrorResult& aRv) override;
    MOZ_CAN_RUN_SCRIPT
    virtual void RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue,
                                  ErrorResult& aRv) override;

   private:
    UniquePtr<AsyncCallbackMethodHandlerBase> mHandler;

    ~PromiseHandler() = default;
  };
};

// Class to handle the free method, this is an implicit method for each callback
// interface. In inputs no arguments and has index=0.
class CallbackFreeHandler : public AsyncCallbackMethodHandlerBase {
 public:
  CallbackFreeHandler(const char* aUniffiMethodName, uint64_t aUniffiHandle)
      : AsyncCallbackMethodHandlerBase(aUniffiMethodName, aUniffiHandle) {}

  MOZ_CAN_RUN_SCRIPT
  already_AddRefed<dom::Promise> MakeCall(
      JSContext* aCx, dom::UniFFICallbackHandler* aJsHandler,
      ErrorResult& aError) override;
};

}  // namespace mozilla::uniffi

#endif  // mozilla_UniFFICallbacks_h