Bug 1951241 - Refactor ScaffoldingConverter.h, r=markh,nika,frontend-codestyle-reviewers

Replaced `ScaffoldingConverter` with a set of `FfiValue*` classes.  The
differences are:

* The new classes better match other `uniffi-bindgen-gecko-js` names,
  and also use familiar UniFFI terms like `Lift` and `Lower`.
* Object handles are now freed if there's an error.
* The new classes store the FFI value internal rather than defining an
  `IntermediateType` associated type.
* Moved header files into `mozilla/uniffi/` and removed the `UniFFI`
  prefix from the filename.  This avoids weird filenames like
  `UniFFIFfiValue.h`

Differential Revision: https://phabricator.services.mozilla.com/D240696
This commit is contained in:
Ben Dean-Kawamura
2025-04-11 16:49:50 +00:00
parent 02e039347d
commit c7d555e585
24 changed files with 3527 additions and 2114 deletions

View File

@@ -69,8 +69,7 @@ xpcom/reflect/xptcall/md/unix/.*
# Askama template code, which isn't valid C++ in its original form # Askama template code, which isn't valid C++ in its original form
toolkit/components/uniffi-bindgen-gecko-js/src/templates/.* toolkit/components/uniffi-bindgen-gecko-js/src/templates/.*
# Generated from that template code # Generated from that template code
toolkit/components/uniffi-js/UniFFIGeneratedScaffolding.cpp toolkit/components/uniffi-js/GeneratedScaffolding.cpp
toolkit/components/uniffi-js/UniFFIFixtureScaffolding.cpp
# Generated from ./tools/rewriting/ThirdPartyPaths.txt # Generated from ./tools/rewriting/ThirdPartyPaths.txt
# awk '{print ""$1".*"}' ./tools/rewriting/ThirdPartyPaths.txt # awk '{print ""$1".*"}' ./tools/rewriting/ThirdPartyPaths.txt

View File

@@ -1563,8 +1563,7 @@ toolkit/components/nimbus/schemas/ExperimentFeatureManifest.schema.json
toolkit/components/nimbus/schemas/NimbusExperiment.schema.json toolkit/components/nimbus/schemas/NimbusExperiment.schema.json
toolkit/components/pdfjs/PdfJsDefaultPrefs.js toolkit/components/pdfjs/PdfJsDefaultPrefs.js
toolkit/components/pdfjs/PdfJsOverridePrefs.js toolkit/components/pdfjs/PdfJsOverridePrefs.js
toolkit/components/uniffi-js/UniFFIGeneratedScaffolding.cpp toolkit/components/uniffi-js/GeneratedScaffolding.cpp
toolkit/components/uniffi-js/UniFFIFixtureScaffolding.cpp
toolkit/components/uniffi-bindgen-gecko-js/fixtures/generated toolkit/components/uniffi-bindgen-gecko-js/fixtures/generated
tools/@types/tspaths.json tools/@types/tspaths.json
tools/browsertime/package.json tools/browsertime/package.json

1
Cargo.lock generated
View File

@@ -2524,6 +2524,7 @@ dependencies = [
name = "gkrust-uniffi-components" name = "gkrust-uniffi-components"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"hashbrown 0.15.2",
"relevancy", "relevancy",
"search", "search",
"suggest", "suggest",

View File

@@ -22,6 +22,8 @@ search = "0.1"
suggest = "0.1" suggest = "0.1"
relevancy = "0.1" relevancy = "0.1"
webext-storage = "0.1" webext-storage = "0.1"
# Workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=1959469
hashbrown = { version = "0.15.2", features = [ "default-hasher" ] }
[features] [features]
# Should we depend on xpcom crates? # Should we depend on xpcom crates?

View File

@@ -7,7 +7,7 @@ import subprocess
from mach.decorators import Command, SubCommand from mach.decorators import Command, SubCommand
CPP_PATH = "toolkit/components/uniffi-js/UniFFIGeneratedScaffolding.cpp" CPP_PATH = "toolkit/components/uniffi-js/GeneratedScaffolding.cpp"
JS_DIR = "toolkit/components/uniffi-bindgen-gecko-js/components/generated" JS_DIR = "toolkit/components/uniffi-bindgen-gecko-js/components/generated"
FIXTURE_JS_DIR = "toolkit/components/uniffi-bindgen-gecko-js/fixtures/generated" FIXTURE_JS_DIR = "toolkit/components/uniffi-bindgen-gecko-js/fixtures/generated"
DOCS_PATH = "docs/rust-components/api/js/" DOCS_PATH = "docs/rust-components/api/js/"

View File

@@ -93,7 +93,7 @@ impl CPPScaffoldingTemplate {
arg_types: ffi_func arg_types: ffi_func
.arguments() .arguments()
.iter() .iter()
.map(|a| cpp_type(&a.type_())) .map(|a| ffi_type_name(&a.type_()))
.chain( .chain(
ffi_func ffi_func
.has_rust_call_status_arg() .has_rust_call_status_arg()
@@ -108,7 +108,7 @@ impl CPPScaffoldingTemplate {
arg_types: ffi_callback arg_types: ffi_callback
.arguments() .arguments()
.into_iter() .into_iter()
.map(|a| cpp_type(&a.type_())) .map(|a| ffi_type_name(&a.type_()))
.chain( .chain(
ffi_callback ffi_callback
.has_rust_call_status_arg() .has_rust_call_status_arg()
@@ -125,7 +125,7 @@ impl CPPScaffoldingTemplate {
.into_iter() .into_iter()
.map(|f| FfiFieldCpp { .map(|f| FfiFieldCpp {
name: f.name().to_snake_case(), name: f.name().to_snake_case(),
type_: cpp_type(&f.type_()), type_: ffi_type_name(&f.type_()),
}) })
.collect(), .collect(),
}), }),
@@ -142,6 +142,7 @@ impl CPPScaffoldingTemplate {
.map(move |obj| PointerType { .map(move |obj| PointerType {
object_id: object_ids.get(&c.ci, obj), object_id: object_ids.get(&c.ci, obj),
name: pointer_type(&c.ci.namespace(), obj.name()), name: pointer_type(&c.ci.namespace(), obj.name()),
ffi_value_class: pointer_ffi_value_class(&c.ci.namespace(), obj.name()),
label: format!("{}::{}", c.ci.namespace(), obj.name()), label: format!("{}::{}", c.ci.namespace(), obj.name()),
clone_fn: obj.ffi_object_clone().name().to_string(), clone_fn: obj.ffi_object_clone().name().to_string(),
free_fn: obj.ffi_object_free().name().to_string(), free_fn: obj.ffi_object_free().name().to_string(),
@@ -182,7 +183,7 @@ impl CPPScaffoldingTemplate {
let cbi_name_snake = cbi.name().to_snake_case(); let cbi_name_snake = cbi.name().to_snake_case();
CallbackInterfaceVTable { CallbackInterfaceVTable {
type_: cpp_type(&cbi.vtable()), type_: ffi_type_name(&cbi.vtable()),
var_name: format!("kCallbackInterfaceVtable{cbi_name}"), var_name: format!("kCallbackInterfaceVtable{cbi_name}"),
method_handlers: cbi method_handlers: cbi
.vtable_methods() .vtable_methods()
@@ -196,13 +197,13 @@ impl CPPScaffoldingTemplate {
arguments: method arguments: method
.arguments() .arguments()
.iter() .iter()
.map(|arg| CallbackMethodArgument { .map(|arg| {
name: arg.name().to_snake_case(), let ffi_type = arg.as_type().into();
type_: cpp_type(&arg.as_type().into()), CallbackMethodArgument {
scaffolding_converter: scaffolding_converter( name: arg.name().to_snake_case(),
ci, ffi_type: ffi_type_name(&ffi_type),
&arg.as_type().into(), ffi_value_class: ffi_value_class(ci, &ffi_type),
), }
}) })
.collect(), .collect(),
} }
@@ -297,6 +298,7 @@ struct FfiFieldCpp {
struct PointerType { struct PointerType {
object_id: usize, object_id: usize,
name: String, name: String,
ffi_value_class: String,
label: String, label: String,
clone_fn: String, clone_fn: String,
free_fn: String, free_fn: String,
@@ -337,8 +339,8 @@ struct CallbackMethodHandler {
struct CallbackMethodArgument { struct CallbackMethodArgument {
name: String, name: String,
type_: String, ffi_type: String,
scaffolding_converter: String, ffi_value_class: String,
} }
struct ScaffoldingCall { struct ScaffoldingCall {
@@ -366,7 +368,7 @@ impl ScaffoldingCall {
.into_iter() .into_iter()
.map(|a| ScaffoldingCallArgument { .map(|a| ScaffoldingCallArgument {
var_name: format!("m{}", a.name().to_upper_camel_case()), var_name: format!("m{}", a.name().to_upper_camel_case()),
scaffolding_converter: scaffolding_converter(ci, &a.type_()), ffi_value_class: ffi_value_class(ci, &a.type_()),
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
@@ -384,8 +386,9 @@ impl ScaffoldingCall {
// function always returns a handle. // function always returns a handle.
return_type: callable return_type: callable
.return_type() .return_type()
.map(|return_type| FfiType::from(return_type))
.map(|return_type| ScaffoldingCallReturnType { .map(|return_type| ScaffoldingCallReturnType {
scaffolding_converter: scaffolding_converter(ci, &return_type.into()), ffi_value_class: ffi_value_class(ci, &return_type),
}), }),
arguments, arguments,
async_info, async_info,
@@ -398,12 +401,12 @@ impl ScaffoldingCall {
} }
struct ScaffoldingCallReturnType { struct ScaffoldingCallReturnType {
scaffolding_converter: String, ffi_value_class: String,
} }
struct ScaffoldingCallArgument { struct ScaffoldingCallArgument {
var_name: String, var_name: String,
scaffolding_converter: String, ffi_value_class: String,
} }
struct ScaffoldingCallAsyncInfo { struct ScaffoldingCallAsyncInfo {
@@ -412,7 +415,7 @@ struct ScaffoldingCallAsyncInfo {
free_fn: String, free_fn: String,
} }
fn scaffolding_converter(ci: &ComponentInterface, ffi_type: &FfiType) -> String { fn ffi_value_class(ci: &ComponentInterface, ffi_type: &FfiType) -> String {
match ffi_type { match ffi_type {
FfiType::RustArcPtr(name) => { FfiType::RustArcPtr(name) => {
// Check if this is an external type // Check if this is an external type
@@ -420,18 +423,24 @@ fn scaffolding_converter(ci: &ComponentInterface, ffi_type: &FfiType) -> String
let external_ty_name = ty.name().expect("External type without name"); let external_ty_name = ty.name().expect("External type without name");
let crate_name = ty.module_path().expect("External type without module path"); let crate_name = ty.module_path().expect("External type without module path");
if external_ty_name == name { if external_ty_name == name {
return format!( return pointer_ffi_value_class(crate_name_to_namespace(&crate_name), name);
"ScaffoldingObjectConverter<&{}>",
pointer_type(crate_name_to_namespace(&crate_name), name),
);
} }
} }
format!( pointer_ffi_value_class(ci.namespace(), name)
"ScaffoldingObjectConverter<&{}>",
pointer_type(ci.namespace(), name),
)
} }
_ => format!("ScaffoldingConverter<{}>", cpp_type(ffi_type)), FfiType::UInt8
| FfiType::Int8
| FfiType::UInt16
| FfiType::Int16
| FfiType::UInt32
| FfiType::Int32
| FfiType::UInt64
| FfiType::Int64 => format!("FfiValueInt<{}>", ffi_type_name(ffi_type)),
FfiType::Float32 | FfiType::Float64 => {
format!("FfiValueFloat<{}>", ffi_type_name(ffi_type))
}
FfiType::RustBuffer(_) => "FfiValueRustBuffer".to_owned(),
_ => format!("FfiConverter<{}>", ffi_type_name(ffi_type)),
} }
} }
@@ -443,8 +452,16 @@ fn pointer_type(namespace: &str, name: &str) -> String {
) )
} }
// Type for the Rust scaffolding code fn pointer_ffi_value_class(namespace: &str, name: &str) -> String {
fn cpp_type(ffi_type: &FfiType) -> String { format!(
"FfiValueObjectHandle{}{}",
namespace.to_upper_camel_case(),
name.to_upper_camel_case()
)
}
// C++ type for an FFI value
fn ffi_type_name(ffi_type: &FfiType) -> String {
match ffi_type { match ffi_type {
FfiType::UInt8 => "uint8_t".to_owned(), FfiType::UInt8 => "uint8_t".to_owned(),
FfiType::Int8 => "int8_t".to_owned(), FfiType::Int8 => "int8_t".to_owned(),
@@ -464,14 +481,14 @@ fn cpp_type(ffi_type: &FfiType) -> String {
FfiType::Callback(name) | FfiType::Struct(name) => name.to_owned(), FfiType::Callback(name) | FfiType::Struct(name) => name.to_owned(),
FfiType::VoidPointer => "void*".to_owned(), FfiType::VoidPointer => "void*".to_owned(),
FfiType::MutReference(inner) | FfiType::Reference(inner) => { FfiType::MutReference(inner) | FfiType::Reference(inner) => {
format!("{}*", cpp_type(inner.as_ref())) format!("{}*", ffi_type_name(inner.as_ref()))
} }
} }
} }
fn return_type(ffi_type: Option<&FfiType>) -> String { fn return_type(ffi_type: Option<&FfiType>) -> String {
match ffi_type { match ffi_type {
Some(t) => cpp_type(t), Some(t) => ffi_type_name(t),
None => "void".to_owned(), None => "void".to_owned(),
} }
} }

View File

@@ -10,12 +10,12 @@
#include "mozilla/StaticPtr.h" #include "mozilla/StaticPtr.h"
#include "mozilla/UniquePtr.h" #include "mozilla/UniquePtr.h"
#include "mozilla/dom/Promise.h" #include "mozilla/dom/Promise.h"
#include "mozilla/dom/ScaffoldingConverter.h" #include "mozilla/uniffi/Call.h"
#include "mozilla/dom/UniFFICall.h" #include "mozilla/uniffi/Callbacks.h"
#include "mozilla/dom/UniFFICallbacks.h" #include "mozilla/uniffi/FfiValue.h"
#include "mozilla/dom/UniFFIPointerType.h" #include "mozilla/uniffi/PointerType.h"
#include "mozilla/dom/UniFFIScaffolding.h" #include "mozilla/dom/UniFFIScaffolding.h"
#include "mozilla/dom/UniFFIRust.h" #include "mozilla/uniffi/Rust.h"
namespace mozilla::uniffi { namespace mozilla::uniffi {
@@ -53,7 +53,7 @@ extern "C" {
{%- endfor %} {%- endfor %}
} }
// Define pointer types // Define pointer types and FfiValueObjectHandle* classes
{%- for (preprocessor_condition, pointer_types, preprocessor_condition_end) in all_pointer_types.iter() %} {%- for (preprocessor_condition, pointer_types, preprocessor_condition_end) in all_pointer_types.iter() %}
{{ preprocessor_condition }} {{ preprocessor_condition }}
{%- for pointer_type in pointer_types %} {%- for pointer_type in pointer_types %}
@@ -62,6 +62,75 @@ const static mozilla::uniffi::UniFFIPointerType {{ pointer_type.name }} {
{{ pointer_type.clone_fn }}, {{ pointer_type.clone_fn }},
{{ pointer_type.free_fn }}, {{ pointer_type.free_fn }},
}; };
class {{ pointer_type.ffi_value_class }} {
private:
void* mValue = nullptr;
public:
{{ pointer_type.ffi_value_class }}() = default;
explicit {{ pointer_type.ffi_value_class }}(void* aValue) : mValue(aValue) {}
// Delete copy constructor and assignment as this type is non-copyable.
{{ pointer_type.ffi_value_class }}(const {{ pointer_type.ffi_value_class }}&) = delete;
{{ pointer_type.ffi_value_class }}& operator=(const {{ pointer_type.ffi_value_class }}&) = delete;
{{ pointer_type.ffi_value_class }}& operator=({{ pointer_type.ffi_value_class }}&& aOther) {
FreeHandle();
mValue = aOther.mValue;
aOther.mValue = nullptr;
return *this;
}
void Lower(const dom::OwningUniFFIScaffoldingValue& aValue,
ErrorResult& aError) {
if (!aValue.IsUniFFIPointer()) {
aError.ThrowTypeError("Expected UniFFI pointer argument"_ns);
return;
}
dom::UniFFIPointer& value = aValue.GetAsUniFFIPointer();
if (!value.IsSamePtrType(&{{ pointer_type.name }})) {
aError.ThrowTypeError("Incorrect UniFFI pointer type"_ns);
return;
}
FreeHandle();
mValue = value.ClonePtr();
}
void Lift(JSContext* aContext, dom::OwningUniFFIScaffoldingValue* aDest,
ErrorResult& aError) {
aDest->SetAsUniFFIPointer() =
dom::UniFFIPointer::Create(mValue, &{{ pointer_type.name }});
mValue = nullptr;
}
void* IntoRust() {
auto temp = mValue;
mValue = nullptr;
return temp;
}
static {{ pointer_type.ffi_value_class }} FromRust(void* aValue) {
return {{ pointer_type.ffi_value_class }}(aValue);
}
void FreeHandle() {
if (mValue) {
RustCallStatus callStatus{};
({{ pointer_type.free_fn }})(mValue, &callStatus);
// No need to check `RustCallStatus`, it's only part of the API to match
// other FFI calls. The free function can never fail.
}
}
~{{ pointer_type.ffi_value_class }}() {
// If the pointer is non-null, this means Lift/IntoRust was never called
// because there was some failure along the way. Free the pointer to avoid a
// leak
FreeHandle();
}
};
{%- endfor %} {%- endfor %}
{{ preprocessor_condition_end }} {{ preprocessor_condition_end }}
{%- endfor %} {%- endfor %}
@@ -78,15 +147,15 @@ static StaticRefPtr<dom::UniFFICallbackHandler> {{ cbi.js_handler_var }};
class {{ handler.class_name }} : public UniffiCallbackMethodHandlerBase { class {{ handler.class_name }} : public UniffiCallbackMethodHandlerBase {
private: private:
// Rust arguments, converted using ScaffoldingConverter::FromRust. // Rust arguments
{%- for a in handler.arguments %} {%- for a in handler.arguments %}
typename {{ a.scaffolding_converter }}::IntermediateType {{ a.name }}; {{ a.ffi_value_class }} {{ a.name }}{};
{%- endfor %} {%- endfor %}
public: public:
{{ handler.class_name }}(size_t aObjectHandle{%- for a in handler.arguments %}, {{ a.type_ }} {{ a.name }}{%- endfor %}) {{ handler.class_name }}(size_t aObjectHandle{%- for a in handler.arguments %}, {{ a.ffi_type }} {{ a.name }}{%- endfor %})
: UniffiCallbackMethodHandlerBase("{{ cbi.name }}", aObjectHandle) : UniffiCallbackMethodHandlerBase("{{ cbi.name }}", aObjectHandle)
{%- for a in handler.arguments %}, {{ a.name }}({{ a.scaffolding_converter }}::FromRust({{ a.name }})){% endfor %} { {%- for a in handler.arguments %}, {{ a.name }}({{ a.ffi_value_class }}::FromRust({{ a.name }})){% endfor %} {
} }
MOZ_CAN_RUN_SCRIPT MOZ_CAN_RUN_SCRIPT
@@ -102,9 +171,8 @@ public:
// Convert each argument // Convert each argument
{%- for a in handler.arguments %} {%- for a in handler.arguments %}
{{ a.scaffolding_converter }}::IntoJs( {{ a.name }}.Lift(
aCx, aCx,
std::move(this->{{ a.name }}),
&uniffiArgs[{{ loop.index0 }}], &uniffiArgs[{{ loop.index0 }}],
aError); aError);
if (aError.Failed()) { if (aError.Failed()) {
@@ -123,7 +191,7 @@ public:
extern "C" void {{ handler.fn_name }}( extern "C" void {{ handler.fn_name }}(
uint64_t uniffiHandle, uint64_t uniffiHandle,
{% for a in handler.arguments %}{{ a.type_ }} {{ a.name }}, {% endfor %} {% for a in handler.arguments %}{{ a.ffi_type }} {{ a.name }}, {% endfor %}
void* uniffiOutReturn, void* uniffiOutReturn,
RustCallStatus* uniffiCallStatus RustCallStatus* uniffiCallStatus
) { ) {
@@ -223,20 +291,20 @@ class {{ scaffolding_call.handler_class_name }} : public UniffiSyncCallHandler {
private: private:
// PrepareRustArgs stores the resulting arguments in these fields // PrepareRustArgs stores the resulting arguments in these fields
{%- for arg in scaffolding_call.arguments %} {%- for arg in scaffolding_call.arguments %}
typename {{ arg.scaffolding_converter }}::IntermediateType {{ arg.var_name }}; {{ arg.ffi_value_class }} {{ arg.var_name }}{};
{%- endfor %} {%- endfor %}
// MakeRustCall stores the result of the call in these fields // MakeRustCall stores the result of the call in these fields
{%- match scaffolding_call.return_type %} {%- match scaffolding_call.return_type %}
{%- when Some(return_type) %} {%- when Some(return_type) %}
typename {{ return_type.scaffolding_converter }}::IntermediateType mUniffiReturnValue; {{ return_type.ffi_value_class }} mUniffiReturnValue{};
{%- else %} {%- else %}
{%- endmatch %} {%- endmatch %}
public: public:
void PrepareRustArgs(const dom::Sequence<dom::OwningUniFFIScaffoldingValue>& aArgs, ErrorResult& aError) override { void PrepareRustArgs(const dom::Sequence<dom::OwningUniFFIScaffoldingValue>& aArgs, ErrorResult& aError) override {
{%- for arg in scaffolding_call.arguments %} {%- for arg in scaffolding_call.arguments %}
{{ arg.scaffolding_converter }}::FromJs(aArgs[{{ loop.index0 }}], &{{ arg.var_name }}, aError); {{ arg.var_name }}.Lower(aArgs[{{ loop.index0 }}], aError);
if (aError.Failed()) { if (aError.Failed()) {
return; return;
} }
@@ -246,10 +314,10 @@ public:
void MakeRustCall(RustCallStatus* aOutStatus) override { void MakeRustCall(RustCallStatus* aOutStatus) override {
{%- match scaffolding_call.return_type %} {%- match scaffolding_call.return_type %}
{%- when Some(return_type) %} {%- when Some(return_type) %}
mUniffiReturnValue = {{ return_type.scaffolding_converter }}::FromRust( mUniffiReturnValue = {{ return_type.ffi_value_class }}::FromRust(
{{ scaffolding_call.ffi_func_name }}( {{ scaffolding_call.ffi_func_name }}(
{%- for arg in scaffolding_call.arguments %} {%- for arg in scaffolding_call.arguments %}
{{ arg.scaffolding_converter }}::IntoRust(std::move({{ arg.var_name }})), {{ arg.var_name }}.IntoRust(),
{%- endfor %} {%- endfor %}
aOutStatus aOutStatus
) )
@@ -257,7 +325,7 @@ public:
{%- else %} {%- else %}
{{ scaffolding_call.ffi_func_name }}( {{ scaffolding_call.ffi_func_name }}(
{%- for arg in scaffolding_call.arguments %} {%- for arg in scaffolding_call.arguments %}
{{ arg.scaffolding_converter }}::IntoRust(std::move({{ arg.var_name }})), {{ arg.var_name }}.IntoRust(),
{%- endfor %} {%- endfor %}
aOutStatus aOutStatus
); );
@@ -267,9 +335,8 @@ public:
virtual void ExtractSuccessfulCallResult(JSContext* aCx, dom::Optional<dom::OwningUniFFIScaffoldingValue>& aDest, ErrorResult& aError) override { virtual void ExtractSuccessfulCallResult(JSContext* aCx, dom::Optional<dom::OwningUniFFIScaffoldingValue>& aDest, ErrorResult& aError) override {
{%- match scaffolding_call.return_type %} {%- match scaffolding_call.return_type %}
{%- when Some(return_type) %} {%- when Some(return_type) %}
{{ return_type.scaffolding_converter }}::IntoJs( mUniffiReturnValue.Lift(
aCx, aCx,
std::move(mUniffiReturnValue),
&aDest.Construct(), &aDest.Construct(),
aError aError
); );
@@ -286,7 +353,7 @@ private:
// Complete stores the result of the call in mUniffiReturnValue // Complete stores the result of the call in mUniffiReturnValue
{%- match scaffolding_call.return_type %} {%- match scaffolding_call.return_type %}
{%- when Some(return_type) %} {%- when Some(return_type) %}
typename {{ return_type.scaffolding_converter }}::IntermediateType mUniffiReturnValue; {{ return_type.ffi_value_class }} mUniffiReturnValue{};
{%- else %} {%- else %}
{%- endmatch %} {%- endmatch %}
@@ -296,8 +363,8 @@ protected:
// return a future. // return a future.
void PrepareArgsAndMakeRustCall(const dom::Sequence<dom::OwningUniFFIScaffoldingValue>& aArgs, ErrorResult& aError) override { void PrepareArgsAndMakeRustCall(const dom::Sequence<dom::OwningUniFFIScaffoldingValue>& aArgs, ErrorResult& aError) override {
{%- for arg in scaffolding_call.arguments %} {%- for arg in scaffolding_call.arguments %}
typename {{ arg.scaffolding_converter }}::IntermediateType {{ arg.var_name }}; {{ arg.ffi_value_class }} {{ arg.var_name }}{};
{{ arg.scaffolding_converter }}::FromJs(aArgs[{{ loop.index0 }}], &{{ arg.var_name }}, aError); {{ arg.var_name }}.Lower(aArgs[{{ loop.index0 }}], aError);
if (aError.Failed()) { if (aError.Failed()) {
return; return;
} }
@@ -305,7 +372,7 @@ protected:
mFutureHandle = {{ scaffolding_call.ffi_func_name }}( mFutureHandle = {{ scaffolding_call.ffi_func_name }}(
{%- for arg in scaffolding_call.arguments %} {%- for arg in scaffolding_call.arguments %}
{{ arg.scaffolding_converter }}::IntoRust(std::move({{ arg.var_name }})){% if !loop.last %},{% endif %} {{ arg.var_name }}.IntoRust(){% if !loop.last %},{% endif %}
{%- endfor %} {%- endfor %}
); );
} }
@@ -313,7 +380,7 @@ protected:
void CallCompleteFn(RustCallStatus* aOutStatus) override { void CallCompleteFn(RustCallStatus* aOutStatus) override {
{%- match scaffolding_call.return_type %} {%- match scaffolding_call.return_type %}
{%- when Some(return_type) %} {%- when Some(return_type) %}
mUniffiReturnValue = {{ return_type.scaffolding_converter }}::FromRust( mUniffiReturnValue = {{ return_type.ffi_value_class }}::FromRust(
{{ async_info.complete_fn }}(mFutureHandle, aOutStatus)); {{ async_info.complete_fn }}(mFutureHandle, aOutStatus));
{%- else %} {%- else %}
{{ async_info.complete_fn }}(mFutureHandle, aOutStatus); {{ async_info.complete_fn }}(mFutureHandle, aOutStatus);
@@ -324,9 +391,8 @@ public:
void ExtractSuccessfulCallResult(JSContext* aCx, dom::Optional<dom::OwningUniFFIScaffoldingValue>& aDest, ErrorResult& aError) override { void ExtractSuccessfulCallResult(JSContext* aCx, dom::Optional<dom::OwningUniFFIScaffoldingValue>& aDest, ErrorResult& aError) override {
{%- match scaffolding_call.return_type %} {%- match scaffolding_call.return_type %}
{%- when Some(return_type) %} {%- when Some(return_type) %}
{{ return_type.scaffolding_converter }}::IntoJs( mUniffiReturnValue.Lift(
aCx, aCx,
std::move(mUniffiReturnValue),
&aDest.Construct(), &aDest.Construct(),
aError aError
); );

View File

@@ -7,7 +7,7 @@
#include "nsThreadUtils.h" #include "nsThreadUtils.h"
#include "mozilla/dom/Promise.h" #include "mozilla/dom/Promise.h"
#include "mozilla/dom/RootedDictionary.h" #include "mozilla/dom/RootedDictionary.h"
#include "mozilla/dom/UniFFICall.h" #include "mozilla/uniffi/Call.h"
namespace mozilla::uniffi { namespace mozilla::uniffi {
extern mozilla::LazyLogModule gUniffiLogger; extern mozilla::LazyLogModule gUniffiLogger;
@@ -32,7 +32,8 @@ void UniffiSyncCallHandler::CallSync(
aHandler->MakeRustCall(&callStatus); aHandler->MakeRustCall(&callStatus);
aHandler->mUniffiCallStatusCode = callStatus.code; aHandler->mUniffiCallStatusCode = callStatus.code;
if (callStatus.error_buf.data) { if (callStatus.error_buf.data) {
aHandler->mUniffiCallStatusErrorBuf = OwnedRustBuffer(callStatus.error_buf); aHandler->mUniffiCallStatusErrorBuf =
FfiValueRustBuffer(callStatus.error_buf);
} }
aHandler->ExtractCallResult(aGlobal.Context(), aReturnValue, aError); aHandler->ExtractCallResult(aGlobal.Context(), aReturnValue, aError);
} }
@@ -71,7 +72,7 @@ already_AddRefed<dom::Promise> UniffiSyncCallHandler::CallAsyncWrapper(
handler->mUniffiCallStatusCode = callStatus.code; handler->mUniffiCallStatusCode = callStatus.code;
if (callStatus.error_buf.data) { if (callStatus.error_buf.data) {
handler->mUniffiCallStatusErrorBuf = handler->mUniffiCallStatusErrorBuf =
OwnedRustBuffer(callStatus.error_buf); FfiValueRustBuffer(callStatus.error_buf);
} }
taskPromise->Resolve(std::move(handler), __func__); taskPromise->Resolve(std::move(handler), __func__);
}), }),
@@ -125,13 +126,7 @@ void UniffiCallHandlerBase::ExtractCallResult(
// Rust Err() value. Populate data with the `RustBuffer` containing the // Rust Err() value. Populate data with the `RustBuffer` containing the
// error // error
aDest.mCode = dom::UniFFIScaffoldingCallCode::Error; aDest.mCode = dom::UniFFIScaffoldingCallCode::Error;
mUniffiCallStatusErrorBuf.Lift(aCx, &aDest.mData.Construct(), aError);
JS::Rooted<JSObject*> obj(aCx);
mUniffiCallStatusErrorBuf.IntoArrayBuffer(aCx, &obj, aError);
if (aError.Failed()) {
break;
}
aDest.mData.Construct().SetAsArrayBuffer().Init(obj);
break; break;
} }
@@ -139,13 +134,8 @@ void UniffiCallHandlerBase::ExtractCallResult(
// This indicates a RustError, which should rarely happen in practice. // This indicates a RustError, which should rarely happen in practice.
// The normal case is a Rust panic, but FF sets panic=abort. // The normal case is a Rust panic, but FF sets panic=abort.
aDest.mCode = dom::UniFFIScaffoldingCallCode::Internal_error; aDest.mCode = dom::UniFFIScaffoldingCallCode::Internal_error;
if (mUniffiCallStatusErrorBuf.IsValid()) { if (mUniffiCallStatusErrorBuf.IsSet()) {
JS::Rooted<JSObject*> obj(aCx); mUniffiCallStatusErrorBuf.Lift(aCx, &aDest.mData.Construct(), aError);
mUniffiCallStatusErrorBuf.IntoArrayBuffer(aCx, &obj, aError);
if (aError.Failed()) {
break;
}
aDest.mData.Construct().SetAsArrayBuffer().Init(obj);
} }
break; break;
@@ -283,7 +273,8 @@ void UniffiAsyncCallHandler::Finish(
aHandler->CallCompleteFn(&callStatus); aHandler->CallCompleteFn(&callStatus);
aHandler->mUniffiCallStatusCode = callStatus.code; aHandler->mUniffiCallStatusCode = callStatus.code;
if (callStatus.error_buf.data) { if (callStatus.error_buf.data) {
aHandler->mUniffiCallStatusErrorBuf = OwnedRustBuffer(callStatus.error_buf); aHandler->mUniffiCallStatusErrorBuf =
FfiValueRustBuffer(callStatus.error_buf);
} }
aHandler->ExtractCallResult(aes.cx(), returnValue, error); aHandler->ExtractCallResult(aes.cx(), returnValue, error);
error.WouldReportJSException(); error.WouldReportJSException();

View File

@@ -9,9 +9,10 @@
#include "mozilla/RefPtr.h" #include "mozilla/RefPtr.h"
#include "mozilla/UniquePtr.h" #include "mozilla/UniquePtr.h"
#include "mozilla/dom/OwnedRustBuffer.h"
#include "mozilla/dom/UniFFIRust.h"
#include "mozilla/dom/UniFFIScaffolding.h" #include "mozilla/dom/UniFFIScaffolding.h"
#include "mozilla/uniffi/OwnedRustBuffer.h"
#include "mozilla/uniffi/FfiValue.h"
#include "mozilla/uniffi/Rust.h"
namespace mozilla::uniffi { namespace mozilla::uniffi {
@@ -59,7 +60,7 @@ class UniffiCallHandlerBase {
// Call status from the rust call // Call status from the rust call
int8_t mUniffiCallStatusCode = RUST_CALL_SUCCESS; int8_t mUniffiCallStatusCode = RUST_CALL_SUCCESS;
OwnedRustBuffer mUniffiCallStatusErrorBuf; FfiValueRustBuffer mUniffiCallStatusErrorBuf;
}; };
// Call scaffolding functions for synchronous Rust calls // Call scaffolding functions for synchronous Rust calls

View File

@@ -7,10 +7,10 @@
#include "nsPrintfCString.h" #include "nsPrintfCString.h"
#include "nsString.h" #include "nsString.h"
#include "nsThreadUtils.h" #include "nsThreadUtils.h"
#include "mozilla/dom/OwnedRustBuffer.h" #include "mozilla/uniffi/OwnedRustBuffer.h"
#include "mozilla/dom/RootedDictionary.h" #include "mozilla/dom/RootedDictionary.h"
#include "mozilla/dom/UniFFIBinding.h" #include "mozilla/dom/UniFFIBinding.h"
#include "mozilla/dom/UniFFICallbacks.h" #include "mozilla/uniffi/Callbacks.h"
#include "mozilla/Maybe.h" #include "mozilla/Maybe.h"
#include "mozilla/Logging.h" #include "mozilla/Logging.h"
#include "mozilla/RefPtr.h" #include "mozilla/RefPtr.h"

View File

@@ -9,8 +9,8 @@
#include "mozilla/StaticPtr.h" #include "mozilla/StaticPtr.h"
#include "mozilla/UniquePtr.h" #include "mozilla/UniquePtr.h"
#include "mozilla/dom/UniFFIRust.h"
#include "mozilla/dom/UniFFIScaffolding.h" #include "mozilla/dom/UniFFIScaffolding.h"
#include "mozilla/uniffi/Rust.h"
namespace mozilla::uniffi { namespace mozilla::uniffi {

View File

@@ -0,0 +1,160 @@
/* -*- 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_UniFFIFfiConverter_h
#define mozilla_UniFFIFfiConverter_h
#include <limits>
#include <type_traits>
#include "nsString.h"
#include "mozilla/ResultVariant.h"
#include "mozilla/dom/PrimitiveConversions.h"
#include "mozilla/dom/TypedArray.h"
#include "mozilla/dom/UniFFIBinding.h"
#include "mozilla/dom/UniFFIPointer.h"
#include "mozilla/dom/UniFFIScaffolding.h"
#include "mozilla/uniffi/OwnedRustBuffer.h"
#include "mozilla/uniffi/PointerType.h"
#include "mozilla/uniffi/Rust.h"
namespace mozilla::uniffi {
// This header defines the `FfiValue*` classes, which handle conversions between
// FFI values and the JS `OwningUniFFIScaffoldingValue` class.
//
// The exact signatures vary slightly, but in all FfiValue classes define these
// functions:
// - `Lower` -- Convert a `OwningUniFFIScaffoldingValue` into an `FfiValue`.
// - `Lift` -- Convert a `FfiValue` into a `OwningUniFFIScaffoldingValue`.
// - `IntoRust` -- Convert a `FfiValue` into a raw FFI type to pass to Rust
// - `FromRust` -- Convert a raw FFI type from Rust into a `FfiValue`
//
// Also, each `FfiValue` class defines a default constructor.
// For types that hold resources like `FfiValueRustBuffer`, `Lift` and
// `IntoRust` move resources out of the value, leaving behind the default.
// FfiValue class for integer values
template <typename T>
class FfiValueInt {
private:
T mValue = 0;
public:
FfiValueInt() = default;
explicit FfiValueInt(T aValue) : mValue(aValue) {}
void Lower(const dom::OwningUniFFIScaffoldingValue& aValue,
ErrorResult& aError) {
if (!aValue.IsDouble()) {
aError.ThrowTypeError("Bad argument type"_ns);
return;
}
double floatValue = aValue.GetAsDouble();
// Use PrimitiveConversionTraits_Limits rather than std::numeric_limits,
// since it handles JS-specific bounds like the 64-bit integer limits.
// (see Number.MAX_SAFE_INTEGER and Number.MIN_SAFE_INTEGER)
if (floatValue < dom::PrimitiveConversionTraits_Limits<T>::min() ||
floatValue > dom::PrimitiveConversionTraits_Limits<T>::max()) {
aError.ThrowRangeError("Integer value is out of range"_ns);
return;
}
T intValue = static_cast<T>(floatValue);
if (intValue != floatValue) {
aError.ThrowTypeError("Not an integer"_ns);
return;
}
mValue = intValue;
}
void Lift(JSContext* aContext, dom::OwningUniFFIScaffoldingValue* aDest,
ErrorResult& aError) {
if (mValue < dom::PrimitiveConversionTraits_Limits<T>::min() ||
mValue > dom::PrimitiveConversionTraits_Limits<T>::max()) {
aError.ThrowRangeError(
"64-bit value cannot be precisely represented in JS"_ns);
return;
}
aDest->SetAsDouble() = mValue;
}
T IntoRust() { return mValue; }
static FfiValueInt FromRust(T aValue) { return FfiValueInt(aValue); };
};
// FfiValue class for floating point values
template <typename T>
class FfiValueFloat {
private:
T mValue = 0.0;
public:
FfiValueFloat() = default;
explicit FfiValueFloat(T aValue) : mValue(aValue) {}
void Lower(const dom::OwningUniFFIScaffoldingValue& aValue,
ErrorResult& aError) {
if (!aValue.IsDouble()) {
aError.ThrowTypeError("Bad argument type"_ns);
return;
}
mValue = aValue.GetAsDouble();
}
void Lift(JSContext* aContext, dom::OwningUniFFIScaffoldingValue* aDest,
ErrorResult& aError) {
aDest->SetAsDouble() = mValue;
}
T IntoRust() { return mValue; }
static FfiValueFloat FromRust(T aValue) { return FfiValueFloat(aValue); }
};
class FfiValueRustBuffer {
private:
OwnedRustBuffer mValue;
public:
FfiValueRustBuffer() = default;
explicit FfiValueRustBuffer(RustBuffer aValue)
: mValue(OwnedRustBuffer(aValue)) {}
explicit FfiValueRustBuffer(OwnedRustBuffer aValue)
: mValue(std::move(aValue)) {}
void Lower(const dom::OwningUniFFIScaffoldingValue& aValue,
ErrorResult& aError) {
if (!aValue.IsArrayBuffer()) {
aError.ThrowTypeError("Expected ArrayBuffer argument"_ns);
return;
}
mValue = OwnedRustBuffer::FromArrayBuffer(aValue.GetAsArrayBuffer());
}
void Lift(JSContext* aContext, dom::OwningUniFFIScaffoldingValue* aDest,
ErrorResult& aError) {
JS::Rooted<JSObject*> obj(aContext);
mValue.IntoArrayBuffer(aContext, &obj, aError);
if (aError.Failed()) {
return;
}
aDest->SetAsArrayBuffer().Init(obj);
}
RustBuffer IntoRust() { return mValue.IntoRustBuffer(); }
static FfiValueRustBuffer FromRust(RustBuffer aValue) {
return FfiValueRustBuffer(OwnedRustBuffer(aValue));
}
bool IsSet() { return mValue.IsValid(); }
};
} // namespace mozilla::uniffi
#endif // mozilla_UniFFIFfiConverter_h

View File

@@ -5,7 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsString.h" #include "nsString.h"
#include "mozilla/dom/OwnedRustBuffer.h" #include "mozilla/uniffi/OwnedRustBuffer.h"
namespace mozilla::uniffi { namespace mozilla::uniffi {

View File

@@ -9,7 +9,7 @@
#include "mozilla/ErrorResult.h" #include "mozilla/ErrorResult.h"
#include "mozilla/dom/TypedArray.h" #include "mozilla/dom/TypedArray.h"
#include "mozilla/dom/UniFFIRust.h" #include "mozilla/uniffi/Rust.h"
namespace mozilla::uniffi { namespace mozilla::uniffi {

View File

@@ -10,7 +10,7 @@
#include "nsISupports.h" #include "nsISupports.h"
#include "nsWrapperCache.h" #include "nsWrapperCache.h"
#include "nsLiteralString.h" #include "nsLiteralString.h"
#include "UniFFIRust.h" #include "mozilla/uniffi/Rust.h"
namespace mozilla::uniffi { namespace mozilla::uniffi {

View File

@@ -10,8 +10,7 @@ This directory contains C++ helper code for the UniFFI Rust library
- UniFFIScaffolding.cpp is a facade that wraps UniFFIFixtureScaffolding, and - UniFFIScaffolding.cpp is a facade that wraps UniFFIFixtureScaffolding, and
UniFFIGeneratedScaffolding if enabled, to implement the interface. UniFFIGeneratedScaffolding if enabled, to implement the interface.
- `ScaffoldingConverter.h` contain helper code to convert values between JS and Rust. This is used - `UniFFIFfiConverter.h` Lifts/Lowers JS values into FFI values.
by the generated code to make scaffolding calls.
- `OwnedRustBuffer.*` implements a C++ class to help manager ownership of a RustBuffer. - `OwnedRustBuffer.*` implements a C++ class to help manager ownership of a RustBuffer.

View File

@@ -1,211 +0,0 @@
/* -*- 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_ScaffoldingConverter_h
#define mozilla_ScaffoldingConverter_h
#include <limits>
#include <type_traits>
#include "nsString.h"
#include "mozilla/ResultVariant.h"
#include "mozilla/dom/OwnedRustBuffer.h"
#include "mozilla/dom/PrimitiveConversions.h"
#include "mozilla/dom/TypedArray.h"
#include "mozilla/dom/UniFFIBinding.h"
#include "mozilla/dom/UniFFIPointer.h"
#include "mozilla/dom/UniFFIPointerType.h"
#include "mozilla/dom/UniFFIRust.h"
#include "mozilla/dom/UniFFIScaffolding.h"
namespace mozilla::uniffi {
// Handle converting types between JS and Rust
//
// Scaffolding conversions are done using a 2 step process:
// - Call FromJs/FromRust to convert to an intermediate type
// - Call IntoJs/IntoRust to convert from that type to the target type
//
// The main reason for this is handling RustBuffers when other arguments fail
// to convert. By using OwnedRustBuffer as the intermediate type, we can
// ensure those buffers get freed in that case. Note that we can't use
// OwnedRustBuffer as the Rust type. Passing the buffer into Rust transfers
// ownership so we shouldn't free the buffer in this case.
//
// For most other types, we just use the Rust type as the intermediate type.
template <typename T>
class ScaffoldingConverter {
public:
using RustType = T;
using IntermediateType = T;
// Convert a JS value to an intermedate type
//
// This inputs a const ref, because that's what the WebIDL bindings send to
// us.
//
// If this succeeds then IntoRust is also guaranteed to succeed
static void FromJs(const dom::OwningUniFFIScaffoldingValue& aValue,
IntermediateType* aResult, ErrorResult& aError) {
if (!aValue.IsDouble()) {
aError.ThrowTypeError("Bad argument type"_ns);
return;
}
double value = aValue.GetAsDouble();
if (std::isnan(value)) {
aError.ThrowUnknownError("NaN not allowed"_ns);
return;
}
if constexpr (std::is_integral<RustType>::value) {
// Use PrimitiveConversionTraits_Limits rather than std::numeric_limits,
// since it handles JS-specific bounds like the 64-bit integer limits.
// (see Number.MAX_SAFE_INTEGER and Number.MIN_SAFE_INTEGER)
if (value < dom::PrimitiveConversionTraits_Limits<RustType>::min() ||
value > dom::PrimitiveConversionTraits_Limits<RustType>::max()) {
aError.ThrowRangeError(
"UniFFI return value cannot be precisely represented in JS"_ns);
return;
}
}
// Don't check float bounds for a few reasons.
// - It's difficult because
// PrimitiveConversionTraits_Limits<float>::min() is the smallest
// positive value, rather than the most negative.
// - A float value unlikely to overflow
// - It's also likely that we can't do an exact conversion because the
// float doesn't have enough precision, but it doesn't seem correct
// to error out in that case.
IntermediateType rv = static_cast<IntermediateType>(value);
if constexpr (std::is_integral<IntermediateType>::value) {
if (rv != value) {
aError.ThrowTypeError("Not an integer"_ns);
return;
}
}
*aResult = rv;
}
// Convert an intermediate type to a Rust type
//
// IntoRust doesn't touch the JS data, so it's safe to call in a worker thread
static RustType IntoRust(IntermediateType aValue) { return aValue; }
// Convert an Rust type to an intermediate type
//
// This inputs a value since Rust types are POD types
static IntermediateType FromRust(RustType aValue) { return aValue; }
// Convert an intermedate type to a JS type
//
// This inputs an r-value reference since we may want to move data out of
// this type.
static void IntoJs(JSContext* aContext, IntermediateType&& aValue,
dom::OwningUniFFIScaffoldingValue* aDest,
ErrorResult& aError) {
if constexpr (std::is_same<RustType, int64_t>::value ||
std::is_same<RustType, uint64_t>::value) {
// Check that the value can fit in a double (only needed for 64 bit types)
if (aValue < dom::PrimitiveConversionTraits_Limits<RustType>::min() ||
aValue > dom::PrimitiveConversionTraits_Limits<RustType>::max()) {
aError.ThrowRangeError(
"UniFFI return value cannot be precisely represented in JS"_ns);
return;
}
}
if constexpr (std::is_floating_point<RustType>::value) {
if (std::isnan(aValue)) {
aError.ThrowUnknownError("NaN not allowed"_ns);
return;
}
}
aDest->SetAsDouble() = aValue;
}
};
template <>
class ScaffoldingConverter<RustBuffer> {
public:
using RustType = RustBuffer;
using IntermediateType = OwnedRustBuffer;
static void FromJs(const dom::OwningUniFFIScaffoldingValue& aValue,
OwnedRustBuffer* aResult, ErrorResult& aError) {
if (!aValue.IsArrayBuffer()) {
aError.ThrowTypeError("Expected ArrayBuffer argument"_ns);
return;
}
*aResult = OwnedRustBuffer::FromArrayBuffer(aValue.GetAsArrayBuffer());
}
static RustBuffer IntoRust(OwnedRustBuffer&& aValue) {
return aValue.IntoRustBuffer();
}
static OwnedRustBuffer FromRust(RustBuffer aValue) {
return OwnedRustBuffer(aValue);
}
static void IntoJs(JSContext* aContext, OwnedRustBuffer&& aValue,
dom::OwningUniFFIScaffoldingValue* aDest,
ErrorResult& aError) {
JS::Rooted<JSObject*> obj(aContext);
aValue.IntoArrayBuffer(aContext, &obj, aError);
if (aError.Failed()) {
return;
}
aDest->SetAsArrayBuffer().Init(obj);
}
};
// ScaffoldingConverter for object pointers
template <const UniFFIPointerType* PointerType>
class ScaffoldingObjectConverter {
public:
using RustType = void*;
using IntermediateType = void*;
static void FromJs(const dom::OwningUniFFIScaffoldingValue& aValue,
void** aResult, ErrorResult& aError) {
if (!aValue.IsUniFFIPointer()) {
aError.ThrowTypeError("Expected UniFFI pointer argument"_ns);
return;
}
dom::UniFFIPointer& value = aValue.GetAsUniFFIPointer();
if (!value.IsSamePtrType(PointerType)) {
aError.ThrowTypeError("Incorrect UniFFI pointer type"_ns);
return;
}
*aResult = value.ClonePtr();
}
static void* IntoRust(void* aValue) { return aValue; }
static void* FromRust(void* aValue) { return aValue; }
static void IntoJs(JSContext* aContext, void* aValue,
dom::OwningUniFFIScaffoldingValue* aDest,
ErrorResult& aError) {
aDest->SetAsUniFFIPointer() =
dom::UniFFIPointer::Create(aValue, PointerType);
}
};
// ScaffoldingConverter for void returns
//
// This doesn't implement the normal interface, it's only use is a the
// ReturnConverter parameter of ScaffoldingCallHandler.
template <>
class ScaffoldingConverter<void> {
public:
using RustType = void;
};
} // namespace mozilla::uniffi
#endif // mozilla_ScaffoldingConverter_h

View File

@@ -7,10 +7,10 @@
#include "nsPrintfCString.h" #include "nsPrintfCString.h"
#include "js/GCAPI.h" #include "js/GCAPI.h"
#include "mozilla/EndianUtils.h" #include "mozilla/EndianUtils.h"
#include "mozilla/Logging.h"
#include "mozilla/dom/UniFFIPointer.h" #include "mozilla/dom/UniFFIPointer.h"
#include "mozilla/dom/UniFFIBinding.h" #include "mozilla/dom/UniFFIBinding.h"
#include "mozilla/Logging.h" #include "mozilla/uniffi/Rust.h"
#include "UniFFIRust.h"
namespace mozilla::uniffi { namespace mozilla::uniffi {
extern mozilla::LazyLogModule gUniffiLogger; extern mozilla::LazyLogModule gUniffiLogger;

View File

@@ -12,7 +12,7 @@
#include "nsString.h" #include "nsString.h"
#include "mozilla/ErrorResult.h" #include "mozilla/ErrorResult.h"
#include "mozilla/dom/TypedArray.h" #include "mozilla/dom/TypedArray.h"
#include "mozilla/dom/UniFFIPointerType.h" #include "mozilla/uniffi/PointerType.h"
namespace mozilla::dom { namespace mozilla::dom {

View File

@@ -12,14 +12,14 @@
#include "mozilla/Maybe.h" #include "mozilla/Maybe.h"
#include "mozilla/UniquePtr.h" #include "mozilla/UniquePtr.h"
#include "mozilla/dom/Promise.h" #include "mozilla/dom/Promise.h"
#include "mozilla/dom/UniFFICall.h" #include "mozilla/uniffi/Call.h"
#include "mozilla/dom/UniFFICallbacks.h" #include "mozilla/uniffi/Callbacks.h"
#include "mozilla/dom/UniFFIScaffolding.h" #include "mozilla/dom/UniFFIScaffolding.h"
// This file implements the UniFFI WebIDL interface by leveraging the generate // This file implements the UniFFI WebIDL interface by leveraging the generate
// code in UniFFIScaffolding.cpp and UniFFIFixtureScaffolding.cpp. It's main // code in UniFFIScaffolding.cpp. It's main purpose is to check if
// purpose is to check if MOZ_UNIFFI_FIXTURES is set and only try calling the // MOZ_UNIFFI_FIXTURES is set and only try calling the scaffolding code if it
// scaffolding code if it is. // is.
using mozilla::dom::ArrayBuffer; using mozilla::dom::ArrayBuffer;
using mozilla::dom::GlobalObject; using mozilla::dom::GlobalObject;
@@ -35,7 +35,7 @@ using mozilla::uniffi::UniffiSyncCallHandler;
namespace mozilla::uniffi { namespace mozilla::uniffi {
mozilla::LazyLogModule gUniffiLogger("uniffi"); mozilla::LazyLogModule gUniffiLogger("uniffi");
// Implemented in UniFFIGeneratedScaffolding.cpp // Implemented in GeneratedScaffolding.cpp
UniquePtr<UniffiSyncCallHandler> GetSyncCallHandler(uint64_t aId); UniquePtr<UniffiSyncCallHandler> GetSyncCallHandler(uint64_t aId);
UniquePtr<UniffiAsyncCallHandler> GetAsyncCallHandler(uint64_t aId); UniquePtr<UniffiAsyncCallHandler> GetAsyncCallHandler(uint64_t aId);
Maybe<already_AddRefed<UniFFIPointer>> ReadPointer( Maybe<already_AddRefed<UniFFIPointer>> ReadPointer(

View File

@@ -7,10 +7,10 @@
FINAL_LIBRARY = "xul" FINAL_LIBRARY = "xul"
UNIFIED_SOURCES += [ UNIFIED_SOURCES += [
"Call.cpp",
"Callbacks.cpp",
"GeneratedScaffolding.cpp",
"OwnedRustBuffer.cpp", "OwnedRustBuffer.cpp",
"UniFFICall.cpp",
"UniFFICallbacks.cpp",
"UniFFIGeneratedScaffolding.cpp",
"UniFFIPointer.cpp", "UniFFIPointer.cpp",
"UniFFIScaffolding.cpp", "UniFFIScaffolding.cpp",
] ]
@@ -19,16 +19,19 @@ if CONFIG["MOZ_UNIFFI_FIXTURES"]:
DEFINES["MOZ_UNIFFI_FIXTURES"] = True DEFINES["MOZ_UNIFFI_FIXTURES"] = True
EXPORTS.mozilla.dom += [ EXPORTS.mozilla.dom += [
"OwnedRustBuffer.h",
"ScaffoldingConverter.h",
"UniFFICall.h",
"UniFFICallbacks.h",
"UniFFIPointer.h", "UniFFIPointer.h",
"UniFFIPointerType.h",
"UniFFIRust.h",
"UniFFIScaffolding.h", "UniFFIScaffolding.h",
] ]
EXPORTS.mozilla.uniffi += [
"Call.h",
"Callbacks.h",
"FfiValue.h",
"OwnedRustBuffer.h",
"PointerType.h",
"Rust.h",
]
EXTRA_JS_MODULES += [ EXTRA_JS_MODULES += [
"js/UniFFI.sys.mjs", "js/UniFFI.sys.mjs",
] ]

View File

@@ -215,8 +215,7 @@ toolkit/components/nimbus/schemas/ExperimentFeatureManifest.schema.json
toolkit/components/nimbus/schemas/NimbusExperiment.schema.json toolkit/components/nimbus/schemas/NimbusExperiment.schema.json
toolkit/components/pdfjs/PdfJsDefaultPrefs.js toolkit/components/pdfjs/PdfJsDefaultPrefs.js
toolkit/components/pdfjs/PdfJsOverridePrefs.js toolkit/components/pdfjs/PdfJsOverridePrefs.js
toolkit/components/uniffi-js/UniFFIGeneratedScaffolding.cpp toolkit/components/uniffi-js/GeneratedScaffolding.cpp
toolkit/components/uniffi-js/UniFFIFixtureScaffolding.cpp
toolkit/components/uniffi-bindgen-gecko-js/fixtures/generated toolkit/components/uniffi-bindgen-gecko-js/fixtures/generated
tools/@types/tspaths.json tools/@types/tspaths.json
tools/browsertime/package.json tools/browsertime/package.json