Backed out 2 changesets (bug 1951243, bug 1951241) for causing bustages on GeneratedScaffolding.cpp . CLOSED TREE
Backed out changeset 944bac64c3db (bug 1951243) Backed out changeset c79b66ed7283 (bug 1951241)
This commit is contained in:
@@ -69,7 +69,8 @@ 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/GeneratedScaffolding.cpp
|
toolkit/components/uniffi-js/UniFFIGeneratedScaffolding.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
|
||||||
|
|||||||
@@ -1563,7 +1563,8 @@ 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/GeneratedScaffolding.cpp
|
toolkit/components/uniffi-js/UniFFIGeneratedScaffolding.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
1
Cargo.lock
generated
@@ -2524,7 +2524,6 @@ 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",
|
||||||
|
|||||||
@@ -22,8 +22,6 @@ 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?
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import subprocess
|
|||||||
|
|
||||||
from mach.decorators import Command, SubCommand
|
from mach.decorators import Command, SubCommand
|
||||||
|
|
||||||
CPP_PATH = "toolkit/components/uniffi-js/GeneratedScaffolding.cpp"
|
CPP_PATH = "toolkit/components/uniffi-js/UniFFIGeneratedScaffolding.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/"
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ impl CPPScaffoldingTemplate {
|
|||||||
arg_types: ffi_func
|
arg_types: ffi_func
|
||||||
.arguments()
|
.arguments()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|a| ffi_type_name(&a.type_()))
|
.map(|a| cpp_type(&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| ffi_type_name(&a.type_()))
|
.map(|a| cpp_type(&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_: ffi_type_name(&f.type_()),
|
type_: cpp_type(&f.type_()),
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
}),
|
}),
|
||||||
@@ -182,7 +182,7 @@ impl CPPScaffoldingTemplate {
|
|||||||
let cbi_name_snake = cbi.name().to_snake_case();
|
let cbi_name_snake = cbi.name().to_snake_case();
|
||||||
|
|
||||||
CallbackInterfaceVTable {
|
CallbackInterfaceVTable {
|
||||||
type_: ffi_type_name(&cbi.vtable()),
|
type_: cpp_type(&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 +196,13 @@ impl CPPScaffoldingTemplate {
|
|||||||
arguments: method
|
arguments: method
|
||||||
.arguments()
|
.arguments()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|arg| {
|
.map(|arg| CallbackMethodArgument {
|
||||||
let ffi_type = arg.as_type().into();
|
name: arg.name().to_snake_case(),
|
||||||
CallbackMethodArgument {
|
type_: cpp_type(&arg.as_type().into()),
|
||||||
name: arg.name().to_snake_case(),
|
scaffolding_converter: scaffolding_converter(
|
||||||
ffi_type: ffi_type_name(&ffi_type),
|
ci,
|
||||||
ffi_value_class: ffi_value_class(ci, &ffi_type),
|
&arg.as_type().into(),
|
||||||
}
|
),
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
}
|
}
|
||||||
@@ -337,8 +337,8 @@ struct CallbackMethodHandler {
|
|||||||
|
|
||||||
struct CallbackMethodArgument {
|
struct CallbackMethodArgument {
|
||||||
name: String,
|
name: String,
|
||||||
ffi_type: String,
|
type_: String,
|
||||||
ffi_value_class: String,
|
scaffolding_converter: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ScaffoldingCall {
|
struct ScaffoldingCall {
|
||||||
@@ -366,7 +366,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()),
|
||||||
ffi_value_class: ffi_value_class(ci, &a.type_()),
|
scaffolding_converter: scaffolding_converter(ci, &a.type_()),
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
@@ -384,9 +384,8 @@ 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 {
|
||||||
ffi_value_class: ffi_value_class(ci, &return_type),
|
scaffolding_converter: scaffolding_converter(ci, &return_type.into()),
|
||||||
}),
|
}),
|
||||||
arguments,
|
arguments,
|
||||||
async_info,
|
async_info,
|
||||||
@@ -399,12 +398,12 @@ impl ScaffoldingCall {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct ScaffoldingCallReturnType {
|
struct ScaffoldingCallReturnType {
|
||||||
ffi_value_class: String,
|
scaffolding_converter: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ScaffoldingCallArgument {
|
struct ScaffoldingCallArgument {
|
||||||
var_name: String,
|
var_name: String,
|
||||||
ffi_value_class: String,
|
scaffolding_converter: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ScaffoldingCallAsyncInfo {
|
struct ScaffoldingCallAsyncInfo {
|
||||||
@@ -413,7 +412,7 @@ struct ScaffoldingCallAsyncInfo {
|
|||||||
free_fn: String,
|
free_fn: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ffi_value_class(ci: &ComponentInterface, ffi_type: &FfiType) -> String {
|
fn scaffolding_converter(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
|
||||||
@@ -422,29 +421,17 @@ fn ffi_value_class(ci: &ComponentInterface, ffi_type: &FfiType) -> String {
|
|||||||
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 format!(
|
||||||
"FfiValueObjectHandle<&{}>",
|
"ScaffoldingObjectConverter<&{}>",
|
||||||
pointer_type(crate_name_to_namespace(&crate_name), name),
|
pointer_type(crate_name_to_namespace(&crate_name), name),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
format!(
|
format!(
|
||||||
"FfiValueObjectHandle<&{}>",
|
"ScaffoldingObjectConverter<&{}>",
|
||||||
pointer_type(ci.namespace(), name),
|
pointer_type(ci.namespace(), name),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
FfiType::UInt8
|
_ => format!("ScaffoldingConverter<{}>", cpp_type(ffi_type)),
|
||||||
| 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)),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -456,8 +443,8 @@ fn pointer_type(namespace: &str, name: &str) -> String {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// C++ type for an FFI value
|
// Type for the Rust scaffolding code
|
||||||
fn ffi_type_name(ffi_type: &FfiType) -> String {
|
fn cpp_type(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(),
|
||||||
@@ -477,14 +464,14 @@ fn ffi_type_name(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!("{}*", ffi_type_name(inner.as_ref()))
|
format!("{}*", cpp_type(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) => ffi_type_name(t),
|
Some(t) => cpp_type(t),
|
||||||
None => "void".to_owned(),
|
None => "void".to_owned(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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/dom/UniFFICall.h"
|
||||||
|
#include "mozilla/dom/UniFFICallbacks.h"
|
||||||
|
#include "mozilla/dom/UniFFIPointerType.h"
|
||||||
#include "mozilla/dom/UniFFIScaffolding.h"
|
#include "mozilla/dom/UniFFIScaffolding.h"
|
||||||
#include "mozilla/uniffi/Call.h"
|
#include "mozilla/dom/UniFFIRust.h"
|
||||||
#include "mozilla/uniffi/Callbacks.h"
|
|
||||||
#include "mozilla/uniffi/FfiValue.h"
|
|
||||||
#include "mozilla/uniffi/PointerType.h"
|
|
||||||
#include "mozilla/uniffi/Rust.h"
|
|
||||||
|
|
||||||
namespace mozilla::uniffi {
|
namespace mozilla::uniffi {
|
||||||
|
|
||||||
@@ -78,15 +78,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
|
// Rust arguments, converted using ScaffoldingConverter::FromRust.
|
||||||
{%- for a in handler.arguments %}
|
{%- for a in handler.arguments %}
|
||||||
{{ a.ffi_value_class }} {{ a.name }}{};
|
typename {{ a.scaffolding_converter }}::IntermediateType {{ a.name }};
|
||||||
{%- endfor %}
|
{%- endfor %}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
{{ handler.class_name }}(size_t aObjectHandle{%- for a in handler.arguments %}, {{ a.ffi_type }} {{ a.name }}{%- endfor %})
|
{{ handler.class_name }}(size_t aObjectHandle{%- for a in handler.arguments %}, {{ a.type_ }} {{ a.name }}{%- endfor %})
|
||||||
: UniffiCallbackMethodHandlerBase("{{ cbi.name }}", aObjectHandle)
|
: UniffiCallbackMethodHandlerBase("{{ cbi.name }}", aObjectHandle)
|
||||||
{%- for a in handler.arguments %}, {{ a.name }}({{ a.ffi_value_class }}::FromRust({{ a.name }})){% endfor %} {
|
{%- for a in handler.arguments %}, {{ a.name }}({{ a.scaffolding_converter }}::FromRust({{ a.name }})){% endfor %} {
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_CAN_RUN_SCRIPT
|
MOZ_CAN_RUN_SCRIPT
|
||||||
@@ -102,8 +102,9 @@ public:
|
|||||||
|
|
||||||
// Convert each argument
|
// Convert each argument
|
||||||
{%- for a in handler.arguments %}
|
{%- for a in handler.arguments %}
|
||||||
{{ a.name }}.Lift(
|
{{ a.scaffolding_converter }}::IntoJs(
|
||||||
aCx,
|
aCx,
|
||||||
|
std::move(this->{{ a.name }}),
|
||||||
&uniffiArgs[{{ loop.index0 }}],
|
&uniffiArgs[{{ loop.index0 }}],
|
||||||
aError);
|
aError);
|
||||||
if (aError.Failed()) {
|
if (aError.Failed()) {
|
||||||
@@ -122,7 +123,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.ffi_type }} {{ a.name }}, {% endfor %}
|
{% for a in handler.arguments %}{{ a.type_ }} {{ a.name }}, {% endfor %}
|
||||||
void* uniffiOutReturn,
|
void* uniffiOutReturn,
|
||||||
RustCallStatus* uniffiCallStatus
|
RustCallStatus* uniffiCallStatus
|
||||||
) {
|
) {
|
||||||
@@ -220,22 +221,22 @@ void DeregisterCallbackHandler(uint64_t aInterfaceId, ErrorResult& aError) {
|
|||||||
{%- when None %}
|
{%- when None %}
|
||||||
class {{ scaffolding_call.handler_class_name }} : public UniffiSyncCallHandler {
|
class {{ scaffolding_call.handler_class_name }} : public UniffiSyncCallHandler {
|
||||||
private:
|
private:
|
||||||
// LowerRustArgs 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 %}
|
||||||
{{ arg.ffi_value_class }} {{ arg.var_name }}{};
|
typename {{ arg.scaffolding_converter }}::IntermediateType {{ 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) %}
|
||||||
{{ return_type.ffi_value_class }} mUniffiReturnValue{};
|
typename {{ return_type.scaffolding_converter }}::IntermediateType mUniffiReturnValue;
|
||||||
{%- else %}
|
{%- else %}
|
||||||
{%- endmatch %}
|
{%- endmatch %}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void LowerRustArgs(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.var_name }}.Lower(aArgs[{{ loop.index0 }}], aError);
|
{{ arg.scaffolding_converter }}::FromJs(aArgs[{{ loop.index0 }}], &{{ arg.var_name }}, aError);
|
||||||
if (aError.Failed()) {
|
if (aError.Failed()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -245,10 +246,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.ffi_value_class }}::FromRust(
|
mUniffiReturnValue = {{ return_type.scaffolding_converter }}::FromRust(
|
||||||
{{ scaffolding_call.ffi_func_name }}(
|
{{ scaffolding_call.ffi_func_name }}(
|
||||||
{%- for arg in scaffolding_call.arguments %}
|
{%- for arg in scaffolding_call.arguments %}
|
||||||
{{ arg.var_name }}.IntoRust(),
|
{{ arg.scaffolding_converter }}::IntoRust(std::move({{ arg.var_name }})),
|
||||||
{%- endfor %}
|
{%- endfor %}
|
||||||
aOutStatus
|
aOutStatus
|
||||||
)
|
)
|
||||||
@@ -256,18 +257,19 @@ 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.var_name }}.IntoRust(),
|
{{ arg.scaffolding_converter }}::IntoRust(std::move({{ arg.var_name }})),
|
||||||
{%- endfor %}
|
{%- endfor %}
|
||||||
aOutStatus
|
aOutStatus
|
||||||
);
|
);
|
||||||
{%- endmatch %}
|
{%- endmatch %}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void LiftSuccessfulCallResult(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) %}
|
||||||
mUniffiReturnValue.Lift(
|
{{ return_type.scaffolding_converter }}::IntoJs(
|
||||||
aCx,
|
aCx,
|
||||||
|
std::move(mUniffiReturnValue),
|
||||||
&aDest.Construct(),
|
&aDest.Construct(),
|
||||||
aError
|
aError
|
||||||
);
|
);
|
||||||
@@ -284,7 +286,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) %}
|
||||||
{{ return_type.ffi_value_class }} mUniffiReturnValue{};
|
typename {{ return_type.scaffolding_converter }}::IntermediateType mUniffiReturnValue;
|
||||||
{%- else %}
|
{%- else %}
|
||||||
{%- endmatch %}
|
{%- endmatch %}
|
||||||
|
|
||||||
@@ -292,10 +294,10 @@ protected:
|
|||||||
// Convert a sequence of JS arguments and call the scaffolding function.
|
// Convert a sequence of JS arguments and call the scaffolding function.
|
||||||
// Always called on the main thread since async Rust calls don't block, they
|
// Always called on the main thread since async Rust calls don't block, they
|
||||||
// return a future.
|
// return a future.
|
||||||
void LowerArgsAndMakeRustCall(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 %}
|
||||||
{{ arg.ffi_value_class }} {{ arg.var_name }}{};
|
typename {{ arg.scaffolding_converter }}::IntermediateType {{ arg.var_name }};
|
||||||
{{ arg.var_name }}.Lower(aArgs[{{ loop.index0 }}], aError);
|
{{ arg.scaffolding_converter }}::FromJs(aArgs[{{ loop.index0 }}], &{{ arg.var_name }}, aError);
|
||||||
if (aError.Failed()) {
|
if (aError.Failed()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -303,7 +305,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.var_name }}.IntoRust(){% if !loop.last %},{% endif %}
|
{{ arg.scaffolding_converter }}::IntoRust(std::move({{ arg.var_name }})){% if !loop.last %},{% endif %}
|
||||||
{%- endfor %}
|
{%- endfor %}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -311,7 +313,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.ffi_value_class }}::FromRust(
|
mUniffiReturnValue = {{ return_type.scaffolding_converter }}::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);
|
||||||
@@ -319,11 +321,12 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void LiftSuccessfulCallResult(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) %}
|
||||||
mUniffiReturnValue.Lift(
|
{{ return_type.scaffolding_converter }}::IntoJs(
|
||||||
aCx,
|
aCx,
|
||||||
|
std::move(mUniffiReturnValue),
|
||||||
&aDest.Construct(),
|
&aDest.Construct(),
|
||||||
aError
|
aError
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,226 +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/. */
|
|
||||||
|
|
||||||
#include "nsThreadUtils.h"
|
|
||||||
#include "mozilla/dom/Promise.h"
|
|
||||||
#include "mozilla/dom/RootedDictionary.h"
|
|
||||||
#include "mozilla/uniffi/Call.h"
|
|
||||||
#include "mozilla/uniffi/ResultPromise.h"
|
|
||||||
|
|
||||||
namespace mozilla::uniffi {
|
|
||||||
extern mozilla::LazyLogModule gUniffiLogger;
|
|
||||||
|
|
||||||
using dom::GlobalObject;
|
|
||||||
using dom::OwningUniFFIScaffoldingValue;
|
|
||||||
using dom::RootedDictionary;
|
|
||||||
using dom::Sequence;
|
|
||||||
using dom::UniFFIScaffoldingCallResult;
|
|
||||||
|
|
||||||
void UniffiSyncCallHandler::CallSync(
|
|
||||||
UniquePtr<UniffiSyncCallHandler> aHandler, const GlobalObject& aGlobal,
|
|
||||||
const Sequence<OwningUniFFIScaffoldingValue>& aArgs,
|
|
||||||
RootedDictionary<UniFFIScaffoldingCallResult>& aReturnValue,
|
|
||||||
ErrorResult& aError) {
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
aHandler->LowerRustArgs(aArgs, aError);
|
|
||||||
if (aError.Failed()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
RustCallStatus callStatus{};
|
|
||||||
aHandler->MakeRustCall(&callStatus);
|
|
||||||
aHandler->mUniffiCallStatusCode = callStatus.code;
|
|
||||||
if (callStatus.error_buf.data) {
|
|
||||||
aHandler->mUniffiCallStatusErrorBuf =
|
|
||||||
FfiValueRustBuffer(callStatus.error_buf);
|
|
||||||
}
|
|
||||||
aHandler->LiftCallResult(aGlobal.Context(), aReturnValue, aError);
|
|
||||||
}
|
|
||||||
|
|
||||||
already_AddRefed<dom::Promise> UniffiSyncCallHandler::CallAsyncWrapper(
|
|
||||||
UniquePtr<UniffiSyncCallHandler> aHandler, const dom::GlobalObject& aGlobal,
|
|
||||||
const dom::Sequence<dom::OwningUniFFIScaffoldingValue>& aArgs,
|
|
||||||
ErrorResult& aError) {
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
aHandler->LowerRustArgs(aArgs, aError);
|
|
||||||
if (aError.Failed()) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
uniffi::ResultPromise resultPromise;
|
|
||||||
resultPromise.Init(aGlobal, aError);
|
|
||||||
if (aError.Failed()) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult dispatchResult = NS_DispatchBackgroundTask(
|
|
||||||
NS_NewRunnableFunction("UniffiSyncCallHandler::CallAsyncWrapper",
|
|
||||||
[handler = std::move(aHandler),
|
|
||||||
resultPromise = resultPromise]() mutable {
|
|
||||||
RustCallStatus callStatus{};
|
|
||||||
handler->MakeRustCall(&callStatus);
|
|
||||||
handler->mUniffiCallStatusCode = callStatus.code;
|
|
||||||
if (callStatus.error_buf.data) {
|
|
||||||
handler->mUniffiCallStatusErrorBuf =
|
|
||||||
FfiValueRustBuffer(callStatus.error_buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
resultPromise.Complete(std::move(handler));
|
|
||||||
}),
|
|
||||||
NS_DISPATCH_EVENT_MAY_BLOCK);
|
|
||||||
if (NS_FAILED(dispatchResult)) {
|
|
||||||
MOZ_LOG(gUniffiLogger, LogLevel::Error,
|
|
||||||
("[UniFFI] NS_DispatchBackgroundTask failed"));
|
|
||||||
resultPromise.RejectWithUnexpectedError();
|
|
||||||
}
|
|
||||||
|
|
||||||
return do_AddRef(resultPromise.GetPromise());
|
|
||||||
}
|
|
||||||
|
|
||||||
void UniffiCallHandlerBase::LiftCallResult(
|
|
||||||
JSContext* aCx,
|
|
||||||
dom::RootedDictionary<dom::UniFFIScaffoldingCallResult>& aDest,
|
|
||||||
ErrorResult& aError) {
|
|
||||||
switch (mUniffiCallStatusCode) {
|
|
||||||
case RUST_CALL_SUCCESS: {
|
|
||||||
aDest.mCode = dom::UniFFIScaffoldingCallCode::Success;
|
|
||||||
LiftSuccessfulCallResult(aCx, aDest.mData, aError);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case RUST_CALL_ERROR: {
|
|
||||||
// Rust Err() value. Populate data with the `RustBuffer` containing the
|
|
||||||
// error
|
|
||||||
aDest.mCode = dom::UniFFIScaffoldingCallCode::Error;
|
|
||||||
mUniffiCallStatusErrorBuf.Lift(aCx, &aDest.mData.Construct(), aError);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default: {
|
|
||||||
// This indicates a RustError, which should rarely happen in practice.
|
|
||||||
// The normal case is a Rust panic, but FF sets panic=abort.
|
|
||||||
aDest.mCode = dom::UniFFIScaffoldingCallCode::Internal_error;
|
|
||||||
if (mUniffiCallStatusErrorBuf.IsSet()) {
|
|
||||||
mUniffiCallStatusErrorBuf.Lift(aCx, &aDest.mData.Construct(), aError);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
already_AddRefed<dom::Promise> UniffiAsyncCallHandler::CallAsync(
|
|
||||||
UniquePtr<UniffiAsyncCallHandler> aHandler,
|
|
||||||
const dom::GlobalObject& aGlobal,
|
|
||||||
const dom::Sequence<dom::OwningUniFFIScaffoldingValue>& aArgs,
|
|
||||||
ErrorResult& aError) {
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
// Async calls return a Future rather than doing any work. This means we can
|
|
||||||
// make the call right now on the JS main thread without fear of blocking it.
|
|
||||||
aHandler->LowerArgsAndMakeRustCall(aArgs, aError);
|
|
||||||
if (aError.Failed()) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
aHandler->mPromise.Init(aGlobal, aError);
|
|
||||||
if (aError.Failed()) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
ResultPromise returnPromise(aHandler->mPromise);
|
|
||||||
|
|
||||||
// Schedule a poll for the future in a background thread.
|
|
||||||
nsresult dispatchResult = NS_DispatchBackgroundTask(
|
|
||||||
NS_NewRunnableFunction("UniffiAsyncCallHandler::CallAsync",
|
|
||||||
[handler = std::move(aHandler)]() mutable {
|
|
||||||
UniffiAsyncCallHandler::Poll(std::move(handler));
|
|
||||||
}));
|
|
||||||
if (NS_FAILED(dispatchResult)) {
|
|
||||||
MOZ_LOG(gUniffiLogger, LogLevel::Error,
|
|
||||||
("[UniFFI] NS_DispatchBackgroundTask failed"));
|
|
||||||
aHandler->mPromise.RejectWithUnexpectedError();
|
|
||||||
}
|
|
||||||
|
|
||||||
return do_AddRef(returnPromise.GetPromise());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Callback function for async calls
|
|
||||||
//
|
|
||||||
// This is passed to Rust when we poll the future alongside a 64-bit handle that
|
|
||||||
// represents the callback data. For uniffi-bindgen-gecko-js, the handle is a
|
|
||||||
// `UniffiAsyncCallHandler*` casted to an int.
|
|
||||||
//
|
|
||||||
// Rust calls this when either the future is ready or when it's time to poll it
|
|
||||||
// again.
|
|
||||||
void UniffiAsyncCallHandler::FutureCallback(uint64_t aCallHandlerHandle,
|
|
||||||
int8_t aCode) {
|
|
||||||
// Recreate the UniquePtr we previously released
|
|
||||||
UniquePtr<UniffiAsyncCallHandler> handler(
|
|
||||||
reinterpret_cast<UniffiAsyncCallHandler*>(
|
|
||||||
static_cast<uintptr_t>(aCallHandlerHandle)));
|
|
||||||
|
|
||||||
switch (aCode) {
|
|
||||||
case UNIFFI_FUTURE_READY: {
|
|
||||||
// `Future::poll` returned a `Ready` value on the Rust side.
|
|
||||||
// Complete the future
|
|
||||||
RustCallStatus callStatus{};
|
|
||||||
handler->CallCompleteFn(&callStatus);
|
|
||||||
handler->mUniffiCallStatusCode = callStatus.code;
|
|
||||||
if (callStatus.error_buf.data) {
|
|
||||||
handler->mUniffiCallStatusErrorBuf =
|
|
||||||
FfiValueRustBuffer(callStatus.error_buf);
|
|
||||||
}
|
|
||||||
// Copy of the ResultPromise before moving the handler that contains it.
|
|
||||||
ResultPromise promise(handler->mPromise);
|
|
||||||
promise.Complete(std::move(handler));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case UNIFFI_FUTURE_MAYBE_READY: {
|
|
||||||
// The Rust waker was invoked after `poll` returned a `Pending` value.
|
|
||||||
// Poll the future again soon in a background task.
|
|
||||||
|
|
||||||
nsresult dispatchResult =
|
|
||||||
NS_DispatchBackgroundTask(NS_NewRunnableFunction(
|
|
||||||
"UniffiAsyncCallHandler::FutureCallback",
|
|
||||||
[handler = std::move(handler)]() mutable {
|
|
||||||
UniffiAsyncCallHandler::Poll(std::move(handler));
|
|
||||||
}));
|
|
||||||
if (NS_FAILED(dispatchResult)) {
|
|
||||||
MOZ_LOG(gUniffiLogger, LogLevel::Error,
|
|
||||||
("[UniFFI] NS_DispatchBackgroundTask failed"));
|
|
||||||
handler->mPromise.RejectWithUnexpectedError();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default: {
|
|
||||||
// Invalid poll code, this should never happen, but if it does log an
|
|
||||||
// error and reject the promise.
|
|
||||||
MOZ_LOG(gUniffiLogger, LogLevel::Error,
|
|
||||||
("[UniFFI] Invalid poll code in "
|
|
||||||
"UniffiAsyncCallHandler::FutureCallback %d",
|
|
||||||
aCode));
|
|
||||||
handler->mPromise.RejectWithUnexpectedError();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
void UniffiAsyncCallHandler::Poll(UniquePtr<UniffiAsyncCallHandler> aHandler) {
|
|
||||||
auto futureHandle = aHandler->mFutureHandle;
|
|
||||||
auto pollFn = aHandler->mPollFn;
|
|
||||||
// Release the UniquePtr into a raw pointer and convert it to a handle
|
|
||||||
// so that we can pass it as a handle to the UniFFI code. It gets converted
|
|
||||||
// back in `UniffiAsyncCallHandler::FutureCallback()`, which the Rust code
|
|
||||||
// guarentees will be called if the future makes progress.
|
|
||||||
uint64_t selfHandle =
|
|
||||||
static_cast<uint64_t>(reinterpret_cast<uintptr_t>(aHandler.release()));
|
|
||||||
pollFn(futureHandle, UniffiAsyncCallHandler::FutureCallback, selfHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
UniffiAsyncCallHandler::~UniffiAsyncCallHandler() { mFreeFn(mFutureHandle); }
|
|
||||||
|
|
||||||
} // namespace mozilla::uniffi
|
|
||||||
@@ -1,231 +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_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(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
template <const UniFFIPointerType* PointerType>
|
|
||||||
class FfiValueObjectHandle {
|
|
||||||
private:
|
|
||||||
void* mValue = nullptr;
|
|
||||||
|
|
||||||
public:
|
|
||||||
FfiValueObjectHandle() = default;
|
|
||||||
explicit FfiValueObjectHandle(void* aValue) : mValue(aValue) {}
|
|
||||||
|
|
||||||
// Delete copy constructor and assignment as this type is non-copyable.
|
|
||||||
FfiValueObjectHandle(const FfiValueObjectHandle&) = delete;
|
|
||||||
FfiValueObjectHandle& operator=(const FfiValueObjectHandle&) = delete;
|
|
||||||
|
|
||||||
FfiValueObjectHandle& operator=(FfiValueObjectHandle&& aOther) {
|
|
||||||
if (mValue && mValue != aOther.mValue) {
|
|
||||||
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(PointerType)) {
|
|
||||||
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, PointerType);
|
|
||||||
mValue = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* IntoRust() {
|
|
||||||
auto temp = mValue;
|
|
||||||
mValue = nullptr;
|
|
||||||
return temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
static FfiValueObjectHandle FromRust(void* aValue) {
|
|
||||||
return FfiValueObjectHandle(aValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FreeHandle() {
|
|
||||||
if (mValue) {
|
|
||||||
RustCallStatus callStatus{};
|
|
||||||
(PointerType->destructor)(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.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
~FfiValueObjectHandle() {
|
|
||||||
// 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();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace mozilla::uniffi
|
|
||||||
|
|
||||||
#endif // mozilla_UniFFIFfiConverter_h
|
|
||||||
@@ -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/uniffi/OwnedRustBuffer.h"
|
#include "mozilla/dom/OwnedRustBuffer.h"
|
||||||
|
|
||||||
namespace mozilla::uniffi {
|
namespace mozilla::uniffi {
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
#include "mozilla/ErrorResult.h"
|
#include "mozilla/ErrorResult.h"
|
||||||
#include "mozilla/dom/TypedArray.h"
|
#include "mozilla/dom/TypedArray.h"
|
||||||
#include "mozilla/uniffi/Rust.h"
|
#include "mozilla/dom/UniFFIRust.h"
|
||||||
|
|
||||||
namespace mozilla::uniffi {
|
namespace mozilla::uniffi {
|
||||||
|
|
||||||
|
|||||||
@@ -2,3 +2,17 @@
|
|||||||
|
|
||||||
This directory contains C++ helper code for the UniFFI Rust library
|
This directory contains C++ helper code for the UniFFI Rust library
|
||||||
(https://github.com/mozilla/uniffi-rs/).
|
(https://github.com/mozilla/uniffi-rs/).
|
||||||
|
|
||||||
|
- `UniFFIPointer.*` and `UniFFIPointerType.*` implement the `UniFFIPointer` WebIDL class
|
||||||
|
|
||||||
|
- `UniFFI*Scaffolding.cpp` implements the `UniFFIScaffolding` WebIDL class.
|
||||||
|
- UniFFIGeneratedScaffolding.cpp contains the generated C++ code
|
||||||
|
- UniFFIScaffolding.cpp is a facade that wraps UniFFIFixtureScaffolding, and
|
||||||
|
UniFFIGeneratedScaffolding if enabled, to implement the interface.
|
||||||
|
|
||||||
|
- `ScaffoldingConverter.h` contain helper code to convert values between JS and Rust. This is used
|
||||||
|
by the generated code to make scaffolding calls.
|
||||||
|
|
||||||
|
- `OwnedRustBuffer.*` implements a C++ class to help manager ownership of a RustBuffer.
|
||||||
|
|
||||||
|
- `UniFFIRust.h` contains definitions for the C functions that UniFFI exports.
|
||||||
|
|||||||
@@ -1,54 +0,0 @@
|
|||||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
||||||
/* 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 "mozilla/uniffi/Call.h"
|
|
||||||
#include "mozilla/uniffi/ResultPromise.h"
|
|
||||||
|
|
||||||
namespace mozilla::uniffi {
|
|
||||||
|
|
||||||
void ResultPromise::Init(const dom::GlobalObject& aGlobal,
|
|
||||||
ErrorResult& aError) {
|
|
||||||
nsCOMPtr<nsIGlobalObject> xpcomGlobal =
|
|
||||||
do_QueryInterface(aGlobal.GetAsSupports());
|
|
||||||
RefPtr<dom::Promise> promise = dom::Promise::Create(xpcomGlobal, aError);
|
|
||||||
if (aError.Failed()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mPromise =
|
|
||||||
new nsMainThreadPtrHolder<dom::Promise>("uniffi::ResultPromise", promise);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ResultPromise::Complete(UniquePtr<UniffiCallHandlerBase> aHandler) {
|
|
||||||
MOZ_ASSERT(mPromise);
|
|
||||||
NS_DispatchToMainThread(NS_NewRunnableFunction(
|
|
||||||
"uniffi::ResultPromise::Complete",
|
|
||||||
[promise = mPromise, handler = std::move(aHandler)]() {
|
|
||||||
dom::AutoEntryScript aes(promise->GetGlobalObject(),
|
|
||||||
"uniffi::ResultPromise::Complete");
|
|
||||||
dom::RootedDictionary<dom::UniFFIScaffoldingCallResult> returnValue(
|
|
||||||
aes.cx());
|
|
||||||
|
|
||||||
ErrorResult error;
|
|
||||||
handler->LiftCallResult(aes.cx(), returnValue, error);
|
|
||||||
error.WouldReportJSException();
|
|
||||||
if (error.Failed()) {
|
|
||||||
promise->MaybeReject(std::move(error));
|
|
||||||
} else {
|
|
||||||
promise->MaybeResolve(returnValue);
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
void ResultPromise::RejectWithUnexpectedError() {
|
|
||||||
MOZ_ASSERT(mPromise);
|
|
||||||
NS_DispatchToMainThread(NS_NewRunnableFunction(
|
|
||||||
"uniffi::ResultPromise::RejectWithUnexpectedError", [promise = mPromise] {
|
|
||||||
promise->MaybeRejectWithUnknownError(
|
|
||||||
"UniFFI Unexpected Internal Error");
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace mozilla::uniffi
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
||||||
/* 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_dom_UniFFIResultPromise_h
|
|
||||||
#define mozilla_dom_UniFFIResultPromise_h
|
|
||||||
|
|
||||||
#include "nsThreadUtils.h"
|
|
||||||
#include "mozilla/MozPromise.h"
|
|
||||||
#include "mozilla/RefPtr.h"
|
|
||||||
#include "mozilla/UniquePtr.h"
|
|
||||||
#include "mozilla/dom/Promise.h"
|
|
||||||
#include "mozilla/dom/UniFFIBinding.h"
|
|
||||||
|
|
||||||
namespace mozilla::uniffi {
|
|
||||||
extern mozilla::LazyLogModule gUniffiLogger;
|
|
||||||
|
|
||||||
class UniffiAsyncCallHandler;
|
|
||||||
class UniffiCallHandlerBase;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* JS "bridge" for UniFFI
|
|
||||||
*
|
|
||||||
* This module intefaces with the SpiderMonkey JS API so that other code can
|
|
||||||
* focus on the core UniFFI logic.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class ResultPromise {
|
|
||||||
public:
|
|
||||||
ResultPromise() = default;
|
|
||||||
|
|
||||||
// Initialize a ResultPromise, this must be done before calling any other
|
|
||||||
// methods.
|
|
||||||
//
|
|
||||||
// This must be called on the main thread.
|
|
||||||
void Init(const dom::GlobalObject& aGlobal, ErrorResult& aError);
|
|
||||||
|
|
||||||
// Get a raw `dom::Promise` pointer
|
|
||||||
//
|
|
||||||
// Use this to return the promise from a webidl-generated function.
|
|
||||||
// May only be called on the main thread.
|
|
||||||
dom::Promise* GetPromise() { return mPromise; }
|
|
||||||
|
|
||||||
// Complete the promise using a call handler, this can be called from any
|
|
||||||
// thread.
|
|
||||||
//
|
|
||||||
// After a promise is completed, it must not be used anymore.
|
|
||||||
void Complete(UniquePtr<UniffiCallHandlerBase> aHandler);
|
|
||||||
|
|
||||||
// Reject the promise with an unexpected error.
|
|
||||||
//
|
|
||||||
// Use this as a last resort, when something has gone very wrong in the FFI.
|
|
||||||
//
|
|
||||||
// After a promise is rejected, it must not be used anymore.
|
|
||||||
void RejectWithUnexpectedError();
|
|
||||||
|
|
||||||
private:
|
|
||||||
// The `nsMainThreadPtrHandle` ensures that if this type is destroyed
|
|
||||||
// from off-main-thread, it'll actually be released on the main thread.
|
|
||||||
// This is important because the promise is a main-thread-only object.
|
|
||||||
nsMainThreadPtrHandle<dom::Promise> mPromise;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace mozilla::uniffi
|
|
||||||
|
|
||||||
#endif // mozilla_dom_UniFFIResultPromise_h
|
|
||||||
211
toolkit/components/uniffi-js/ScaffoldingConverter.h
Normal file
211
toolkit/components/uniffi-js/ScaffoldingConverter.h
Normal file
@@ -0,0 +1,211 @@
|
|||||||
|
/* -*- 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
|
||||||
299
toolkit/components/uniffi-js/UniFFICall.cpp
Normal file
299
toolkit/components/uniffi-js/UniFFICall.cpp
Normal file
@@ -0,0 +1,299 @@
|
|||||||
|
/* -*- 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 "nsThreadUtils.h"
|
||||||
|
#include "mozilla/dom/Promise.h"
|
||||||
|
#include "mozilla/dom/RootedDictionary.h"
|
||||||
|
#include "mozilla/dom/UniFFICall.h"
|
||||||
|
|
||||||
|
namespace mozilla::uniffi {
|
||||||
|
extern mozilla::LazyLogModule gUniffiLogger;
|
||||||
|
|
||||||
|
using dom::GlobalObject;
|
||||||
|
using dom::OwningUniFFIScaffoldingValue;
|
||||||
|
using dom::RootedDictionary;
|
||||||
|
using dom::Sequence;
|
||||||
|
using dom::UniFFIScaffoldingCallResult;
|
||||||
|
|
||||||
|
void UniffiSyncCallHandler::CallSync(
|
||||||
|
UniquePtr<UniffiSyncCallHandler> aHandler, const GlobalObject& aGlobal,
|
||||||
|
const Sequence<OwningUniFFIScaffoldingValue>& aArgs,
|
||||||
|
RootedDictionary<UniFFIScaffoldingCallResult>& aReturnValue,
|
||||||
|
ErrorResult& aError) {
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
aHandler->PrepareRustArgs(aArgs, aError);
|
||||||
|
if (aError.Failed()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
RustCallStatus callStatus{};
|
||||||
|
aHandler->MakeRustCall(&callStatus);
|
||||||
|
aHandler->mUniffiCallStatusCode = callStatus.code;
|
||||||
|
if (callStatus.error_buf.data) {
|
||||||
|
aHandler->mUniffiCallStatusErrorBuf = OwnedRustBuffer(callStatus.error_buf);
|
||||||
|
}
|
||||||
|
aHandler->ExtractCallResult(aGlobal.Context(), aReturnValue, aError);
|
||||||
|
}
|
||||||
|
|
||||||
|
already_AddRefed<dom::Promise> UniffiSyncCallHandler::CallAsyncWrapper(
|
||||||
|
UniquePtr<UniffiSyncCallHandler> aHandler, const dom::GlobalObject& aGlobal,
|
||||||
|
const dom::Sequence<dom::OwningUniFFIScaffoldingValue>& aArgs,
|
||||||
|
ErrorResult& aError) {
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
aHandler->PrepareRustArgs(aArgs, aError);
|
||||||
|
if (aError.Failed()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the promise that we return to JS
|
||||||
|
nsCOMPtr<nsIGlobalObject> xpcomGlobal =
|
||||||
|
do_QueryInterface(aGlobal.GetAsSupports());
|
||||||
|
RefPtr<dom::Promise> returnPromise =
|
||||||
|
dom::Promise::Create(xpcomGlobal, aError);
|
||||||
|
if (aError.Failed()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a second promise that gets resolved by a background task that
|
||||||
|
// calls the scaffolding function
|
||||||
|
RefPtr taskPromise =
|
||||||
|
new MozPromise<UniquePtr<UniffiSyncCallHandler>, nsresult, true>::Private(
|
||||||
|
__func__);
|
||||||
|
|
||||||
|
nsresult dispatchResult = NS_DispatchBackgroundTask(
|
||||||
|
NS_NewRunnableFunction(
|
||||||
|
__func__,
|
||||||
|
[handler = std::move(aHandler), taskPromise]() mutable {
|
||||||
|
RustCallStatus callStatus{};
|
||||||
|
handler->MakeRustCall(&callStatus);
|
||||||
|
handler->mUniffiCallStatusCode = callStatus.code;
|
||||||
|
if (callStatus.error_buf.data) {
|
||||||
|
handler->mUniffiCallStatusErrorBuf =
|
||||||
|
OwnedRustBuffer(callStatus.error_buf);
|
||||||
|
}
|
||||||
|
taskPromise->Resolve(std::move(handler), __func__);
|
||||||
|
}),
|
||||||
|
NS_DISPATCH_EVENT_MAY_BLOCK);
|
||||||
|
if (NS_FAILED(dispatchResult)) {
|
||||||
|
taskPromise->Reject(dispatchResult, __func__);
|
||||||
|
}
|
||||||
|
|
||||||
|
// When the background task promise completes, resolve the JS promise
|
||||||
|
taskPromise->Then(
|
||||||
|
GetCurrentSerialEventTarget(), __func__,
|
||||||
|
[xpcomGlobal, returnPromise](
|
||||||
|
typename MozPromise<UniquePtr<UniffiSyncCallHandler>, nsresult,
|
||||||
|
true>::ResolveOrRejectValue&& aResult) {
|
||||||
|
if (!aResult.IsResolve()) {
|
||||||
|
returnPromise->MaybeRejectWithUnknownError(__func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto handler = std::move(aResult.ResolveValue());
|
||||||
|
dom::AutoEntryScript aes(xpcomGlobal,
|
||||||
|
"UniffiSyncCallHandler::CallAsyncWrapper");
|
||||||
|
dom::RootedDictionary<dom::UniFFIScaffoldingCallResult> returnValue(
|
||||||
|
aes.cx());
|
||||||
|
|
||||||
|
ErrorResult error;
|
||||||
|
handler->ExtractCallResult(aes.cx(), returnValue, error);
|
||||||
|
error.WouldReportJSException();
|
||||||
|
if (error.Failed()) {
|
||||||
|
returnPromise->MaybeReject(std::move(error));
|
||||||
|
} else {
|
||||||
|
returnPromise->MaybeResolve(returnValue);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Return the JS promise, using forget() to convert it to already_AddRefed
|
||||||
|
return returnPromise.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UniffiCallHandlerBase::ExtractCallResult(
|
||||||
|
JSContext* aCx,
|
||||||
|
dom::RootedDictionary<dom::UniFFIScaffoldingCallResult>& aDest,
|
||||||
|
ErrorResult& aError) {
|
||||||
|
switch (mUniffiCallStatusCode) {
|
||||||
|
case RUST_CALL_SUCCESS: {
|
||||||
|
aDest.mCode = dom::UniFFIScaffoldingCallCode::Success;
|
||||||
|
ExtractSuccessfulCallResult(aCx, aDest.mData, aError);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case RUST_CALL_ERROR: {
|
||||||
|
// Rust Err() value. Populate data with the `RustBuffer` containing the
|
||||||
|
// error
|
||||||
|
aDest.mCode = dom::UniFFIScaffoldingCallCode::Error;
|
||||||
|
|
||||||
|
JS::Rooted<JSObject*> obj(aCx);
|
||||||
|
mUniffiCallStatusErrorBuf.IntoArrayBuffer(aCx, &obj, aError);
|
||||||
|
if (aError.Failed()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
aDest.mData.Construct().SetAsArrayBuffer().Init(obj);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: {
|
||||||
|
// This indicates a RustError, which should rarely happen in practice.
|
||||||
|
// The normal case is a Rust panic, but FF sets panic=abort.
|
||||||
|
aDest.mCode = dom::UniFFIScaffoldingCallCode::Internal_error;
|
||||||
|
if (mUniffiCallStatusErrorBuf.IsValid()) {
|
||||||
|
JS::Rooted<JSObject*> obj(aCx);
|
||||||
|
mUniffiCallStatusErrorBuf.IntoArrayBuffer(aCx, &obj, aError);
|
||||||
|
if (aError.Failed()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
aDest.mData.Construct().SetAsArrayBuffer().Init(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
already_AddRefed<dom::Promise> UniffiAsyncCallHandler::CallAsync(
|
||||||
|
UniquePtr<UniffiAsyncCallHandler> aHandler,
|
||||||
|
const dom::GlobalObject& aGlobal,
|
||||||
|
const dom::Sequence<dom::OwningUniFFIScaffoldingValue>& aArgs,
|
||||||
|
ErrorResult& aError) {
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
// Async calls return a Future rather than doing any work. This means we can
|
||||||
|
// make the call right now on the JS main thread without fear of blocking it.
|
||||||
|
aHandler->PrepareArgsAndMakeRustCall(aArgs, aError);
|
||||||
|
if (aError.Failed()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the promise that the handler will resolve
|
||||||
|
nsCOMPtr<nsIGlobalObject> global(do_QueryInterface(aGlobal.GetAsSupports()));
|
||||||
|
aHandler->mPromise = dom::Promise::Create(global, aError);
|
||||||
|
// Also get a copy to return to JS
|
||||||
|
RefPtr<dom::Promise> returnPromise(aHandler->mPromise);
|
||||||
|
|
||||||
|
if (aError.Failed()) {
|
||||||
|
aError.ThrowUnknownError("[UniFFI] dom::Promise::Create failed"_ns);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Schedule a poll for the future in a background thread.
|
||||||
|
nsresult dispatchResult = NS_DispatchBackgroundTask(NS_NewRunnableFunction(
|
||||||
|
__func__, [handler = std::move(aHandler)]() mutable {
|
||||||
|
UniffiAsyncCallHandler::Poll(std::move(handler));
|
||||||
|
}));
|
||||||
|
if (NS_FAILED(dispatchResult)) {
|
||||||
|
aError.ThrowUnknownError(
|
||||||
|
"[UniFFI] UniffiAsyncCallHandler::CallAsync - Error scheduling background task"_ns);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return a copy of the JS promise, using forget() to convert it to
|
||||||
|
// already_AddRefed
|
||||||
|
return returnPromise.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Callback function for async calls
|
||||||
|
//
|
||||||
|
// This is passed to Rust when we poll the future alongside a 64-bit handle that
|
||||||
|
// represents the callback data. For uniffi-bindgen-gecko-js, the handle is a
|
||||||
|
// `UniffiAsyncCallHandler*` casted to an int.
|
||||||
|
//
|
||||||
|
// Rust calls this when either the future is ready or when it's time to poll it
|
||||||
|
// again.
|
||||||
|
void UniffiAsyncCallHandler::FutureCallback(uint64_t aCallHandlerHandle,
|
||||||
|
int8_t aCode) {
|
||||||
|
// Recreate the UniquePtr we previously released
|
||||||
|
UniquePtr<UniffiAsyncCallHandler> handler(
|
||||||
|
reinterpret_cast<UniffiAsyncCallHandler*>(
|
||||||
|
static_cast<uintptr_t>(aCallHandlerHandle)));
|
||||||
|
|
||||||
|
switch (aCode) {
|
||||||
|
case UNIFFI_FUTURE_READY: {
|
||||||
|
// `Future::poll` returned a `Ready` value on the Rust side.
|
||||||
|
nsresult dispatchResult = NS_DispatchToMainThread(NS_NewRunnableFunction(
|
||||||
|
__func__, [handler = std::move(handler)]() mutable {
|
||||||
|
UniffiAsyncCallHandler::Finish(std::move(handler));
|
||||||
|
}));
|
||||||
|
if (NS_FAILED(dispatchResult)) {
|
||||||
|
MOZ_LOG(gUniffiLogger, LogLevel::Error,
|
||||||
|
("[UniFFI] NS_DispatchToMainThread failed in "
|
||||||
|
"UniffiAsyncCallHandler::FutureCallback"));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case UNIFFI_FUTURE_MAYBE_READY: {
|
||||||
|
// The Rust waker was invoked after `poll` returned a `Pending` value.
|
||||||
|
// Poll the future again soon in a background task.
|
||||||
|
nsresult dispatchResult = NS_DispatchBackgroundTask(
|
||||||
|
NS_NewRunnableFunction(__func__,
|
||||||
|
[handler = std::move(handler)]() mutable {
|
||||||
|
UniffiAsyncCallHandler::Poll(
|
||||||
|
std::move(handler));
|
||||||
|
}),
|
||||||
|
NS_DISPATCH_NORMAL);
|
||||||
|
if (NS_FAILED(dispatchResult)) {
|
||||||
|
MOZ_LOG(gUniffiLogger, LogLevel::Error,
|
||||||
|
("[UniFFI] NS_DispatchBackgroundTask failed in "
|
||||||
|
"UniffiAsyncCallHandler::FutureCallback"));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: {
|
||||||
|
// Invalid poll code, this should never happen, but if it does log an
|
||||||
|
// error and reject the promise.
|
||||||
|
MOZ_LOG(gUniffiLogger, LogLevel::Error,
|
||||||
|
("[UniFFI] Invalid poll code in "
|
||||||
|
"UniffiAsyncCallHandler::FutureCallback %d",
|
||||||
|
aCode));
|
||||||
|
handler->mPromise->MaybeRejectWithUndefined();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void UniffiAsyncCallHandler::Poll(UniquePtr<UniffiAsyncCallHandler> aHandler) {
|
||||||
|
auto futureHandle = aHandler->mFutureHandle;
|
||||||
|
auto pollFn = aHandler->mPollFn;
|
||||||
|
// Release the UniquePtr into a raw pointer and convert it to a handle
|
||||||
|
// so that we can pass it as a handle to the UniFFI code. It gets converted
|
||||||
|
// back in `UniffiAsyncCallHandler::FutureCallback()`, which the Rust code
|
||||||
|
// guarentees will be called if the future makes progress.
|
||||||
|
uint64_t selfHandle =
|
||||||
|
static_cast<uint64_t>(reinterpret_cast<uintptr_t>(aHandler.release()));
|
||||||
|
pollFn(futureHandle, UniffiAsyncCallHandler::FutureCallback, selfHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Complete the Rust future, extract the call result and resolve/reject the JS
|
||||||
|
// promise
|
||||||
|
void UniffiAsyncCallHandler::Finish(
|
||||||
|
UniquePtr<UniffiAsyncCallHandler> aHandler) {
|
||||||
|
RefPtr<dom::Promise> promise = aHandler->mPromise;
|
||||||
|
if (!promise) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dom::AutoEntryScript aes(promise->GetGlobalObject(),
|
||||||
|
"UniffiAsyncCallHandler::Finish");
|
||||||
|
dom::RootedDictionary<dom::UniFFIScaffoldingCallResult> returnValue(aes.cx());
|
||||||
|
ErrorResult error;
|
||||||
|
|
||||||
|
RustCallStatus callStatus{};
|
||||||
|
aHandler->CallCompleteFn(&callStatus);
|
||||||
|
aHandler->mUniffiCallStatusCode = callStatus.code;
|
||||||
|
if (callStatus.error_buf.data) {
|
||||||
|
aHandler->mUniffiCallStatusErrorBuf = OwnedRustBuffer(callStatus.error_buf);
|
||||||
|
}
|
||||||
|
aHandler->ExtractCallResult(aes.cx(), returnValue, error);
|
||||||
|
error.WouldReportJSException();
|
||||||
|
if (error.Failed()) {
|
||||||
|
aHandler->mPromise->MaybeReject(std::move(error));
|
||||||
|
} else {
|
||||||
|
aHandler->mPromise->MaybeResolve(returnValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UniffiAsyncCallHandler::~UniffiAsyncCallHandler() { mFreeFn(mFutureHandle); }
|
||||||
|
|
||||||
|
} // namespace mozilla::uniffi
|
||||||
@@ -9,11 +9,9 @@
|
|||||||
|
|
||||||
#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/ResultPromise.h"
|
|
||||||
#include "mozilla/uniffi/Rust.h"
|
|
||||||
|
|
||||||
namespace mozilla::uniffi {
|
namespace mozilla::uniffi {
|
||||||
|
|
||||||
@@ -30,7 +28,7 @@ namespace mozilla::uniffi {
|
|||||||
// In all cases, a new instance is created each time the scaffolding function
|
// In all cases, a new instance is created each time the scaffolding function
|
||||||
// is called.
|
// is called.
|
||||||
class UniffiCallHandlerBase {
|
class UniffiCallHandlerBase {
|
||||||
public:
|
protected:
|
||||||
// Extract the call result when the status code is `RUST_CALL_SUCCESS`.
|
// Extract the call result when the status code is `RUST_CALL_SUCCESS`.
|
||||||
//
|
//
|
||||||
// On success, set aDest with the converted return value. If there is a
|
// On success, set aDest with the converted return value. If there is a
|
||||||
@@ -38,7 +36,7 @@ class UniffiCallHandlerBase {
|
|||||||
// value doesn't fit into a JS number.
|
// value doesn't fit into a JS number.
|
||||||
//
|
//
|
||||||
// Called on the main thread.
|
// Called on the main thread.
|
||||||
virtual void LiftSuccessfulCallResult(
|
virtual void ExtractSuccessfulCallResult(
|
||||||
JSContext* aCx, dom::Optional<dom::OwningUniFFIScaffoldingValue>& aDest,
|
JSContext* aCx, dom::Optional<dom::OwningUniFFIScaffoldingValue>& aDest,
|
||||||
ErrorResult& aError) = 0;
|
ErrorResult& aError) = 0;
|
||||||
|
|
||||||
@@ -54,17 +52,14 @@ class UniffiCallHandlerBase {
|
|||||||
// panic=abort.
|
// panic=abort.
|
||||||
// - If some other error happens in the C++ layer, then `aError` will be set
|
// - If some other error happens in the C++ layer, then `aError` will be set
|
||||||
// to the error.
|
// to the error.
|
||||||
void LiftCallResult(
|
void ExtractCallResult(
|
||||||
JSContext* aCx,
|
JSContext* aCx,
|
||||||
dom::RootedDictionary<dom::UniFFIScaffoldingCallResult>& aDest,
|
dom::RootedDictionary<dom::UniFFIScaffoldingCallResult>& aDest,
|
||||||
ErrorResult& aError);
|
ErrorResult& aError);
|
||||||
|
|
||||||
virtual ~UniffiCallHandlerBase() = default;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// Call status from the rust call
|
// Call status from the rust call
|
||||||
int8_t mUniffiCallStatusCode = RUST_CALL_SUCCESS;
|
int8_t mUniffiCallStatusCode = RUST_CALL_SUCCESS;
|
||||||
FfiValueRustBuffer mUniffiCallStatusErrorBuf;
|
OwnedRustBuffer mUniffiCallStatusErrorBuf;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Call scaffolding functions for synchronous Rust calls
|
// Call scaffolding functions for synchronous Rust calls
|
||||||
@@ -74,7 +69,7 @@ class UniffiSyncCallHandler : public UniffiCallHandlerBase {
|
|||||||
|
|
||||||
// Convert a sequence of JS arguments and store them in this
|
// Convert a sequence of JS arguments and store them in this
|
||||||
// UniffiSyncCallHandler. Called on the main thread.
|
// UniffiSyncCallHandler. Called on the main thread.
|
||||||
virtual void LowerRustArgs(
|
virtual void PrepareRustArgs(
|
||||||
const dom::Sequence<dom::OwningUniFFIScaffoldingValue>& aArgs,
|
const dom::Sequence<dom::OwningUniFFIScaffoldingValue>& aArgs,
|
||||||
ErrorResult& aError) = 0;
|
ErrorResult& aError) = 0;
|
||||||
|
|
||||||
@@ -121,9 +116,9 @@ class UniffiAsyncCallHandler : public UniffiCallHandlerBase {
|
|||||||
//
|
//
|
||||||
// Always called on the main thread since async Rust calls don't block, they
|
// Always called on the main thread since async Rust calls don't block, they
|
||||||
// return a future. Because of this, there's no reason to split out the
|
// return a future. Because of this, there's no reason to split out the
|
||||||
// `LowerRustArgs` and `MakeRustCall` like in the sync
|
// `PrepareRustArgs` and `PrepareArgs` and `MakeRustCall` like in the sync
|
||||||
// case.
|
// case.
|
||||||
virtual void LowerArgsAndMakeRustCall(
|
virtual void PrepareArgsAndMakeRustCall(
|
||||||
const dom::Sequence<dom::OwningUniFFIScaffoldingValue>& aArgs,
|
const dom::Sequence<dom::OwningUniFFIScaffoldingValue>& aArgs,
|
||||||
ErrorResult& aError) = 0;
|
ErrorResult& aError) = 0;
|
||||||
|
|
||||||
@@ -145,6 +140,11 @@ class UniffiAsyncCallHandler : public UniffiCallHandlerBase {
|
|||||||
// Call mPollFn to poll the future
|
// Call mPollFn to poll the future
|
||||||
static void Poll(UniquePtr<UniffiAsyncCallHandler> aHandler);
|
static void Poll(UniquePtr<UniffiAsyncCallHandler> aHandler);
|
||||||
|
|
||||||
|
// Complete the async call and resolve the promise returned by CallAsync
|
||||||
|
//
|
||||||
|
// Called in the main thread.
|
||||||
|
static void Finish(UniquePtr<UniffiAsyncCallHandler> aHandler);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~UniffiAsyncCallHandler();
|
virtual ~UniffiAsyncCallHandler();
|
||||||
|
|
||||||
@@ -159,7 +159,7 @@ class UniffiAsyncCallHandler : public UniffiCallHandlerBase {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
// Promise created by CallAsync
|
// Promise created by CallAsync
|
||||||
ResultPromise mPromise;
|
RefPtr<dom::Promise> mPromise;
|
||||||
|
|
||||||
// Callback function for Rust async calls
|
// Callback function for Rust async calls
|
||||||
//
|
//
|
||||||
@@ -7,10 +7,10 @@
|
|||||||
#include "nsPrintfCString.h"
|
#include "nsPrintfCString.h"
|
||||||
#include "nsString.h"
|
#include "nsString.h"
|
||||||
#include "nsThreadUtils.h"
|
#include "nsThreadUtils.h"
|
||||||
#include "mozilla/uniffi/OwnedRustBuffer.h"
|
#include "mozilla/dom/OwnedRustBuffer.h"
|
||||||
#include "mozilla/dom/RootedDictionary.h"
|
#include "mozilla/dom/RootedDictionary.h"
|
||||||
#include "mozilla/dom/UniFFIBinding.h"
|
#include "mozilla/dom/UniFFIBinding.h"
|
||||||
#include "mozilla/uniffi/Callbacks.h"
|
#include "mozilla/dom/UniFFICallbacks.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"
|
||||||
@@ -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 {
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -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/UniFFIBinding.h"
|
|
||||||
#include "mozilla/dom/UniFFIPointer.h"
|
#include "mozilla/dom/UniFFIPointer.h"
|
||||||
#include "mozilla/uniffi/Rust.h"
|
#include "mozilla/dom/UniFFIBinding.h"
|
||||||
|
#include "mozilla/Logging.h"
|
||||||
|
#include "UniFFIRust.h"
|
||||||
|
|
||||||
namespace mozilla::uniffi {
|
namespace mozilla::uniffi {
|
||||||
extern mozilla::LazyLogModule gUniffiLogger;
|
extern mozilla::LazyLogModule gUniffiLogger;
|
||||||
|
|||||||
@@ -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/uniffi/PointerType.h"
|
#include "mozilla/dom/UniFFIPointerType.h"
|
||||||
|
|
||||||
namespace mozilla::dom {
|
namespace mozilla::dom {
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
#include "nsISupports.h"
|
#include "nsISupports.h"
|
||||||
#include "nsWrapperCache.h"
|
#include "nsWrapperCache.h"
|
||||||
#include "nsLiteralString.h"
|
#include "nsLiteralString.h"
|
||||||
#include "mozilla/uniffi/Rust.h"
|
#include "UniFFIRust.h"
|
||||||
|
|
||||||
namespace mozilla::uniffi {
|
namespace mozilla::uniffi {
|
||||||
|
|
||||||
@@ -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/dom/UniFFICallbacks.h"
|
||||||
#include "mozilla/dom/UniFFIScaffolding.h"
|
#include "mozilla/dom/UniFFIScaffolding.h"
|
||||||
#include "mozilla/uniffi/Call.h"
|
|
||||||
#include "mozilla/uniffi/Callbacks.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. It's main purpose is to check if
|
// code in UniFFIScaffolding.cpp and UniFFIFixtureScaffolding.cpp. It's main
|
||||||
// MOZ_UNIFFI_FIXTURES is set and only try calling the scaffolding code if it
|
// purpose is to check if MOZ_UNIFFI_FIXTURES is set and only try calling the
|
||||||
// is.
|
// scaffolding code if it 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 GeneratedScaffolding.cpp
|
// Implemented in UniFFIGeneratedScaffolding.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(
|
||||||
|
|||||||
@@ -7,11 +7,10 @@
|
|||||||
FINAL_LIBRARY = "xul"
|
FINAL_LIBRARY = "xul"
|
||||||
|
|
||||||
UNIFIED_SOURCES += [
|
UNIFIED_SOURCES += [
|
||||||
"Call.cpp",
|
|
||||||
"Callbacks.cpp",
|
|
||||||
"GeneratedScaffolding.cpp",
|
|
||||||
"OwnedRustBuffer.cpp",
|
"OwnedRustBuffer.cpp",
|
||||||
"ResultPromise.cpp",
|
"UniFFICall.cpp",
|
||||||
|
"UniFFICallbacks.cpp",
|
||||||
|
"UniFFIGeneratedScaffolding.cpp",
|
||||||
"UniFFIPointer.cpp",
|
"UniFFIPointer.cpp",
|
||||||
"UniFFIScaffolding.cpp",
|
"UniFFIScaffolding.cpp",
|
||||||
]
|
]
|
||||||
@@ -20,18 +19,14 @@ if CONFIG["MOZ_UNIFFI_FIXTURES"]:
|
|||||||
DEFINES["MOZ_UNIFFI_FIXTURES"] = True
|
DEFINES["MOZ_UNIFFI_FIXTURES"] = True
|
||||||
|
|
||||||
EXPORTS.mozilla.dom += [
|
EXPORTS.mozilla.dom += [
|
||||||
"UniFFIPointer.h",
|
|
||||||
"UniFFIScaffolding.h",
|
|
||||||
]
|
|
||||||
|
|
||||||
EXPORTS.mozilla.uniffi += [
|
|
||||||
"Call.h",
|
|
||||||
"Callbacks.h",
|
|
||||||
"FfiValue.h",
|
|
||||||
"OwnedRustBuffer.h",
|
"OwnedRustBuffer.h",
|
||||||
"PointerType.h",
|
"ScaffoldingConverter.h",
|
||||||
"ResultPromise.h",
|
"UniFFICall.h",
|
||||||
"Rust.h",
|
"UniFFICallbacks.h",
|
||||||
|
"UniFFIPointer.h",
|
||||||
|
"UniFFIPointerType.h",
|
||||||
|
"UniFFIRust.h",
|
||||||
|
"UniFFIScaffolding.h",
|
||||||
]
|
]
|
||||||
|
|
||||||
EXTRA_JS_MODULES += [
|
EXTRA_JS_MODULES += [
|
||||||
|
|||||||
@@ -215,7 +215,8 @@ 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/GeneratedScaffolding.cpp
|
toolkit/components/uniffi-js/UniFFIGeneratedScaffolding.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
|
||||||
|
|||||||
Reference in New Issue
Block a user