Files
tubestation/toolkit/components/uniffi-js/UniFFICallbacks.cpp
Ben Dean-Kawamura 67b31442a0 Bug 1913982 - Re-enable UniFFI callback interfaces, r=nika,lina
The FFI for this changed upstream.  Instead of registering a single
function that inputs a single buffer packed with all arguments, you now
register a function for each method where there is a 1-1 mapping of
arguments. The entire interface is represented by a "vtable" -- AKA a
struct that has a field for each of the method handler functions

To implement the methods, I stole the pattern we were using for regular
calls where we define a base class that's implemented by normal code and
a subclass that's implemented by generated code.

Registering/deregistering callback interfaces is now handled by the
generated code directly.  It's simpler this way and now that we don't
have the split between regular and fixture scaffolding, there's not much
need for shared code to handle this.

Kept the decision before to only support "fire-and-forget" callbacks. I
think we will want to revisit this when the we support UniFFI async, but
we can save that for later.

Differential Revision: https://phabricator.services.mozilla.com/D222027
2024-10-02 17:49:09 +00:00

73 lines
2.7 KiB
C++

/* -*- 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/dom/OwnedRustBuffer.h"
#include "mozilla/dom/RootedDictionary.h"
#include "mozilla/dom/UniFFIBinding.h"
#include "mozilla/dom/UniFFICallbacks.h"
#include "mozilla/Maybe.h"
#include "mozilla/Logging.h"
#include "mozilla/RefPtr.h"
#include "mozilla/UniquePtr.h"
static mozilla::LazyLogModule UNIFFI_INVOKE_CALLBACK_LOGGER("uniffi");
namespace mozilla::uniffi {
void UniffiCallbackMethodHandlerBase::FireAndForget(
UniquePtr<UniffiCallbackMethodHandlerBase> aHandler,
StaticRefPtr<dom::UniFFICallbackHandler>* aJsHandler) {
nsresult dispatchResult = NS_DispatchToMainThread(NS_NewRunnableFunction(
"UniFFI callback", [handler = std::move(aHandler),
aJsHandler]() MOZ_CAN_RUN_SCRIPT_BOUNDARY {
// 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(UNIFFI_INVOKE_CALLBACK_LOGGER, LogLevel::Error,
("[UniFFI] %s called, but JS handler not registered",
handler->mInterfaceName));
return;
}
JSObject* global = jsHandler->CallbackGlobalOrNull();
if (!global) {
MOZ_LOG(UNIFFI_INVOKE_CALLBACK_LOGGER, LogLevel::Error,
("[UniFFI] JS handler for %s has null global",
handler->mInterfaceName));
return;
}
dom::AutoEntryScript aes(global, handler->mInterfaceName);
IgnoredErrorResult error;
handler->MakeCall(aes.cx(), jsHandler, error);
if (error.Failed()) {
MOZ_LOG(UNIFFI_INVOKE_CALLBACK_LOGGER, LogLevel::Error,
("[UniFFI] Error invoking JS handler for %s",
handler->mInterfaceName));
return;
}
}));
if (NS_FAILED(dispatchResult)) {
MOZ_LOG(UNIFFI_INVOKE_CALLBACK_LOGGER, LogLevel::Error,
("[UniFFI] Error dispatching UniFFI callback task"));
}
}
void UniffiCallbackFreeHandler::MakeCall(JSContext* aCx,
dom::UniFFICallbackHandler* aJsHandler,
ErrorResult& aError) {
aJsHandler->Destroy(mObjectHandle, aError);
}
} // namespace mozilla::uniffi