зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1788306: UniFFI callback interfaces, r=nika
Started callback interface functionality to UniFFI. Currently this only supports the async fire-and-forget use case, where Rust queues a JS function to run, but doesn't wait (or `await`) for the response. The basic system is: - The JS code registers a callback interface handler with the C++ code. This handler is responsible for the specifics of invoking the callback. - The C++ code defines a function to call a JS handler. Once the JS handler registers itself with C++, the C++ registers it's function with Rust. - The C++ code queues the call to the JS main thread. - Because of how UniFFI handles callback interfaces, the C++ code can be "dumb". UniFFI sends a object id, method id, and RustBuffer encoding all arguments. This means C++ doesn't need to care about the specific arguments, they get unpacked by JS. I tried to keep the generated code as simple as possible by moving the complexity to static code. For JS this meant writing a generic `UniFFICallbackHandler` class in the static code that the generated code constructs. For C++ this meant the generated code defines a `UniFFIGetCallbackInterfaceInfo` function that returns a struct with all the data specific to a callback interface (it's name, the UniFFI scaffolding init function, etc). The static code can then define a generic `QueueCallback` function that looks up the callback interface info using the interface ID and then makes the call. Allow UniFFI functions to run on the main thread rather than always being dispatched to a worker thread. This allows us to test invoking callback interfaces from the main thread thread. I don't think we will use this much currently, since we don't want to block the main thread for any significant amount of time. However, this will pair well with the next step in the project which is async -- allowing async Rust functions to call async JS functions. In that scenario, dispatching to the worker thread is unnecessary. Callback interface objects present a potential memory leak, since you can easily create a cycle between a JS Callback object and a UniFFIed Rust object, and the GC has no way of detecting it. To try to detect these there's some shutdown code that checks that there are no callbacks registered during shutdown and prevents any future callbacks from being registered. Added a `config.toml` file and code to parse it. This is needed to specify which functions should run on the main thread. Updated the git commits for the several UniFFI examples/fixtures. Differential Revision: https://phabricator.services.mozilla.com/D156116
This commit is contained in:
Родитель
192b74fdff
Коммит
79c4dcd5b0
|
@ -102,7 +102,7 @@ replace-with = "vendored-sources"
|
|||
|
||||
[source."https://github.com/mozilla/uniffi-rs.git"]
|
||||
git = "https://github.com/mozilla/uniffi-rs.git"
|
||||
rev = "bb2039f077a29dba0879372a67e764e6ace8e33f"
|
||||
rev = "846612a1d4fb5d11e246bf0682da4a499409424c"
|
||||
replace-with = "vendored-sources"
|
||||
|
||||
[source."https://github.com/rust-minidump/minidump-writer.git"]
|
||||
|
|
|
@ -2230,6 +2230,7 @@ dependencies = [
|
|||
"uniffi-example-rondpoint",
|
||||
"uniffi-example-sprites",
|
||||
"uniffi-example-todolist",
|
||||
"uniffi-fixture-callbacks",
|
||||
"uniffi-fixture-external-types",
|
||||
"url",
|
||||
"viaduct",
|
||||
|
@ -5769,8 +5770,8 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "uniffi-example-arithmetic"
|
||||
version = "0.18.0"
|
||||
source = "git+https://github.com/mozilla/uniffi-rs.git?rev=bb2039f077a29dba0879372a67e764e6ace8e33f#bb2039f077a29dba0879372a67e764e6ace8e33f"
|
||||
version = "0.21.0"
|
||||
source = "git+https://github.com/mozilla/uniffi-rs.git?rev=846612a1d4fb5d11e246bf0682da4a499409424c#846612a1d4fb5d11e246bf0682da4a499409424c"
|
||||
dependencies = [
|
||||
"thiserror",
|
||||
"uniffi",
|
||||
|
@ -5793,8 +5794,8 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "uniffi-example-geometry"
|
||||
version = "0.18.0"
|
||||
source = "git+https://github.com/mozilla/uniffi-rs.git?rev=bb2039f077a29dba0879372a67e764e6ace8e33f#bb2039f077a29dba0879372a67e764e6ace8e33f"
|
||||
version = "0.21.0"
|
||||
source = "git+https://github.com/mozilla/uniffi-rs.git?rev=846612a1d4fb5d11e246bf0682da4a499409424c#846612a1d4fb5d11e246bf0682da4a499409424c"
|
||||
dependencies = [
|
||||
"uniffi",
|
||||
"uniffi_build",
|
||||
|
@ -5803,8 +5804,8 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "uniffi-example-rondpoint"
|
||||
version = "0.18.0"
|
||||
source = "git+https://github.com/mozilla/uniffi-rs.git?rev=bb2039f077a29dba0879372a67e764e6ace8e33f#bb2039f077a29dba0879372a67e764e6ace8e33f"
|
||||
version = "0.21.0"
|
||||
source = "git+https://github.com/mozilla/uniffi-rs.git?rev=846612a1d4fb5d11e246bf0682da4a499409424c#846612a1d4fb5d11e246bf0682da4a499409424c"
|
||||
dependencies = [
|
||||
"uniffi",
|
||||
"uniffi_build",
|
||||
|
@ -5813,8 +5814,8 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "uniffi-example-sprites"
|
||||
version = "0.18.0"
|
||||
source = "git+https://github.com/mozilla/uniffi-rs.git?rev=bb2039f077a29dba0879372a67e764e6ace8e33f#bb2039f077a29dba0879372a67e764e6ace8e33f"
|
||||
version = "0.21.0"
|
||||
source = "git+https://github.com/mozilla/uniffi-rs.git?rev=846612a1d4fb5d11e246bf0682da4a499409424c#846612a1d4fb5d11e246bf0682da4a499409424c"
|
||||
dependencies = [
|
||||
"uniffi",
|
||||
"uniffi_build",
|
||||
|
@ -5823,10 +5824,20 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "uniffi-example-todolist"
|
||||
version = "0.18.0"
|
||||
source = "git+https://github.com/mozilla/uniffi-rs.git?rev=bb2039f077a29dba0879372a67e764e6ace8e33f#bb2039f077a29dba0879372a67e764e6ace8e33f"
|
||||
version = "0.21.0"
|
||||
source = "git+https://github.com/mozilla/uniffi-rs.git?rev=846612a1d4fb5d11e246bf0682da4a499409424c#846612a1d4fb5d11e246bf0682da4a499409424c"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"thiserror",
|
||||
"uniffi",
|
||||
"uniffi_build",
|
||||
"uniffi_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uniffi-fixture-callbacks"
|
||||
version = "0.21.0"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"thiserror",
|
||||
"uniffi",
|
||||
"uniffi_build",
|
||||
|
|
|
@ -12,14 +12,35 @@
|
|||
//
|
||||
// See https://mozilla.github.io/uniffi-rs/ for details.
|
||||
|
||||
// Define some ID types to identify various parts of the UDL interfaces. Using
|
||||
// these IDs, allow this .webidl file to remain static, but support new
|
||||
// interfaces. Using IDs is that the C++ and JS code need to agree on their
|
||||
// meaning, which is handled by
|
||||
// toolkit/components/uniffi-bindgen-gecko-js/src/ci_list.rs.
|
||||
|
||||
// Identifies a scaffolding function.
|
||||
typedef unsigned long long UniFFIFunctionId;
|
||||
|
||||
// Identifies a pointer type
|
||||
typedef unsigned long long UniFFIPointerId;
|
||||
|
||||
// Identifies a callback interface
|
||||
typedef unsigned long UniFFICallbackInterfaceId;
|
||||
|
||||
// Identifies a method of a callback interface
|
||||
typedef unsigned long UniFFICallbackMethodId;
|
||||
|
||||
// Handle for a callback interface instance
|
||||
typedef unsigned long long UniFFICallbackObjectHandle;
|
||||
|
||||
// Opaque type used to represent a pointer from Rust
|
||||
[ChromeOnly, Exposed=Window]
|
||||
interface UniFFIPointer {};
|
||||
|
||||
// Types that can be passed or returned from scaffolding functions
|
||||
//
|
||||
// - double is used for all numeric types (including bool, which the JS code
|
||||
// coerces to an int)
|
||||
// - double is used for all numeric types and types which the JS code coerces
|
||||
// to an int including Boolean and CallbackInterface.
|
||||
// - ArrayBuffer is used for RustBuffer
|
||||
// - UniFFIPointer is used for Arc pointers
|
||||
typedef (double or ArrayBuffer or UniFFIPointer) UniFFIScaffoldingType;
|
||||
|
@ -40,20 +61,47 @@ dictionary UniFFIScaffoldingCallResult {
|
|||
ByteString internalErrorMessage;
|
||||
};
|
||||
|
||||
// JS handler for calling a CallbackInterface method.
|
||||
// The arguments and return value are always packed into an ArrayBuffer
|
||||
callback UniFFICallbackHandler = undefined (UniFFICallbackObjectHandle objectId, UniFFICallbackMethodId methodId, ArrayBuffer aArgs);
|
||||
|
||||
// Functions to facilitate UniFFI scaffolding calls
|
||||
//
|
||||
// These should only be called by the generated code from UniFFI.
|
||||
[ChromeOnly, Exposed=Window]
|
||||
namespace UniFFIScaffolding {
|
||||
// Call a scaffolding function on the worker thread.
|
||||
//
|
||||
// id is a unique identifier for the function, known to both the C++ and JS code
|
||||
[Throws]
|
||||
Promise<UniFFIScaffoldingCallResult> callAsync(unsigned long long id, UniFFIScaffoldingType... args);
|
||||
Promise<UniFFIScaffoldingCallResult> callAsync(UniFFIFunctionId id, UniFFIScaffoldingType... args);
|
||||
|
||||
// Call a scaffolding function on the main thread
|
||||
//
|
||||
// id is a unique identifier for the function, known to both the C++ and JS code
|
||||
[Throws]
|
||||
UniFFIScaffoldingCallResult callSync(unsigned long long id, UniFFIScaffoldingType... args);
|
||||
UniFFIScaffoldingCallResult callSync(UniFFIFunctionId id, UniFFIScaffoldingType... args);
|
||||
|
||||
// Read a UniFFIPointer from an ArrayBuffer
|
||||
//
|
||||
// id is a unique identifier for the pointer type, known to both the C++ and JS code
|
||||
[Throws]
|
||||
UniFFIPointer readPointer(unsigned long long id, ArrayBuffer buff, long position);
|
||||
UniFFIPointer readPointer(UniFFIPointerId id, ArrayBuffer buff, long position);
|
||||
|
||||
// Write a UniFFIPointer to an ArrayBuffer
|
||||
//
|
||||
// id is a unique identifier for the pointer type, known to both the C++ and JS code
|
||||
[Throws]
|
||||
undefined writePointer(unsigned long long id, UniFFIPointer ptr, ArrayBuffer buff, long position);
|
||||
undefined writePointer(UniFFIPointerId id, UniFFIPointer ptr, ArrayBuffer buff, long position);
|
||||
|
||||
// Register the global calblack handler
|
||||
//
|
||||
// This will be used to invoke all calls for a CallbackInterface.
|
||||
// interfaceId is a unique identifier for the callback interface, known to both the C++ and JS code
|
||||
[Throws]
|
||||
undefined registerCallbackHandler(UniFFICallbackInterfaceId interfaceId, UniFFICallbackHandler handler);
|
||||
|
||||
// Deregister the global calblack handler
|
||||
//
|
||||
// This is called at shutdown to clear out the reference to the JS function.
|
||||
[Throws]
|
||||
undefined deregisterCallbackHandler(UniFFICallbackInterfaceId interfaceId);
|
||||
};
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"90295a750f9c69ee799ac767d56eaee2c3218df7964f11c885b6910a31d07a25","build.rs":"05089b35ac197b5ff83c75872a70df023834141831d0c2051faa35b4c9df55ba","src/arithmetic.udl":"8554c6907ece627645f6b896f71430e5412bf19b0ac6becf63eb9a69868d0f7a","src/lib.rs":"92ebd9fc4d3403ab1960d2d8520c1217971147ea3aebff89228a61fcbb8b2af3","tests/bindings/test_arithmetic.kts":"e0e9347755db4e18f70b1b74c2d5a4aa328373015090ed959b46d65c2a205d92","tests/bindings/test_arithmetic.py":"3e41d69e21e96a6830197c760f3b7bddd754edc0c5515b7bd33b79cccb10f941","tests/bindings/test_arithmetic.rb":"ea0fdce0a4c7b557b427db77521da05240cd6e87d60a128ac2307fab3bbbc76d","tests/bindings/test_arithmetic.swift":"455b87d95fc690af9c35f9e43676e9c855dedddd2fc1c9e1cbaa6a02835c2d4c","tests/test_generated_bindings.rs":"09b0e79c7e769bcf5f3a8b768247a05892d408d48e0295f6737de3c8dab28479","uniffi.toml":"ad149df611a6e3a853a029d90a88a694660f6a4ebe18dcb5f9f503819761dacd"},"package":null}
|
||||
{"files":{"Cargo.toml":"a4dd6685118bebe4eef690470cf112e51cc862162cf7d4c21c133d452ed7c488","build.rs":"05089b35ac197b5ff83c75872a70df023834141831d0c2051faa35b4c9df55ba","src/arithmetic.udl":"8554c6907ece627645f6b896f71430e5412bf19b0ac6becf63eb9a69868d0f7a","src/lib.rs":"92ebd9fc4d3403ab1960d2d8520c1217971147ea3aebff89228a61fcbb8b2af3","tests/bindings/test_arithmetic.kts":"e0e9347755db4e18f70b1b74c2d5a4aa328373015090ed959b46d65c2a205d92","tests/bindings/test_arithmetic.py":"3e41d69e21e96a6830197c760f3b7bddd754edc0c5515b7bd33b79cccb10f941","tests/bindings/test_arithmetic.rb":"ea0fdce0a4c7b557b427db77521da05240cd6e87d60a128ac2307fab3bbbc76d","tests/bindings/test_arithmetic.swift":"455b87d95fc690af9c35f9e43676e9c855dedddd2fc1c9e1cbaa6a02835c2d4c","tests/test_generated_bindings.rs":"09b0e79c7e769bcf5f3a8b768247a05892d408d48e0295f6737de3c8dab28479","uniffi.toml":"ad149df611a6e3a853a029d90a88a694660f6a4ebe18dcb5f9f503819761dacd"},"package":null}
|
|
@ -1,7 +1,7 @@
|
|||
[package]
|
||||
name = "uniffi-example-arithmetic"
|
||||
edition = "2021"
|
||||
version = "0.18.0"
|
||||
version = "0.21.0"
|
||||
authors = ["Firefox Sync Team <sync-team@mozilla.com>"]
|
||||
license = "MPL-2.0"
|
||||
publish = false
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"15bbf6e8c0d438e7f776dfdcf8da5fefb41e4b5bacafe97d1fcb10389d07ed9b","build.rs":"94ca4e70e538a2159cb77157c227d487973756373c4b27ea5cea05a6698cb60b","src/geometry.udl":"7da7a6ec080c7117ec3c25206e23f9ed436e60b1a26fba34f991547680443550","src/lib.rs":"be9c624f691a8d1ebe3be6dbbcde44033759b8321a3a298453018dd69b9c14c7","tests/bindings/test_geometry.kts":"e537185e3c699df1c0468525700e8a38f9a504b2a663c38442146b951e38e9a7","tests/bindings/test_geometry.py":"3ea483b8a4fbe13aefa6641177ae149f75f734bc32bf0da533b97c1abf3dc317","tests/bindings/test_geometry.rb":"17c2fe8a7b477419a6646983dd88f1b07a0304b58a568c03e9bfa640d5b2df5c","tests/bindings/test_geometry.swift":"a61fec6bfe16020809e20e4da372748c24366767138c5672a0bfff85c4b62d78","tests/test_generated_bindings.rs":"8ba67396105b96cc554f78078c7a8c6e8ce86ecc868d97a069a5f60fd87c1a36","uniffi.toml":"5b28f45d3c2581a52cf886a502f034778a002815b66994e5da2081a5c9f5284b"},"package":null}
|
||||
{"files":{"Cargo.toml":"ae167d6d92c007dac4db511c1b9ea2e4c7a7d6edb8f2fa95463b877825a3395a","build.rs":"94ca4e70e538a2159cb77157c227d487973756373c4b27ea5cea05a6698cb60b","src/geometry.udl":"7da7a6ec080c7117ec3c25206e23f9ed436e60b1a26fba34f991547680443550","src/lib.rs":"be9c624f691a8d1ebe3be6dbbcde44033759b8321a3a298453018dd69b9c14c7","tests/bindings/test_geometry.kts":"e537185e3c699df1c0468525700e8a38f9a504b2a663c38442146b951e38e9a7","tests/bindings/test_geometry.py":"3ea483b8a4fbe13aefa6641177ae149f75f734bc32bf0da533b97c1abf3dc317","tests/bindings/test_geometry.rb":"17c2fe8a7b477419a6646983dd88f1b07a0304b58a568c03e9bfa640d5b2df5c","tests/bindings/test_geometry.swift":"a61fec6bfe16020809e20e4da372748c24366767138c5672a0bfff85c4b62d78","tests/test_generated_bindings.rs":"8ba67396105b96cc554f78078c7a8c6e8ce86ecc868d97a069a5f60fd87c1a36","uniffi.toml":"5b28f45d3c2581a52cf886a502f034778a002815b66994e5da2081a5c9f5284b"},"package":null}
|
|
@ -1,7 +1,7 @@
|
|||
[package]
|
||||
name = "uniffi-example-geometry"
|
||||
edition = "2021"
|
||||
version = "0.18.0"
|
||||
version = "0.21.0"
|
||||
authors = ["Firefox Sync Team <sync-team@mozilla.com>"]
|
||||
license = "MPL-2.0"
|
||||
publish = false
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"e26e9e2826e89bf73aed693d2cea2aa1e2ce3d32cb0f03136cc29352f851295c","build.rs":"c48df8045c6cf73a8f3b8e93af7878f4ce1e7baa11f0688d661405f339df4ba4","src/lib.rs":"70b9ab1fb944d3af1ce53ce097caf52d1ebbf0e18be1e70bf57e5cec96e76502","src/rondpoint.udl":"ca4d8720758608b06ffd5f81bfc73881fbd0693a7a5b21bfe61a4557ea052048","tests/bindings/test_rondpoint.kts":"87b3d507f4260aae4e4711263c13b7158b9a814cb97bf5219d1451f348cd7372","tests/bindings/test_rondpoint.py":"d618274170af767f8a5614a2565ea698b26ea3e1a222d5c110e7b2d00763e73b","tests/bindings/test_rondpoint.rb":"9cc49df311823d6caedbe7b05ff8c4da6329063c2ce16810192aaaa7edcdf5f5","tests/bindings/test_rondpoint.swift":"471cf430be35dcdc19b3166adbc08561e0bd939931edc37da974e0fd16a49331","tests/test_generated_bindings.rs":"5843b2c9d6b86b35ab932349d278d9f281493880a1395e0b7566e297fad36c7d"},"package":null}
|
||||
{"files":{"Cargo.toml":"3cb89faf843332975007e3b6f9ad53cbcbdcaebc91c6abda2106b2b75ea01c70","build.rs":"c48df8045c6cf73a8f3b8e93af7878f4ce1e7baa11f0688d661405f339df4ba4","src/lib.rs":"b5eb9861fc436ab9fe9b0c00f95e374d812bbc0ea10b98cf746d38c96e44343a","src/rondpoint.udl":"ca4d8720758608b06ffd5f81bfc73881fbd0693a7a5b21bfe61a4557ea052048","tests/bindings/test_rondpoint.kts":"87b3d507f4260aae4e4711263c13b7158b9a814cb97bf5219d1451f348cd7372","tests/bindings/test_rondpoint.py":"d618274170af767f8a5614a2565ea698b26ea3e1a222d5c110e7b2d00763e73b","tests/bindings/test_rondpoint.rb":"9cc49df311823d6caedbe7b05ff8c4da6329063c2ce16810192aaaa7edcdf5f5","tests/bindings/test_rondpoint.swift":"471cf430be35dcdc19b3166adbc08561e0bd939931edc37da974e0fd16a49331","tests/test_generated_bindings.rs":"5843b2c9d6b86b35ab932349d278d9f281493880a1395e0b7566e297fad36c7d"},"package":null}
|
|
@ -1,7 +1,7 @@
|
|||
[package]
|
||||
name = "uniffi-example-rondpoint"
|
||||
edition = "2021"
|
||||
version = "0.18.0"
|
||||
version = "0.21.0"
|
||||
authors = ["Firefox Sync Team <sync-team@mozilla.com>"]
|
||||
license = "MPL-2.0"
|
||||
publish = false
|
||||
|
|
|
@ -179,7 +179,7 @@ impl Stringifier {
|
|||
value.to_string()
|
||||
}
|
||||
fn well_known_string(&self, value: String) -> String {
|
||||
format!("uniffi 💚 {}!", value)
|
||||
format!("uniffi 💚 {value}!")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"b288fc6b1e909cffdb5171a247f268884a2483d9f97f1a24a679681fb418bd8d","build.rs":"d36e4ff477007611d216e60998d6d8a51b33895bb95159e3d7732e2b8cbc1783","src/lib.rs":"79ae1ea584942b25c108a26df79a781a63d66f8fb37c4dacfc04d180752effcb","src/sprites.udl":"bfd35f04ba0549301189dfb8fc45b0f39bad00956c324f33be0e845fb7ff78aa","tests/bindings/test_sprites.kts":"06ed115325f37ce59ed6f33e2d651cd2aa352fddcc644580f62a6da6ca075844","tests/bindings/test_sprites.py":"2e6ce838cfb387586257703c3500062438e840dd7ae57d185cdc244dc0745b8f","tests/bindings/test_sprites.rb":"6289a1833c7c8f4583ee4f0488d680de2ee46cfb203095a9b66d7234e2f07d53","tests/bindings/test_sprites.swift":"b2c0a6f4d5edfd7de7c2ba77b838865ffda153a6f364f273456175192d3e6e00","tests/test_generated_bindings.rs":"920c532011c8a6c20bdb1f39c50ef7a2803729a62a1bd425d81e40300958778a"},"package":null}
|
||||
{"files":{"Cargo.toml":"78217b44063b2583832205fcbc5be8f1e92d4a77b58a97718edbdc9b2c60e604","build.rs":"d36e4ff477007611d216e60998d6d8a51b33895bb95159e3d7732e2b8cbc1783","src/lib.rs":"857ae59f3194cb7fe117a308854bc793b2b56441e297bd0e327795fd435494da","src/sprites.udl":"bfd35f04ba0549301189dfb8fc45b0f39bad00956c324f33be0e845fb7ff78aa","tests/bindings/test_sprites.kts":"06ed115325f37ce59ed6f33e2d651cd2aa352fddcc644580f62a6da6ca075844","tests/bindings/test_sprites.py":"2e6ce838cfb387586257703c3500062438e840dd7ae57d185cdc244dc0745b8f","tests/bindings/test_sprites.rb":"6289a1833c7c8f4583ee4f0488d680de2ee46cfb203095a9b66d7234e2f07d53","tests/bindings/test_sprites.swift":"b2c0a6f4d5edfd7de7c2ba77b838865ffda153a6f364f273456175192d3e6e00","tests/test_generated_bindings.rs":"920c532011c8a6c20bdb1f39c50ef7a2803729a62a1bd425d81e40300958778a"},"package":null}
|
|
@ -1,7 +1,7 @@
|
|||
[package]
|
||||
name = "uniffi-example-sprites"
|
||||
edition = "2021"
|
||||
version = "0.18.0"
|
||||
version = "0.21.0"
|
||||
authors = ["Firefox Sync Team <sync-team@mozilla.com>"]
|
||||
license = "MPL-2.0"
|
||||
publish = false
|
||||
|
|
|
@ -58,7 +58,7 @@ impl Sprite {
|
|||
|
||||
fn move_by(&self, direction: Vector) {
|
||||
let mut current_position = self.current_position.write().unwrap();
|
||||
*current_position = translate(&*current_position, direction)
|
||||
*current_position = translate(¤t_position, direction)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"4f4fc40bccf4ca5b105ea2abdbcdc6758ba7271d7d4ceb1e8ed45e3de227c2a6","build.rs":"ca26833c671cfe14a8275c276c197ab228cb1639b34cae31bb3805221ecc1245","src/lib.rs":"6a38904924681aed26b74876ad0480fedf8e8b2640cd2b04531a55aba8fc5592","src/todolist.udl":"1f8a24049c2340b9184e95facfc191ecdcb91541729ae7f20b4625d67685f13c","tests/bindings/test_todolist.kts":"f3d29b48e0193563fc4f131d91ea697f758174dcdb80ea554f233949e575bf55","tests/bindings/test_todolist.py":"f7430af9347df0daa954d38bc2203ce400affbb9a53fced4bb67a6796afa0664","tests/bindings/test_todolist.rb":"6524b5271a9cc0e2d78ca9f86ccb6973889926688a0843b4505a4f62d48f6dcb","tests/bindings/test_todolist.swift":"d1911b85fe0c8c0b42e5421b5af5d7359c9a65bba477d23560eb4b0f52e80662","tests/test_generated_bindings.rs":"25108de454213659c3eacd643a24c49099757a6b6da501fdb50874f574bd30c5"},"package":null}
|
||||
{"files":{"Cargo.toml":"1bd2d172cd1b8d546c9b15bae57d9cfa5ff4f8e2bbba50299cafa5a693577d15","build.rs":"ca26833c671cfe14a8275c276c197ab228cb1639b34cae31bb3805221ecc1245","src/lib.rs":"338494783dbbcd8abbc7a1b5206f52296064091faa0a04e2d622a0d370ad12fe","src/todolist.udl":"1f8a24049c2340b9184e95facfc191ecdcb91541729ae7f20b4625d67685f13c","tests/bindings/test_todolist.kts":"f3d29b48e0193563fc4f131d91ea697f758174dcdb80ea554f233949e575bf55","tests/bindings/test_todolist.py":"f7430af9347df0daa954d38bc2203ce400affbb9a53fced4bb67a6796afa0664","tests/bindings/test_todolist.rb":"6524b5271a9cc0e2d78ca9f86ccb6973889926688a0843b4505a4f62d48f6dcb","tests/bindings/test_todolist.swift":"d1911b85fe0c8c0b42e5421b5af5d7359c9a65bba477d23560eb4b0f52e80662","tests/test_generated_bindings.rs":"25108de454213659c3eacd643a24c49099757a6b6da501fdb50874f574bd30c5"},"package":null}
|
|
@ -1,7 +1,7 @@
|
|||
[package]
|
||||
name = "uniffi-example-todolist"
|
||||
edition = "2021"
|
||||
version = "0.18.0"
|
||||
version = "0.21.0"
|
||||
authors = ["Firefox Sync Team <sync-team@mozilla.com>"]
|
||||
license = "MPL-2.0"
|
||||
publish = false
|
||||
|
@ -13,8 +13,8 @@ name = "uniffi_todolist"
|
|||
[dependencies]
|
||||
uniffi_macros = {path = "../../uniffi_macros"}
|
||||
uniffi = {path = "../../uniffi", features=["builtin-bindgen"]}
|
||||
once_cell = "1.12"
|
||||
thiserror = "1.0"
|
||||
lazy_static = "1.4"
|
||||
|
||||
[build-dependencies]
|
||||
uniffi_build = {path = "../../uniffi_build", features=["builtin-bindgen"]}
|
||||
|
|
|
@ -4,18 +4,18 @@
|
|||
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TodoEntry {
|
||||
text: String,
|
||||
}
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
// There is a single "default" TodoList that can be shared
|
||||
// by all consumers of this component. Depending on requirements,
|
||||
// a real app might like to use a `Weak<>` rather than an `Arc<>`
|
||||
// here to reduce the risk of circular references.
|
||||
static ref DEFAULT_LIST: RwLock<Option<Arc<TodoList>>> = RwLock::new(None);
|
||||
}
|
||||
// There is a single "default" TodoList that can be shared
|
||||
// by all consumers of this component. Depending on requirements,
|
||||
// a real app might like to use a `Weak<>` rather than an `Arc<>`
|
||||
// here to reduce the risk of circular references.
|
||||
static DEFAULT_LIST: Lazy<RwLock<Option<Arc<TodoList>>>> = Lazy::new(|| RwLock::new(None));
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum TodoError {
|
||||
|
|
|
@ -5,7 +5,10 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
var EXPORTED_SYMBOLS = [];
|
||||
// Objects intended to be used in the unit tests
|
||||
var UnitTestObjs = {};
|
||||
|
||||
var EXPORTED_SYMBOLS = ["UnitTestObjs"];
|
||||
|
||||
// Write/Read data to/from an ArrayBuffer
|
||||
class ArrayBufferDataStream {
|
||||
|
@ -103,7 +106,6 @@ class ArrayBufferDataStream {
|
|||
this.pos += 8;
|
||||
}
|
||||
|
||||
|
||||
readFloat32() {
|
||||
let rv = this.dataView.getFloat32(this.pos);
|
||||
this.pos += 4;
|
||||
|
@ -220,6 +222,10 @@ class UniFFIError {
|
|||
constructor(message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
toString() {
|
||||
return `UniFFIError: ${this.message}`
|
||||
}
|
||||
}
|
||||
|
||||
class UniFFIInternalError extends UniFFIError {}
|
||||
|
@ -323,200 +329,226 @@ class TabsBridgedEngine {
|
|||
}
|
||||
this[uniffiObjectPtr] = opts[constructUniffiObject];
|
||||
}
|
||||
|
||||
lastSync() {
|
||||
const liftResult = (result) => FfiConverterI64.lift(result);
|
||||
const liftError = (data) => FfiConverterTypeTabsApiError.lift(data);
|
||||
const functionCall = () => {
|
||||
return UniFFIScaffolding.callAsync(
|
||||
7, // tabs:tabs_edc9_TabsBridgedEngine_last_sync
|
||||
FfiConverterTypeTabsBridgedEngine.lower(this),
|
||||
)
|
||||
const liftResult = (result) => FfiConverterI64.lift(result);
|
||||
const liftError = (data) => FfiConverterTypeTabsApiError.lift(data);
|
||||
const functionCall = () => {
|
||||
return UniFFIScaffolding.callAsync(
|
||||
7, // tabs:tabs_edc9_TabsBridgedEngine_last_sync
|
||||
FfiConverterTypeTabsBridgedEngine.lower(this),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}}
|
||||
|
||||
setLastSync(lastSync) {
|
||||
const liftResult = (result) => undefined;
|
||||
const liftError = (data) => FfiConverterTypeTabsApiError.lift(data);
|
||||
const functionCall = () => {
|
||||
FfiConverterI64.checkType("lastSync", lastSync);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
8, // tabs:tabs_edc9_TabsBridgedEngine_set_last_sync
|
||||
FfiConverterTypeTabsBridgedEngine.lower(this),
|
||||
FfiConverterI64.lower(lastSync),
|
||||
)
|
||||
const liftResult = (result) => undefined;
|
||||
const liftError = (data) => FfiConverterTypeTabsApiError.lift(data);
|
||||
const functionCall = () => {
|
||||
FfiConverterI64.checkType("lastSync", lastSync);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
8, // tabs:tabs_edc9_TabsBridgedEngine_set_last_sync
|
||||
FfiConverterTypeTabsBridgedEngine.lower(this),
|
||||
FfiConverterI64.lower(lastSync),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}}
|
||||
|
||||
syncId() {
|
||||
const liftResult = (result) => FfiConverterOptionalstring.lift(result);
|
||||
const liftError = (data) => FfiConverterTypeTabsApiError.lift(data);
|
||||
const functionCall = () => {
|
||||
return UniFFIScaffolding.callAsync(
|
||||
9, // tabs:tabs_edc9_TabsBridgedEngine_sync_id
|
||||
FfiConverterTypeTabsBridgedEngine.lower(this),
|
||||
)
|
||||
const liftResult = (result) => FfiConverterOptionalstring.lift(result);
|
||||
const liftError = (data) => FfiConverterTypeTabsApiError.lift(data);
|
||||
const functionCall = () => {
|
||||
return UniFFIScaffolding.callAsync(
|
||||
9, // tabs:tabs_edc9_TabsBridgedEngine_sync_id
|
||||
FfiConverterTypeTabsBridgedEngine.lower(this),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}}
|
||||
|
||||
resetSyncId() {
|
||||
const liftResult = (result) => FfiConverterString.lift(result);
|
||||
const liftError = (data) => FfiConverterTypeTabsApiError.lift(data);
|
||||
const functionCall = () => {
|
||||
return UniFFIScaffolding.callAsync(
|
||||
10, // tabs:tabs_edc9_TabsBridgedEngine_reset_sync_id
|
||||
FfiConverterTypeTabsBridgedEngine.lower(this),
|
||||
)
|
||||
const liftResult = (result) => FfiConverterString.lift(result);
|
||||
const liftError = (data) => FfiConverterTypeTabsApiError.lift(data);
|
||||
const functionCall = () => {
|
||||
return UniFFIScaffolding.callAsync(
|
||||
10, // tabs:tabs_edc9_TabsBridgedEngine_reset_sync_id
|
||||
FfiConverterTypeTabsBridgedEngine.lower(this),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}}
|
||||
|
||||
ensureCurrentSyncId(newSyncId) {
|
||||
const liftResult = (result) => FfiConverterString.lift(result);
|
||||
const liftError = (data) => FfiConverterTypeTabsApiError.lift(data);
|
||||
const functionCall = () => {
|
||||
FfiConverterString.checkType("newSyncId", newSyncId);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
11, // tabs:tabs_edc9_TabsBridgedEngine_ensure_current_sync_id
|
||||
FfiConverterTypeTabsBridgedEngine.lower(this),
|
||||
FfiConverterString.lower(newSyncId),
|
||||
)
|
||||
const liftResult = (result) => FfiConverterString.lift(result);
|
||||
const liftError = (data) => FfiConverterTypeTabsApiError.lift(data);
|
||||
const functionCall = () => {
|
||||
FfiConverterString.checkType("newSyncId", newSyncId);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
11, // tabs:tabs_edc9_TabsBridgedEngine_ensure_current_sync_id
|
||||
FfiConverterTypeTabsBridgedEngine.lower(this),
|
||||
FfiConverterString.lower(newSyncId),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}}
|
||||
|
||||
prepareForSync(clientData) {
|
||||
const liftResult = (result) => undefined;
|
||||
const liftError = (data) => FfiConverterTypeTabsApiError.lift(data);
|
||||
const functionCall = () => {
|
||||
FfiConverterString.checkType("clientData", clientData);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
12, // tabs:tabs_edc9_TabsBridgedEngine_prepare_for_sync
|
||||
FfiConverterTypeTabsBridgedEngine.lower(this),
|
||||
FfiConverterString.lower(clientData),
|
||||
)
|
||||
const liftResult = (result) => undefined;
|
||||
const liftError = (data) => FfiConverterTypeTabsApiError.lift(data);
|
||||
const functionCall = () => {
|
||||
FfiConverterString.checkType("clientData", clientData);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
12, // tabs:tabs_edc9_TabsBridgedEngine_prepare_for_sync
|
||||
FfiConverterTypeTabsBridgedEngine.lower(this),
|
||||
FfiConverterString.lower(clientData),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}}
|
||||
|
||||
syncStarted() {
|
||||
const liftResult = (result) => undefined;
|
||||
const liftError = (data) => FfiConverterTypeTabsApiError.lift(data);
|
||||
const functionCall = () => {
|
||||
return UniFFIScaffolding.callAsync(
|
||||
13, // tabs:tabs_edc9_TabsBridgedEngine_sync_started
|
||||
FfiConverterTypeTabsBridgedEngine.lower(this),
|
||||
)
|
||||
const liftResult = (result) => undefined;
|
||||
const liftError = (data) => FfiConverterTypeTabsApiError.lift(data);
|
||||
const functionCall = () => {
|
||||
return UniFFIScaffolding.callAsync(
|
||||
13, // tabs:tabs_edc9_TabsBridgedEngine_sync_started
|
||||
FfiConverterTypeTabsBridgedEngine.lower(this),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}}
|
||||
|
||||
storeIncoming(incomingEnvelopesAsJson) {
|
||||
const liftResult = (result) => undefined;
|
||||
const liftError = (data) => FfiConverterTypeTabsApiError.lift(data);
|
||||
const functionCall = () => {
|
||||
FfiConverterSequencestring.checkType("incomingEnvelopesAsJson", incomingEnvelopesAsJson);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
14, // tabs:tabs_edc9_TabsBridgedEngine_store_incoming
|
||||
FfiConverterTypeTabsBridgedEngine.lower(this),
|
||||
FfiConverterSequencestring.lower(incomingEnvelopesAsJson),
|
||||
)
|
||||
const liftResult = (result) => undefined;
|
||||
const liftError = (data) => FfiConverterTypeTabsApiError.lift(data);
|
||||
const functionCall = () => {
|
||||
FfiConverterSequencestring.checkType("incomingEnvelopesAsJson", incomingEnvelopesAsJson);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
14, // tabs:tabs_edc9_TabsBridgedEngine_store_incoming
|
||||
FfiConverterTypeTabsBridgedEngine.lower(this),
|
||||
FfiConverterSequencestring.lower(incomingEnvelopesAsJson),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}}
|
||||
|
||||
apply() {
|
||||
const liftResult = (result) => FfiConverterSequencestring.lift(result);
|
||||
const liftError = (data) => FfiConverterTypeTabsApiError.lift(data);
|
||||
const functionCall = () => {
|
||||
return UniFFIScaffolding.callAsync(
|
||||
15, // tabs:tabs_edc9_TabsBridgedEngine_apply
|
||||
FfiConverterTypeTabsBridgedEngine.lower(this),
|
||||
)
|
||||
const liftResult = (result) => FfiConverterSequencestring.lift(result);
|
||||
const liftError = (data) => FfiConverterTypeTabsApiError.lift(data);
|
||||
const functionCall = () => {
|
||||
return UniFFIScaffolding.callAsync(
|
||||
15, // tabs:tabs_edc9_TabsBridgedEngine_apply
|
||||
FfiConverterTypeTabsBridgedEngine.lower(this),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}}
|
||||
|
||||
setUploaded(newTimestamp,uploadedIds) {
|
||||
const liftResult = (result) => undefined;
|
||||
const liftError = (data) => FfiConverterTypeTabsApiError.lift(data);
|
||||
const functionCall = () => {
|
||||
FfiConverterI64.checkType("newTimestamp", newTimestamp);
|
||||
FfiConverterSequenceTypeTabsGuid.checkType("uploadedIds", uploadedIds);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
16, // tabs:tabs_edc9_TabsBridgedEngine_set_uploaded
|
||||
FfiConverterTypeTabsBridgedEngine.lower(this),
|
||||
FfiConverterI64.lower(newTimestamp),
|
||||
FfiConverterSequenceTypeTabsGuid.lower(uploadedIds),
|
||||
)
|
||||
const liftResult = (result) => undefined;
|
||||
const liftError = (data) => FfiConverterTypeTabsApiError.lift(data);
|
||||
const functionCall = () => {
|
||||
FfiConverterI64.checkType("newTimestamp", newTimestamp);
|
||||
FfiConverterSequenceTypeTabsGuid.checkType("uploadedIds", uploadedIds);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
16, // tabs:tabs_edc9_TabsBridgedEngine_set_uploaded
|
||||
FfiConverterTypeTabsBridgedEngine.lower(this),
|
||||
FfiConverterI64.lower(newTimestamp),
|
||||
FfiConverterSequenceTypeTabsGuid.lower(uploadedIds),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}}
|
||||
|
||||
syncFinished() {
|
||||
const liftResult = (result) => undefined;
|
||||
const liftError = (data) => FfiConverterTypeTabsApiError.lift(data);
|
||||
const functionCall = () => {
|
||||
return UniFFIScaffolding.callAsync(
|
||||
17, // tabs:tabs_edc9_TabsBridgedEngine_sync_finished
|
||||
FfiConverterTypeTabsBridgedEngine.lower(this),
|
||||
)
|
||||
const liftResult = (result) => undefined;
|
||||
const liftError = (data) => FfiConverterTypeTabsApiError.lift(data);
|
||||
const functionCall = () => {
|
||||
return UniFFIScaffolding.callAsync(
|
||||
17, // tabs:tabs_edc9_TabsBridgedEngine_sync_finished
|
||||
FfiConverterTypeTabsBridgedEngine.lower(this),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}}
|
||||
|
||||
reset() {
|
||||
const liftResult = (result) => undefined;
|
||||
const liftError = (data) => FfiConverterTypeTabsApiError.lift(data);
|
||||
const functionCall = () => {
|
||||
return UniFFIScaffolding.callAsync(
|
||||
18, // tabs:tabs_edc9_TabsBridgedEngine_reset
|
||||
FfiConverterTypeTabsBridgedEngine.lower(this),
|
||||
)
|
||||
const liftResult = (result) => undefined;
|
||||
const liftError = (data) => FfiConverterTypeTabsApiError.lift(data);
|
||||
const functionCall = () => {
|
||||
return UniFFIScaffolding.callAsync(
|
||||
18, // tabs:tabs_edc9_TabsBridgedEngine_reset
|
||||
FfiConverterTypeTabsBridgedEngine.lower(this),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}}
|
||||
|
||||
wipe() {
|
||||
const liftResult = (result) => undefined;
|
||||
const liftError = (data) => FfiConverterTypeTabsApiError.lift(data);
|
||||
const functionCall = () => {
|
||||
return UniFFIScaffolding.callAsync(
|
||||
19, // tabs:tabs_edc9_TabsBridgedEngine_wipe
|
||||
FfiConverterTypeTabsBridgedEngine.lower(this),
|
||||
)
|
||||
const liftResult = (result) => undefined;
|
||||
const liftError = (data) => FfiConverterTypeTabsApiError.lift(data);
|
||||
const functionCall = () => {
|
||||
return UniFFIScaffolding.callAsync(
|
||||
19, // tabs:tabs_edc9_TabsBridgedEngine_wipe
|
||||
FfiConverterTypeTabsBridgedEngine.lower(this),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}}
|
||||
|
||||
}
|
||||
|
||||
|
@ -569,116 +601,128 @@ class TabsStore {
|
|||
* to a newly constructed TabsStore
|
||||
*/
|
||||
static init(path) {
|
||||
const liftResult = (result) => FfiConverterTypeTabsStore.lift(result);
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
FfiConverterString.checkType("path", path);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
0, // tabs:tabs_edc9_TabsStore_new
|
||||
FfiConverterString.lower(path),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}}
|
||||
const liftResult = (result) => FfiConverterTypeTabsStore.lift(result);
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
FfiConverterString.checkType("path", path);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
0, // tabs:tabs_edc9_TabsStore_new
|
||||
FfiConverterString.lower(path),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}}
|
||||
|
||||
getAll() {
|
||||
const liftResult = (result) => FfiConverterSequenceTypeClientRemoteTabs.lift(result);
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
return UniFFIScaffolding.callAsync(
|
||||
1, // tabs:tabs_edc9_TabsStore_get_all
|
||||
FfiConverterTypeTabsStore.lower(this),
|
||||
)
|
||||
const liftResult = (result) => FfiConverterSequenceTypeClientRemoteTabs.lift(result);
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
return UniFFIScaffolding.callAsync(
|
||||
1, // tabs:tabs_edc9_TabsStore_get_all
|
||||
FfiConverterTypeTabsStore.lower(this),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}}
|
||||
|
||||
setLocalTabs(remoteTabs) {
|
||||
const liftResult = (result) => undefined;
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
FfiConverterSequenceTypeRemoteTabRecord.checkType("remoteTabs", remoteTabs);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
2, // tabs:tabs_edc9_TabsStore_set_local_tabs
|
||||
FfiConverterTypeTabsStore.lower(this),
|
||||
FfiConverterSequenceTypeRemoteTabRecord.lower(remoteTabs),
|
||||
)
|
||||
const liftResult = (result) => undefined;
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
FfiConverterSequenceTypeRemoteTabRecord.checkType("remoteTabs", remoteTabs);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
2, // tabs:tabs_edc9_TabsStore_set_local_tabs
|
||||
FfiConverterTypeTabsStore.lower(this),
|
||||
FfiConverterSequenceTypeRemoteTabRecord.lower(remoteTabs),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}}
|
||||
|
||||
registerWithSyncManager() {
|
||||
const liftResult = (result) => undefined;
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
return UniFFIScaffolding.callAsync(
|
||||
3, // tabs:tabs_edc9_TabsStore_register_with_sync_manager
|
||||
FfiConverterTypeTabsStore.lower(this),
|
||||
)
|
||||
const liftResult = (result) => undefined;
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
return UniFFIScaffolding.callAsync(
|
||||
3, // tabs:tabs_edc9_TabsStore_register_with_sync_manager
|
||||
FfiConverterTypeTabsStore.lower(this),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}}
|
||||
|
||||
reset() {
|
||||
const liftResult = (result) => undefined;
|
||||
const liftError = (data) => FfiConverterTypeTabsApiError.lift(data);
|
||||
const functionCall = () => {
|
||||
return UniFFIScaffolding.callAsync(
|
||||
4, // tabs:tabs_edc9_TabsStore_reset
|
||||
FfiConverterTypeTabsStore.lower(this),
|
||||
)
|
||||
const liftResult = (result) => undefined;
|
||||
const liftError = (data) => FfiConverterTypeTabsApiError.lift(data);
|
||||
const functionCall = () => {
|
||||
return UniFFIScaffolding.callAsync(
|
||||
4, // tabs:tabs_edc9_TabsStore_reset
|
||||
FfiConverterTypeTabsStore.lower(this),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}}
|
||||
|
||||
sync(keyId,accessToken,syncKey,tokenserverUrl,localId) {
|
||||
const liftResult = (result) => FfiConverterString.lift(result);
|
||||
const liftError = (data) => FfiConverterTypeTabsApiError.lift(data);
|
||||
const functionCall = () => {
|
||||
FfiConverterString.checkType("keyId", keyId);
|
||||
FfiConverterString.checkType("accessToken", accessToken);
|
||||
FfiConverterString.checkType("syncKey", syncKey);
|
||||
FfiConverterString.checkType("tokenserverUrl", tokenserverUrl);
|
||||
FfiConverterString.checkType("localId", localId);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
5, // tabs:tabs_edc9_TabsStore_sync
|
||||
FfiConverterTypeTabsStore.lower(this),
|
||||
FfiConverterString.lower(keyId),
|
||||
FfiConverterString.lower(accessToken),
|
||||
FfiConverterString.lower(syncKey),
|
||||
FfiConverterString.lower(tokenserverUrl),
|
||||
FfiConverterString.lower(localId),
|
||||
)
|
||||
const liftResult = (result) => FfiConverterString.lift(result);
|
||||
const liftError = (data) => FfiConverterTypeTabsApiError.lift(data);
|
||||
const functionCall = () => {
|
||||
FfiConverterString.checkType("keyId", keyId);
|
||||
FfiConverterString.checkType("accessToken", accessToken);
|
||||
FfiConverterString.checkType("syncKey", syncKey);
|
||||
FfiConverterString.checkType("tokenserverUrl", tokenserverUrl);
|
||||
FfiConverterString.checkType("localId", localId);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
5, // tabs:tabs_edc9_TabsStore_sync
|
||||
FfiConverterTypeTabsStore.lower(this),
|
||||
FfiConverterString.lower(keyId),
|
||||
FfiConverterString.lower(accessToken),
|
||||
FfiConverterString.lower(syncKey),
|
||||
FfiConverterString.lower(tokenserverUrl),
|
||||
FfiConverterString.lower(localId),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}}
|
||||
|
||||
bridgedEngine() {
|
||||
const liftResult = (result) => FfiConverterTypeTabsBridgedEngine.lift(result);
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
return UniFFIScaffolding.callAsync(
|
||||
6, // tabs:tabs_edc9_TabsStore_bridged_engine
|
||||
FfiConverterTypeTabsStore.lower(this),
|
||||
)
|
||||
const liftResult = (result) => FfiConverterTypeTabsBridgedEngine.lift(result);
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
return UniFFIScaffolding.callAsync(
|
||||
6, // tabs:tabs_edc9_TabsStore_bridged_engine
|
||||
FfiConverterTypeTabsStore.lower(this),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}}
|
||||
|
||||
}
|
||||
|
||||
|
@ -918,10 +962,13 @@ class SyncError extends TabsApiError {
|
|||
constructor(
|
||||
reason,
|
||||
...params
|
||||
) {
|
||||
super(...params);
|
||||
this.reason = reason;
|
||||
}
|
||||
) {
|
||||
super(...params);
|
||||
this.reason = reason;
|
||||
}
|
||||
toString() {
|
||||
return `SyncError: ${super.toString()}`
|
||||
}
|
||||
}
|
||||
EXPORTED_SYMBOLS.push("SyncError");
|
||||
class SqlError extends TabsApiError {
|
||||
|
@ -929,10 +976,13 @@ class SqlError extends TabsApiError {
|
|||
constructor(
|
||||
reason,
|
||||
...params
|
||||
) {
|
||||
super(...params);
|
||||
this.reason = reason;
|
||||
}
|
||||
) {
|
||||
super(...params);
|
||||
this.reason = reason;
|
||||
}
|
||||
toString() {
|
||||
return `SqlError: ${super.toString()}`
|
||||
}
|
||||
}
|
||||
EXPORTED_SYMBOLS.push("SqlError");
|
||||
class UnexpectedTabsError extends TabsApiError {
|
||||
|
@ -940,10 +990,13 @@ class UnexpectedTabsError extends TabsApiError {
|
|||
constructor(
|
||||
reason,
|
||||
...params
|
||||
) {
|
||||
super(...params);
|
||||
this.reason = reason;
|
||||
}
|
||||
) {
|
||||
super(...params);
|
||||
this.reason = reason;
|
||||
}
|
||||
toString() {
|
||||
return `UnexpectedTabsError: ${super.toString()}`
|
||||
}
|
||||
}
|
||||
EXPORTED_SYMBOLS.push("UnexpectedTabsError");
|
||||
|
||||
|
@ -963,9 +1016,46 @@ class FfiConverterTypeTabsApiError extends FfiConverterArrayBuffer {
|
|||
FfiConverterString.read(dataStream)
|
||||
);
|
||||
default:
|
||||
return new Error("Unknown TabsApiError variant");
|
||||
throw new Error("Unknown TabsApiError variant");
|
||||
}
|
||||
}
|
||||
static computeSize(value) {
|
||||
// Size of the Int indicating the variant
|
||||
let totalSize = 4;
|
||||
if (value instanceof SyncError) {
|
||||
totalSize += FfiConverterString.computeSize(value.reason);
|
||||
return totalSize;
|
||||
}
|
||||
if (value instanceof SqlError) {
|
||||
totalSize += FfiConverterString.computeSize(value.reason);
|
||||
return totalSize;
|
||||
}
|
||||
if (value instanceof UnexpectedTabsError) {
|
||||
totalSize += FfiConverterString.computeSize(value.reason);
|
||||
return totalSize;
|
||||
}
|
||||
throw new Error("Unknown TabsApiError variant");
|
||||
}
|
||||
static write(dataStream, value) {
|
||||
if (value instanceof SyncError) {
|
||||
dataStream.writeInt32(1);
|
||||
FfiConverterString.write(dataStream, value.reason);
|
||||
return;
|
||||
}
|
||||
if (value instanceof SqlError) {
|
||||
dataStream.writeInt32(2);
|
||||
FfiConverterString.write(dataStream, value.reason);
|
||||
return;
|
||||
}
|
||||
if (value instanceof UnexpectedTabsError) {
|
||||
dataStream.writeInt32(3);
|
||||
FfiConverterString.write(dataStream, value.reason);
|
||||
return;
|
||||
}
|
||||
throw new Error("Unknown TabsApiError variant");
|
||||
}
|
||||
|
||||
static errorClass = TabsApiError;
|
||||
}
|
||||
|
||||
// Export the FFIConverter object to make external types work.
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
[fixture_callbacks.receiver_thread]
|
||||
default = "worker"
|
||||
main = [
|
||||
"log_even_numbers_main_thread",
|
||||
]
|
|
@ -5,7 +5,10 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
var EXPORTED_SYMBOLS = [];
|
||||
// Objects intended to be used in the unit tests
|
||||
var UnitTestObjs = {};
|
||||
|
||||
var EXPORTED_SYMBOLS = ["UnitTestObjs"];
|
||||
|
||||
// Write/Read data to/from an ArrayBuffer
|
||||
class ArrayBufferDataStream {
|
||||
|
@ -103,7 +106,6 @@ class ArrayBufferDataStream {
|
|||
this.pos += 8;
|
||||
}
|
||||
|
||||
|
||||
readFloat32() {
|
||||
let rv = this.dataView.getFloat32(this.pos);
|
||||
this.pos += 4;
|
||||
|
@ -180,6 +182,10 @@ class UniFFIError {
|
|||
constructor(message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
toString() {
|
||||
return `UniFFIError: ${this.message}`
|
||||
}
|
||||
}
|
||||
|
||||
class UniFFIInternalError extends UniFFIError {}
|
||||
|
@ -310,6 +316,9 @@ class IntegerOverflow extends ArithmeticError {
|
|||
super(...params);
|
||||
this.message = message;
|
||||
}
|
||||
toString() {
|
||||
return `IntegerOverflow: ${super.toString()}`
|
||||
}
|
||||
}
|
||||
EXPORTED_SYMBOLS.push("IntegerOverflow");
|
||||
|
||||
|
@ -319,9 +328,26 @@ class FfiConverterTypeArithmeticError extends FfiConverterArrayBuffer {
|
|||
case 1:
|
||||
return new IntegerOverflow(FfiConverterString.read(dataStream));
|
||||
default:
|
||||
return new Error("Unknown ArithmeticError variant");
|
||||
throw new Error("Unknown ArithmeticError variant");
|
||||
}
|
||||
}
|
||||
static computeSize(value) {
|
||||
// Size of the Int indicating the variant
|
||||
let totalSize = 4;
|
||||
if (value instanceof IntegerOverflow) {
|
||||
return totalSize;
|
||||
}
|
||||
throw new Error("Unknown ArithmeticError variant");
|
||||
}
|
||||
static write(dataStream, value) {
|
||||
if (value instanceof IntegerOverflow) {
|
||||
dataStream.writeInt32(1);
|
||||
return;
|
||||
}
|
||||
throw new Error("Unknown ArithmeticError variant");
|
||||
}
|
||||
|
||||
static errorClass = ArithmeticError;
|
||||
}
|
||||
|
||||
// Export the FFIConverter object to make external types work.
|
||||
|
@ -332,85 +358,85 @@ EXPORTED_SYMBOLS.push("FfiConverterTypeArithmeticError");
|
|||
|
||||
function add(a,b) {
|
||||
|
||||
const liftResult = (result) => FfiConverterU64.lift(result);
|
||||
const liftError = (data) => FfiConverterTypeArithmeticError.lift(data);
|
||||
const functionCall = () => {
|
||||
FfiConverterU64.checkType("a", a);
|
||||
FfiConverterU64.checkType("b", b);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
22, // arithmetic:arithmetic_906c_add
|
||||
FfiConverterU64.lower(a),
|
||||
FfiConverterU64.lower(b),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
const liftResult = (result) => FfiConverterU64.lift(result);
|
||||
const liftError = (data) => FfiConverterTypeArithmeticError.lift(data);
|
||||
const functionCall = () => {
|
||||
FfiConverterU64.checkType("a", a);
|
||||
FfiConverterU64.checkType("b", b);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
22, // arithmetic:arithmetic_906c_add
|
||||
FfiConverterU64.lower(a),
|
||||
FfiConverterU64.lower(b),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
|
||||
EXPORTED_SYMBOLS.push("add");
|
||||
function sub(a,b) {
|
||||
|
||||
const liftResult = (result) => FfiConverterU64.lift(result);
|
||||
const liftError = (data) => FfiConverterTypeArithmeticError.lift(data);
|
||||
const functionCall = () => {
|
||||
FfiConverterU64.checkType("a", a);
|
||||
FfiConverterU64.checkType("b", b);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
23, // arithmetic:arithmetic_906c_sub
|
||||
FfiConverterU64.lower(a),
|
||||
FfiConverterU64.lower(b),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
const liftResult = (result) => FfiConverterU64.lift(result);
|
||||
const liftError = (data) => FfiConverterTypeArithmeticError.lift(data);
|
||||
const functionCall = () => {
|
||||
FfiConverterU64.checkType("a", a);
|
||||
FfiConverterU64.checkType("b", b);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
23, // arithmetic:arithmetic_906c_sub
|
||||
FfiConverterU64.lower(a),
|
||||
FfiConverterU64.lower(b),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
|
||||
EXPORTED_SYMBOLS.push("sub");
|
||||
function div(dividend,divisor) {
|
||||
|
||||
const liftResult = (result) => FfiConverterU64.lift(result);
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
FfiConverterU64.checkType("dividend", dividend);
|
||||
FfiConverterU64.checkType("divisor", divisor);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
24, // arithmetic:arithmetic_906c_div
|
||||
FfiConverterU64.lower(dividend),
|
||||
FfiConverterU64.lower(divisor),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
const liftResult = (result) => FfiConverterU64.lift(result);
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
FfiConverterU64.checkType("dividend", dividend);
|
||||
FfiConverterU64.checkType("divisor", divisor);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
24, // arithmetic:arithmetic_906c_div
|
||||
FfiConverterU64.lower(dividend),
|
||||
FfiConverterU64.lower(divisor),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
|
||||
EXPORTED_SYMBOLS.push("div");
|
||||
function equal(a,b) {
|
||||
|
||||
const liftResult = (result) => FfiConverterBool.lift(result);
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
FfiConverterU64.checkType("a", a);
|
||||
FfiConverterU64.checkType("b", b);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
25, // arithmetic:arithmetic_906c_equal
|
||||
FfiConverterU64.lower(a),
|
||||
FfiConverterU64.lower(b),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
const liftResult = (result) => FfiConverterBool.lift(result);
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
FfiConverterU64.checkType("a", a);
|
||||
FfiConverterU64.checkType("b", b);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
25, // arithmetic:arithmetic_906c_equal
|
||||
FfiConverterU64.lower(a),
|
||||
FfiConverterU64.lower(b),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
|
||||
EXPORTED_SYMBOLS.push("equal");
|
||||
|
|
|
@ -5,7 +5,10 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
var EXPORTED_SYMBOLS = [];
|
||||
// Objects intended to be used in the unit tests
|
||||
var UnitTestObjs = {};
|
||||
|
||||
var EXPORTED_SYMBOLS = ["UnitTestObjs"];
|
||||
|
||||
// Write/Read data to/from an ArrayBuffer
|
||||
class ArrayBufferDataStream {
|
||||
|
@ -103,7 +106,6 @@ class ArrayBufferDataStream {
|
|||
this.pos += 8;
|
||||
}
|
||||
|
||||
|
||||
readFloat32() {
|
||||
let rv = this.dataView.getFloat32(this.pos);
|
||||
this.pos += 4;
|
||||
|
@ -180,6 +182,10 @@ class UniFFIError {
|
|||
constructor(message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
toString() {
|
||||
return `UniFFIError: ${this.message}`
|
||||
}
|
||||
}
|
||||
|
||||
class UniFFIInternalError extends UniFFIError {}
|
||||
|
@ -417,20 +423,20 @@ EXPORTED_SYMBOLS.push("FfiConverterTypeUrl");
|
|||
|
||||
function getCustomTypesDemo(demo) {
|
||||
|
||||
const liftResult = (result) => FfiConverterTypeCustomTypesDemo.lift(result);
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
FfiConverterOptionalTypeCustomTypesDemo.checkType("demo", demo);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
107, // custom_types:custom_types_8ecd_get_custom_types_demo
|
||||
FfiConverterOptionalTypeCustomTypesDemo.lower(demo),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
const liftResult = (result) => FfiConverterTypeCustomTypesDemo.lift(result);
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
FfiConverterOptionalTypeCustomTypesDemo.checkType("demo", demo);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
109, // custom_types:custom_types_8ecd_get_custom_types_demo
|
||||
FfiConverterOptionalTypeCustomTypesDemo.lower(demo),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
|
||||
EXPORTED_SYMBOLS.push("getCustomTypesDemo");
|
||||
|
|
|
@ -5,7 +5,10 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
var EXPORTED_SYMBOLS = [];
|
||||
// Objects intended to be used in the unit tests
|
||||
var UnitTestObjs = {};
|
||||
|
||||
var EXPORTED_SYMBOLS = ["UnitTestObjs"];
|
||||
|
||||
// Write/Read data to/from an ArrayBuffer
|
||||
class ArrayBufferDataStream {
|
||||
|
@ -103,7 +106,6 @@ class ArrayBufferDataStream {
|
|||
this.pos += 8;
|
||||
}
|
||||
|
||||
|
||||
readFloat32() {
|
||||
let rv = this.dataView.getFloat32(this.pos);
|
||||
this.pos += 4;
|
||||
|
@ -180,6 +182,10 @@ class UniFFIError {
|
|||
constructor(message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
toString() {
|
||||
return `UniFFIError: ${this.message}`
|
||||
}
|
||||
}
|
||||
|
||||
class UniFFIInternalError extends UniFFIError {}
|
||||
|
@ -324,20 +330,20 @@ EXPORTED_SYMBOLS.push("FfiConverterTypePoint");
|
|||
|
||||
function gradient(value) {
|
||||
|
||||
const liftResult = (result) => FfiConverterF64.lift(result);
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
FfiConverterOptionalTypeLine.checkType("value", value);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
108, // external_types:external_types_54cc_gradient
|
||||
FfiConverterOptionalTypeLine.lower(value),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
const liftResult = (result) => FfiConverterF64.lift(result);
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
FfiConverterOptionalTypeLine.checkType("value", value);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
110, // external_types:external_types_54cc_gradient
|
||||
FfiConverterOptionalTypeLine.lower(value),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
|
||||
EXPORTED_SYMBOLS.push("gradient");
|
||||
|
|
|
@ -0,0 +1,598 @@
|
|||
// This file was autogenerated by the `uniffi-bindgen-gecko-js` crate.
|
||||
// Trust me, you don't want to mess with it!
|
||||
|
||||
|
||||
|
||||
"use strict";
|
||||
|
||||
// Objects intended to be used in the unit tests
|
||||
var UnitTestObjs = {};
|
||||
|
||||
var EXPORTED_SYMBOLS = ["UnitTestObjs"];
|
||||
|
||||
// Write/Read data to/from an ArrayBuffer
|
||||
class ArrayBufferDataStream {
|
||||
constructor(arrayBuffer) {
|
||||
this.dataView = new DataView(arrayBuffer);
|
||||
this.pos = 0;
|
||||
}
|
||||
|
||||
readUint8() {
|
||||
let rv = this.dataView.getUint8(this.pos);
|
||||
this.pos += 1;
|
||||
return rv;
|
||||
}
|
||||
|
||||
writeUint8(value) {
|
||||
this.dataView.setUint8(this.pos, value);
|
||||
this.pos += 1;
|
||||
}
|
||||
|
||||
readUint16() {
|
||||
let rv = this.dataView.getUint16(this.pos);
|
||||
this.pos += 2;
|
||||
return rv;
|
||||
}
|
||||
|
||||
writeUint16(value) {
|
||||
this.dataView.setUint16(this.pos, value);
|
||||
this.pos += 2;
|
||||
}
|
||||
|
||||
readUint32() {
|
||||
let rv = this.dataView.getUint32(this.pos);
|
||||
this.pos += 4;
|
||||
return rv;
|
||||
}
|
||||
|
||||
writeUint32(value) {
|
||||
this.dataView.setUint32(this.pos, value);
|
||||
this.pos += 4;
|
||||
}
|
||||
|
||||
readUint64() {
|
||||
let rv = this.dataView.getBigUint64(this.pos);
|
||||
this.pos += 8;
|
||||
return Number(rv);
|
||||
}
|
||||
|
||||
writeUint64(value) {
|
||||
this.dataView.setBigUint64(this.pos, BigInt(value));
|
||||
this.pos += 8;
|
||||
}
|
||||
|
||||
|
||||
readInt8() {
|
||||
let rv = this.dataView.getInt8(this.pos);
|
||||
this.pos += 1;
|
||||
return rv;
|
||||
}
|
||||
|
||||
writeInt8(value) {
|
||||
this.dataView.setInt8(this.pos, value);
|
||||
this.pos += 1;
|
||||
}
|
||||
|
||||
readInt16() {
|
||||
let rv = this.dataView.getInt16(this.pos);
|
||||
this.pos += 2;
|
||||
return rv;
|
||||
}
|
||||
|
||||
writeInt16(value) {
|
||||
this.dataView.setInt16(this.pos, value);
|
||||
this.pos += 2;
|
||||
}
|
||||
|
||||
readInt32() {
|
||||
let rv = this.dataView.getInt32(this.pos);
|
||||
this.pos += 4;
|
||||
return rv;
|
||||
}
|
||||
|
||||
writeInt32(value) {
|
||||
this.dataView.setInt32(this.pos, value);
|
||||
this.pos += 4;
|
||||
}
|
||||
|
||||
readInt64() {
|
||||
let rv = this.dataView.getBigInt64(this.pos);
|
||||
this.pos += 8;
|
||||
return Number(rv);
|
||||
}
|
||||
|
||||
writeInt64(value) {
|
||||
this.dataView.setBigInt64(this.pos, BigInt(value));
|
||||
this.pos += 8;
|
||||
}
|
||||
|
||||
readFloat32() {
|
||||
let rv = this.dataView.getFloat32(this.pos);
|
||||
this.pos += 4;
|
||||
return rv;
|
||||
}
|
||||
|
||||
writeFloat32(value) {
|
||||
this.dataView.setFloat32(this.pos, value);
|
||||
this.pos += 4;
|
||||
}
|
||||
|
||||
readFloat64() {
|
||||
let rv = this.dataView.getFloat64(this.pos);
|
||||
this.pos += 8;
|
||||
return rv;
|
||||
}
|
||||
|
||||
writeFloat64(value) {
|
||||
this.dataView.setFloat64(this.pos, value);
|
||||
this.pos += 8;
|
||||
}
|
||||
|
||||
|
||||
writeString(value) {
|
||||
const encoder = new TextEncoder();
|
||||
// Note: in order to efficiently write this data, we first write the
|
||||
// string data, reserving 4 bytes for the size.
|
||||
const dest = new Uint8Array(this.dataView.buffer, this.pos + 4);
|
||||
const encodeResult = encoder.encodeInto(value, dest);
|
||||
if (encodeResult.read != value.length) {
|
||||
throw new UniFFIError(
|
||||
"writeString: out of space when writing to ArrayBuffer. Did the computeSize() method returned the wrong result?"
|
||||
);
|
||||
}
|
||||
const size = encodeResult.written;
|
||||
// Next, go back and write the size before the string data
|
||||
this.dataView.setUint32(this.pos, size);
|
||||
// Finally, advance our position past both the size and string data
|
||||
this.pos += size + 4;
|
||||
}
|
||||
|
||||
readString() {
|
||||
const decoder = new TextDecoder();
|
||||
const size = this.readUint32();
|
||||
const source = new Uint8Array(this.dataView.buffer, this.pos, size)
|
||||
const value = decoder.decode(source);
|
||||
this.pos += size;
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
function handleRustResult(result, liftCallback, liftErrCallback) {
|
||||
switch (result.code) {
|
||||
case "success":
|
||||
return liftCallback(result.data);
|
||||
|
||||
case "error":
|
||||
throw liftErrCallback(result.data);
|
||||
|
||||
case "internal-error":
|
||||
let message = result.internalErrorMessage;
|
||||
if (message) {
|
||||
throw new UniFFIInternalError(message);
|
||||
} else {
|
||||
throw new UniFFIInternalError("Unknown error");
|
||||
}
|
||||
|
||||
default:
|
||||
throw new UniFFIError(`Unexpected status code: ${result.code}`);
|
||||
}
|
||||
}
|
||||
|
||||
class UniFFIError {
|
||||
constructor(message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
toString() {
|
||||
return `UniFFIError: ${this.message}`
|
||||
}
|
||||
}
|
||||
|
||||
class UniFFIInternalError extends UniFFIError {}
|
||||
|
||||
// Base class for FFI converters
|
||||
class FfiConverter {
|
||||
static checkType(name, value) {
|
||||
if (value === undefined ) {
|
||||
throw TypeError(`${name} is undefined`);
|
||||
}
|
||||
if (value === null ) {
|
||||
throw TypeError(`${name} is null`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Base class for FFI converters that lift/lower by reading/writing to an ArrayBuffer
|
||||
class FfiConverterArrayBuffer extends FfiConverter {
|
||||
static lift(buf) {
|
||||
return this.read(new ArrayBufferDataStream(buf));
|
||||
}
|
||||
|
||||
static lower(value) {
|
||||
const buf = new ArrayBuffer(this.computeSize(value));
|
||||
const dataStream = new ArrayBufferDataStream(buf);
|
||||
this.write(dataStream, value);
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
|
||||
// Symbols that are used to ensure that Object constructors
|
||||
// can only be used with a proper UniFFI pointer
|
||||
const uniffiObjectPtr = Symbol("uniffiObjectPtr");
|
||||
const constructUniffiObject = Symbol("constructUniffiObject");
|
||||
|
||||
|
||||
/**
|
||||
* Handler for a single UniFFI CallbackInterface
|
||||
*
|
||||
* This class stores objects that implement a callback interface in a handle
|
||||
* map, allowing them to be referenced by the Rust code using an integer
|
||||
* handle.
|
||||
*
|
||||
* While the callback object is stored in the map, it allows the Rust code to
|
||||
* call methods on the object using the callback object handle, a method id,
|
||||
* and an ArrayBuffer packed with the method arguments.
|
||||
*
|
||||
* When the Rust code drops its reference, it sends a call with the methodId=0,
|
||||
* which causes callback object to be removed from the map.
|
||||
*/
|
||||
class UniFFICallbackHandler {
|
||||
#name;
|
||||
#interfaceId;
|
||||
#handleCounter;
|
||||
#handleMap;
|
||||
#methodHandlers;
|
||||
#allowNewCallbacks
|
||||
|
||||
/**
|
||||
* Create a UniFFICallbackHandler
|
||||
* @param {string} name - Human-friendly name for this callback interface
|
||||
* @param {int} interfaceId - Interface ID for this CallbackInterface.
|
||||
* @param {UniFFICallbackMethodHandler[]} methodHandlers -- UniFFICallbackHandler for each method, in the same order as the UDL file
|
||||
*/
|
||||
constructor(name, interfaceId, methodHandlers) {
|
||||
this.#name = name;
|
||||
this.#interfaceId = interfaceId;
|
||||
this.#handleCounter = 0;
|
||||
this.#handleMap = new Map();
|
||||
this.#methodHandlers = methodHandlers;
|
||||
this.#allowNewCallbacks = true;
|
||||
|
||||
UniFFIScaffolding.registerCallbackHandler(this.#interfaceId, this.invokeCallback.bind(this));
|
||||
Services.obs.addObserver(this, "xpcom-shutdown");
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a callback object in the handle map and return the handle
|
||||
*
|
||||
* @param {obj} callbackObj - Object that implements the callback interface
|
||||
* @returns {int} - Handle for this callback object, this is what gets passed back to Rust.
|
||||
*/
|
||||
storeCallbackObj(callbackObj) {
|
||||
if (!this.#allowNewCallbacks) {
|
||||
throw new UniFFIError(`No new callbacks allowed for ${this.#name}`);
|
||||
}
|
||||
const handle = this.#handleCounter;
|
||||
this.#handleCounter += 1;
|
||||
this.#handleMap.set(handle, new UniFFICallbackHandleMapEntry(callbackObj, Components.stack.caller.formattedStack.trim()));
|
||||
return handle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a previously stored callback object
|
||||
*
|
||||
* @param {int} handle - Callback object handle, returned from `storeCallbackObj()`
|
||||
* @returns {obj} - Callback object
|
||||
*/
|
||||
getCallbackObj(handle) {
|
||||
return this.#handleMap.get(handle).callbackObj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if new callbacks are allowed for this handler
|
||||
*
|
||||
* This is called with false during shutdown to ensure the callback maps don't
|
||||
* prevent JS objects from being GCed.
|
||||
*/
|
||||
setAllowNewCallbacks(allow) {
|
||||
this.#allowNewCallbacks = allow
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that no callbacks are currently registered
|
||||
*
|
||||
* If there are callbacks registered a UniFFIError will be thrown. This is
|
||||
* called during shutdown to generate an alert if there are leaked callback
|
||||
* interfaces.
|
||||
*/
|
||||
assertNoRegisteredCallbacks() {
|
||||
if (this.#handleMap.size > 0) {
|
||||
const entry = this.#handleMap.values().next().value;
|
||||
throw new UniFFIError(`UniFFI interface ${this.#name} has ${this.#handleMap.size} registered callbacks at xpcom-shutdown. This likely indicates a UniFFI callback leak.\nStack trace for the first leaked callback:\n${entry.stackTrace}.`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke a method on a stored callback object
|
||||
* @param {int} handle - Object handle
|
||||
* @param {int} methodId - Method identifier. This the 1-based index of
|
||||
* the method from the UDL file. 0 is the special drop method, which
|
||||
* removes the callback object from the handle map.
|
||||
* @param {ArrayBuffer} argsArrayBuffer - Arguments to pass to the method, packed in an ArrayBuffer
|
||||
*/
|
||||
invokeCallback(handle, methodId, argsArrayBuffer) {
|
||||
try {
|
||||
this.#invokeCallbackInner(handle, methodId, argsArrayBuffer);
|
||||
} catch (e) {
|
||||
console.error(`internal error invoking callback: ${e}`)
|
||||
}
|
||||
}
|
||||
|
||||
#invokeCallbackInner(handle, methodId, argsArrayBuffer) {
|
||||
const callbackObj = this.getCallbackObj(handle);
|
||||
if (callbackObj === undefined) {
|
||||
throw new UniFFIError(`${this.#name}: invalid callback handle id: ${handle}`);
|
||||
}
|
||||
|
||||
// Special-cased drop method, remove the object from the handle map and
|
||||
// return an empty array buffer
|
||||
if (methodId == 0) {
|
||||
this.#handleMap.delete(handle);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the method data, converting from 1-based indexing
|
||||
const methodHandler = this.#methodHandlers[methodId - 1];
|
||||
if (methodHandler === undefined) {
|
||||
throw new UniFFIError(`${this.#name}: invalid method id: ${methodId}`)
|
||||
}
|
||||
|
||||
methodHandler.call(callbackObj, argsArrayBuffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* xpcom-shutdown observer method
|
||||
*
|
||||
* This handles:
|
||||
* - Deregistering ourselves as the UniFFI callback handler
|
||||
* - Checks for any leftover stored callbacks which indicate memory leaks
|
||||
*/
|
||||
observe(aSubject, aTopic, aData) {
|
||||
if (aTopic == "xpcom-shutdown") {
|
||||
try {
|
||||
this.setAllowNewCallbacks(false);
|
||||
this.assertNoRegisteredCallbacks();
|
||||
UniFFIScaffolding.deregisterCallbackHandler(this.#interfaceId);
|
||||
} catch (ex) {
|
||||
console.error(`UniFFI Callback interface error during xpcom-shutdown: ${ex}`);
|
||||
Cc["@mozilla.org/xpcom/debug;1"]
|
||||
.getService(Ci.nsIDebug2)
|
||||
.abort(ex.filename, ex.lineNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles calling a single method for a callback interface
|
||||
*/
|
||||
class UniFFICallbackMethodHandler {
|
||||
#name;
|
||||
#argsConverters;
|
||||
|
||||
/**
|
||||
* Create a UniFFICallbackMethodHandler
|
||||
|
||||
* @param {string} name -- Name of the method to call on the callback object
|
||||
* @param {FfiConverter[]} argsConverters - FfiConverter for each argument type
|
||||
*/
|
||||
constructor(name, argsConverters) {
|
||||
this.#name = name;
|
||||
this.#argsConverters = argsConverters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke the method
|
||||
*
|
||||
* @param {obj} callbackObj -- Object implementing the callback interface for this method
|
||||
* @param {ArrayBuffer} argsArrayBuffer -- Arguments for the method, packed in an ArrayBuffer
|
||||
*/
|
||||
call(callbackObj, argsArrayBuffer) {
|
||||
const argsStream = new ArrayBufferDataStream(argsArrayBuffer);
|
||||
const args = this.#argsConverters.map(converter => converter.read(argsStream));
|
||||
callbackObj[this.#name](...args);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* UniFFICallbackHandler.handleMap entry
|
||||
*
|
||||
* @property callbackObj - Callback object, this must implement the callback interface.
|
||||
* @property {string} stackTrace - Stack trace from when the callback object was registered. This is used to proved extra context when debugging leaked callback objects.
|
||||
*/
|
||||
class UniFFICallbackHandleMapEntry {
|
||||
constructor(callbackObj, stackTrace) {
|
||||
this.callbackObj = callbackObj;
|
||||
this.stackTrace = stackTrace
|
||||
}
|
||||
}
|
||||
|
||||
class FfiConverterI32 extends FfiConverter {
|
||||
static checkType(name, value) {
|
||||
super.checkType(name, value);
|
||||
if (!Number.isInteger(value)) {
|
||||
throw TypeError(`${name} is not an integer(${value})`);
|
||||
}
|
||||
if (value < -2147483648 || value > 2147483647) {
|
||||
throw TypeError(`${name} exceeds the I32 bounds (${value})`);
|
||||
}
|
||||
}
|
||||
static computeSize() {
|
||||
return 4;
|
||||
}
|
||||
static lift(value) {
|
||||
return value;
|
||||
}
|
||||
static lower(value) {
|
||||
return value;
|
||||
}
|
||||
static write(dataStream, value) {
|
||||
dataStream.writeInt32(value)
|
||||
}
|
||||
static read(dataStream) {
|
||||
return dataStream.readInt32()
|
||||
}
|
||||
}
|
||||
|
||||
// Export the FFIConverter object to make external types work.
|
||||
EXPORTED_SYMBOLS.push("FfiConverterI32");
|
||||
|
||||
class FfiConverterString extends FfiConverter {
|
||||
static lift(buf) {
|
||||
const decoder = new TextDecoder();
|
||||
const utf8Arr = new Uint8Array(buf);
|
||||
return decoder.decode(utf8Arr);
|
||||
}
|
||||
static lower(value) {
|
||||
const encoder = new TextEncoder();
|
||||
return encoder.encode(value).buffer;
|
||||
}
|
||||
|
||||
static write(dataStream, value) {
|
||||
dataStream.writeString(value);
|
||||
}
|
||||
|
||||
static read(dataStream) {
|
||||
return dataStream.readString();
|
||||
}
|
||||
|
||||
static computeSize(value) {
|
||||
const encoder = new TextEncoder();
|
||||
return 4 + encoder.encode(value).length
|
||||
}
|
||||
}
|
||||
|
||||
// Export the FFIConverter object to make external types work.
|
||||
EXPORTED_SYMBOLS.push("FfiConverterString");
|
||||
|
||||
|
||||
class FfiConverterCallbackInterfaceLogger extends FfiConverter {
|
||||
static lower(callbackObj) {
|
||||
return callbackHandlerLogger.storeCallbackObj(callbackObj)
|
||||
}
|
||||
|
||||
static lift(handleId) {
|
||||
return callbackHandlerLogger.getCallbackObj(handleId)
|
||||
}
|
||||
|
||||
static read(dataStream) {
|
||||
return this.lift(dataStream.readInt64())
|
||||
}
|
||||
|
||||
static write(dataStream, callbackObj) {
|
||||
dataStream.writeInt64(this.lower(callbackObj))
|
||||
}
|
||||
|
||||
static computeSize(callbackObj) {
|
||||
return 8;
|
||||
}
|
||||
}
|
||||
|
||||
// Export the FFIConverter object to make external types work.
|
||||
EXPORTED_SYMBOLS.push("FfiConverterCallbackInterfaceLogger");
|
||||
|
||||
class FfiConverterSequencei32 extends FfiConverterArrayBuffer {
|
||||
static read(dataStream) {
|
||||
const len = dataStream.readInt32();
|
||||
const arr = [];
|
||||
for (let i = 0; i < len; i++) {
|
||||
arr.push(FfiConverterI32.read(dataStream));
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
static write(dataStream, value) {
|
||||
dataStream.writeInt32(value.length);
|
||||
value.forEach((innerValue) => {
|
||||
FfiConverterI32.write(dataStream, innerValue);
|
||||
})
|
||||
}
|
||||
|
||||
static computeSize(value) {
|
||||
// The size of the length
|
||||
let size = 4;
|
||||
for (const innerValue of value) {
|
||||
size += FfiConverterI32.computeSize(innerValue);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
// Export the FFIConverter object to make external types work.
|
||||
EXPORTED_SYMBOLS.push("FfiConverterSequencei32");
|
||||
|
||||
|
||||
// Define callback interface handlers, this must come after the type loop since they reference the FfiConverters defined above.
|
||||
|
||||
const callbackHandlerLogger = new UniFFICallbackHandler(
|
||||
"fixture_callbacks:Logger",
|
||||
0,
|
||||
[
|
||||
new UniFFICallbackMethodHandler(
|
||||
"log",
|
||||
[
|
||||
FfiConverterString,
|
||||
],
|
||||
),
|
||||
new UniFFICallbackMethodHandler(
|
||||
"finished",
|
||||
[
|
||||
],
|
||||
),
|
||||
]
|
||||
);
|
||||
|
||||
// Allow the shutdown-related functionality to be tested in the unit tests
|
||||
UnitTestObjs.callbackHandlerLogger = callbackHandlerLogger;
|
||||
|
||||
|
||||
|
||||
|
||||
function logEvenNumbers(logger,items) {
|
||||
|
||||
const liftResult = (result) => undefined;
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
FfiConverterCallbackInterfaceLogger.checkType("logger", logger);
|
||||
FfiConverterSequencei32.checkType("items", items);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
107, // fixture_callbacks:fixture_callbacks_1107_log_even_numbers
|
||||
FfiConverterCallbackInterfaceLogger.lower(logger),
|
||||
FfiConverterSequencei32.lower(items),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
|
||||
EXPORTED_SYMBOLS.push("logEvenNumbers");
|
||||
function logEvenNumbersMainThread(logger,items) {
|
||||
|
||||
const liftResult = (result) => undefined;
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
FfiConverterCallbackInterfaceLogger.checkType("logger", logger);
|
||||
FfiConverterSequencei32.checkType("items", items);
|
||||
return UniFFIScaffolding.callSync(
|
||||
108, // fixture_callbacks:fixture_callbacks_1107_log_even_numbers_main_thread
|
||||
FfiConverterCallbackInterfaceLogger.lower(logger),
|
||||
FfiConverterSequencei32.lower(items),
|
||||
)
|
||||
}
|
||||
return handleRustResult(functionCall(), liftResult, liftError);
|
||||
}
|
||||
|
||||
EXPORTED_SYMBOLS.push("logEvenNumbersMainThread");
|
|
@ -5,7 +5,10 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
var EXPORTED_SYMBOLS = [];
|
||||
// Objects intended to be used in the unit tests
|
||||
var UnitTestObjs = {};
|
||||
|
||||
var EXPORTED_SYMBOLS = ["UnitTestObjs"];
|
||||
|
||||
// Write/Read data to/from an ArrayBuffer
|
||||
class ArrayBufferDataStream {
|
||||
|
@ -103,7 +106,6 @@ class ArrayBufferDataStream {
|
|||
this.pos += 8;
|
||||
}
|
||||
|
||||
|
||||
readFloat32() {
|
||||
let rv = this.dataView.getFloat32(this.pos);
|
||||
this.pos += 4;
|
||||
|
@ -180,6 +182,10 @@ class UniFFIError {
|
|||
constructor(message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
toString() {
|
||||
return `UniFFIError: ${this.message}`
|
||||
}
|
||||
}
|
||||
|
||||
class UniFFIInternalError extends UniFFIError {}
|
||||
|
@ -406,41 +412,41 @@ EXPORTED_SYMBOLS.push("FfiConverterOptionalTypePoint");
|
|||
|
||||
function gradient(ln) {
|
||||
|
||||
const liftResult = (result) => FfiConverterF64.lift(result);
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
FfiConverterTypeLine.checkType("ln", ln);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
20, // geometry:geometry_1cce_gradient
|
||||
FfiConverterTypeLine.lower(ln),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
const liftResult = (result) => FfiConverterF64.lift(result);
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
FfiConverterTypeLine.checkType("ln", ln);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
20, // geometry:geometry_1cce_gradient
|
||||
FfiConverterTypeLine.lower(ln),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
|
||||
EXPORTED_SYMBOLS.push("gradient");
|
||||
function intersection(ln1,ln2) {
|
||||
|
||||
const liftResult = (result) => FfiConverterOptionalTypePoint.lift(result);
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
FfiConverterTypeLine.checkType("ln1", ln1);
|
||||
FfiConverterTypeLine.checkType("ln2", ln2);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
21, // geometry:geometry_1cce_intersection
|
||||
FfiConverterTypeLine.lower(ln1),
|
||||
FfiConverterTypeLine.lower(ln2),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
const liftResult = (result) => FfiConverterOptionalTypePoint.lift(result);
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
FfiConverterTypeLine.checkType("ln1", ln1);
|
||||
FfiConverterTypeLine.checkType("ln2", ln2);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
21, // geometry:geometry_1cce_intersection
|
||||
FfiConverterTypeLine.lower(ln1),
|
||||
FfiConverterTypeLine.lower(ln2),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
|
||||
EXPORTED_SYMBOLS.push("intersection");
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -5,7 +5,10 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
var EXPORTED_SYMBOLS = [];
|
||||
// Objects intended to be used in the unit tests
|
||||
var UnitTestObjs = {};
|
||||
|
||||
var EXPORTED_SYMBOLS = ["UnitTestObjs"];
|
||||
|
||||
// Write/Read data to/from an ArrayBuffer
|
||||
class ArrayBufferDataStream {
|
||||
|
@ -103,7 +106,6 @@ class ArrayBufferDataStream {
|
|||
this.pos += 8;
|
||||
}
|
||||
|
||||
|
||||
readFloat32() {
|
||||
let rv = this.dataView.getFloat32(this.pos);
|
||||
this.pos += 4;
|
||||
|
@ -200,6 +202,10 @@ class UniFFIError {
|
|||
constructor(message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
toString() {
|
||||
return `UniFFIError: ${this.message}`
|
||||
}
|
||||
}
|
||||
|
||||
class UniFFIInternalError extends UniFFIError {}
|
||||
|
@ -304,20 +310,20 @@ class Sprite {
|
|||
* to a newly constructed Sprite
|
||||
*/
|
||||
static init(initialPosition) {
|
||||
const liftResult = (result) => FfiConverterTypeSprite.lift(result);
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
FfiConverterOptionalTypePoint.checkType("initialPosition", initialPosition);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
86, // sprites:sprites_accb_Sprite_new
|
||||
FfiConverterOptionalTypePoint.lower(initialPosition),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}}
|
||||
const liftResult = (result) => FfiConverterTypeSprite.lift(result);
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
FfiConverterOptionalTypePoint.checkType("initialPosition", initialPosition);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
86, // sprites:sprites_accb_Sprite_new
|
||||
FfiConverterOptionalTypePoint.lower(initialPosition),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}}
|
||||
/**
|
||||
* An async constructor for Sprite.
|
||||
*
|
||||
|
@ -325,68 +331,74 @@ class Sprite {
|
|||
* to a newly constructed Sprite
|
||||
*/
|
||||
static newRelativeTo(reference,direction) {
|
||||
const liftResult = (result) => FfiConverterTypeSprite.lift(result);
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
FfiConverterTypePoint.checkType("reference", reference);
|
||||
FfiConverterTypeVector.checkType("direction", direction);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
87, // sprites:sprites_accb_Sprite_new_relative_to
|
||||
FfiConverterTypePoint.lower(reference),
|
||||
FfiConverterTypeVector.lower(direction),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}}
|
||||
const liftResult = (result) => FfiConverterTypeSprite.lift(result);
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
FfiConverterTypePoint.checkType("reference", reference);
|
||||
FfiConverterTypeVector.checkType("direction", direction);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
87, // sprites:sprites_accb_Sprite_new_relative_to
|
||||
FfiConverterTypePoint.lower(reference),
|
||||
FfiConverterTypeVector.lower(direction),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}}
|
||||
|
||||
getPosition() {
|
||||
const liftResult = (result) => FfiConverterTypePoint.lift(result);
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
return UniFFIScaffolding.callAsync(
|
||||
88, // sprites:sprites_accb_Sprite_get_position
|
||||
FfiConverterTypeSprite.lower(this),
|
||||
)
|
||||
const liftResult = (result) => FfiConverterTypePoint.lift(result);
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
return UniFFIScaffolding.callAsync(
|
||||
88, // sprites:sprites_accb_Sprite_get_position
|
||||
FfiConverterTypeSprite.lower(this),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}}
|
||||
|
||||
moveTo(position) {
|
||||
const liftResult = (result) => undefined;
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
FfiConverterTypePoint.checkType("position", position);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
89, // sprites:sprites_accb_Sprite_move_to
|
||||
FfiConverterTypeSprite.lower(this),
|
||||
FfiConverterTypePoint.lower(position),
|
||||
)
|
||||
const liftResult = (result) => undefined;
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
FfiConverterTypePoint.checkType("position", position);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
89, // sprites:sprites_accb_Sprite_move_to
|
||||
FfiConverterTypeSprite.lower(this),
|
||||
FfiConverterTypePoint.lower(position),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}}
|
||||
|
||||
moveBy(direction) {
|
||||
const liftResult = (result) => undefined;
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
FfiConverterTypeVector.checkType("direction", direction);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
90, // sprites:sprites_accb_Sprite_move_by
|
||||
FfiConverterTypeSprite.lower(this),
|
||||
FfiConverterTypeVector.lower(direction),
|
||||
)
|
||||
const liftResult = (result) => undefined;
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
FfiConverterTypeVector.checkType("direction", direction);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
90, // sprites:sprites_accb_Sprite_move_by
|
||||
FfiConverterTypeSprite.lower(this),
|
||||
FfiConverterTypeVector.lower(direction),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}}
|
||||
|
||||
}
|
||||
|
||||
|
@ -561,22 +573,22 @@ EXPORTED_SYMBOLS.push("FfiConverterOptionalTypePoint");
|
|||
|
||||
function translate(position,direction) {
|
||||
|
||||
const liftResult = (result) => FfiConverterTypePoint.lift(result);
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
FfiConverterTypePoint.checkType("position", position);
|
||||
FfiConverterTypeVector.checkType("direction", direction);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
91, // sprites:sprites_accb_translate
|
||||
FfiConverterTypePoint.lower(position),
|
||||
FfiConverterTypeVector.lower(direction),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
const liftResult = (result) => FfiConverterTypePoint.lift(result);
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
FfiConverterTypePoint.checkType("position", position);
|
||||
FfiConverterTypeVector.checkType("direction", direction);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
91, // sprites:sprites_accb_translate
|
||||
FfiConverterTypePoint.lower(position),
|
||||
FfiConverterTypeVector.lower(direction),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
|
||||
EXPORTED_SYMBOLS.push("translate");
|
||||
|
|
|
@ -5,7 +5,10 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
var EXPORTED_SYMBOLS = [];
|
||||
// Objects intended to be used in the unit tests
|
||||
var UnitTestObjs = {};
|
||||
|
||||
var EXPORTED_SYMBOLS = ["UnitTestObjs"];
|
||||
|
||||
// Write/Read data to/from an ArrayBuffer
|
||||
class ArrayBufferDataStream {
|
||||
|
@ -103,7 +106,6 @@ class ArrayBufferDataStream {
|
|||
this.pos += 8;
|
||||
}
|
||||
|
||||
|
||||
readFloat32() {
|
||||
let rv = this.dataView.getFloat32(this.pos);
|
||||
this.pos += 4;
|
||||
|
@ -200,6 +202,10 @@ class UniFFIError {
|
|||
constructor(message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
toString() {
|
||||
return `UniFFIError: ${this.message}`
|
||||
}
|
||||
}
|
||||
|
||||
class UniFFIInternalError extends UniFFIError {}
|
||||
|
@ -283,182 +289,204 @@ class TodoList {
|
|||
* to a newly constructed TodoList
|
||||
*/
|
||||
static init() {
|
||||
const liftResult = (result) => FfiConverterTypeTodoList.lift(result);
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
return UniFFIScaffolding.callAsync(
|
||||
92, // todolist:todolist_aa33_TodoList_new
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}}
|
||||
const liftResult = (result) => FfiConverterTypeTodoList.lift(result);
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
return UniFFIScaffolding.callAsync(
|
||||
92, // todolist:todolist_aa33_TodoList_new
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}}
|
||||
|
||||
addItem(todo) {
|
||||
const liftResult = (result) => undefined;
|
||||
const liftError = (data) => FfiConverterTypeTodoError.lift(data);
|
||||
const functionCall = () => {
|
||||
FfiConverterString.checkType("todo", todo);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
93, // todolist:todolist_aa33_TodoList_add_item
|
||||
FfiConverterTypeTodoList.lower(this),
|
||||
FfiConverterString.lower(todo),
|
||||
)
|
||||
const liftResult = (result) => undefined;
|
||||
const liftError = (data) => FfiConverterTypeTodoError.lift(data);
|
||||
const functionCall = () => {
|
||||
FfiConverterString.checkType("todo", todo);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
93, // todolist:todolist_aa33_TodoList_add_item
|
||||
FfiConverterTypeTodoList.lower(this),
|
||||
FfiConverterString.lower(todo),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}}
|
||||
|
||||
addEntry(entry) {
|
||||
const liftResult = (result) => undefined;
|
||||
const liftError = (data) => FfiConverterTypeTodoError.lift(data);
|
||||
const functionCall = () => {
|
||||
FfiConverterTypeTodoEntry.checkType("entry", entry);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
94, // todolist:todolist_aa33_TodoList_add_entry
|
||||
FfiConverterTypeTodoList.lower(this),
|
||||
FfiConverterTypeTodoEntry.lower(entry),
|
||||
)
|
||||
const liftResult = (result) => undefined;
|
||||
const liftError = (data) => FfiConverterTypeTodoError.lift(data);
|
||||
const functionCall = () => {
|
||||
FfiConverterTypeTodoEntry.checkType("entry", entry);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
94, // todolist:todolist_aa33_TodoList_add_entry
|
||||
FfiConverterTypeTodoList.lower(this),
|
||||
FfiConverterTypeTodoEntry.lower(entry),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}}
|
||||
|
||||
getEntries() {
|
||||
const liftResult = (result) => FfiConverterSequenceTypeTodoEntry.lift(result);
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
return UniFFIScaffolding.callAsync(
|
||||
95, // todolist:todolist_aa33_TodoList_get_entries
|
||||
FfiConverterTypeTodoList.lower(this),
|
||||
)
|
||||
const liftResult = (result) => FfiConverterSequenceTypeTodoEntry.lift(result);
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
return UniFFIScaffolding.callAsync(
|
||||
95, // todolist:todolist_aa33_TodoList_get_entries
|
||||
FfiConverterTypeTodoList.lower(this),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}}
|
||||
|
||||
getItems() {
|
||||
const liftResult = (result) => FfiConverterSequencestring.lift(result);
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
return UniFFIScaffolding.callAsync(
|
||||
96, // todolist:todolist_aa33_TodoList_get_items
|
||||
FfiConverterTypeTodoList.lower(this),
|
||||
)
|
||||
const liftResult = (result) => FfiConverterSequencestring.lift(result);
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
return UniFFIScaffolding.callAsync(
|
||||
96, // todolist:todolist_aa33_TodoList_get_items
|
||||
FfiConverterTypeTodoList.lower(this),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}}
|
||||
|
||||
addEntries(entries) {
|
||||
const liftResult = (result) => undefined;
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
FfiConverterSequenceTypeTodoEntry.checkType("entries", entries);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
97, // todolist:todolist_aa33_TodoList_add_entries
|
||||
FfiConverterTypeTodoList.lower(this),
|
||||
FfiConverterSequenceTypeTodoEntry.lower(entries),
|
||||
)
|
||||
const liftResult = (result) => undefined;
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
FfiConverterSequenceTypeTodoEntry.checkType("entries", entries);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
97, // todolist:todolist_aa33_TodoList_add_entries
|
||||
FfiConverterTypeTodoList.lower(this),
|
||||
FfiConverterSequenceTypeTodoEntry.lower(entries),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}}
|
||||
|
||||
addItems(items) {
|
||||
const liftResult = (result) => undefined;
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
FfiConverterSequencestring.checkType("items", items);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
98, // todolist:todolist_aa33_TodoList_add_items
|
||||
FfiConverterTypeTodoList.lower(this),
|
||||
FfiConverterSequencestring.lower(items),
|
||||
)
|
||||
const liftResult = (result) => undefined;
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
FfiConverterSequencestring.checkType("items", items);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
98, // todolist:todolist_aa33_TodoList_add_items
|
||||
FfiConverterTypeTodoList.lower(this),
|
||||
FfiConverterSequencestring.lower(items),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}}
|
||||
|
||||
getLastEntry() {
|
||||
const liftResult = (result) => FfiConverterTypeTodoEntry.lift(result);
|
||||
const liftError = (data) => FfiConverterTypeTodoError.lift(data);
|
||||
const functionCall = () => {
|
||||
return UniFFIScaffolding.callAsync(
|
||||
99, // todolist:todolist_aa33_TodoList_get_last_entry
|
||||
FfiConverterTypeTodoList.lower(this),
|
||||
)
|
||||
const liftResult = (result) => FfiConverterTypeTodoEntry.lift(result);
|
||||
const liftError = (data) => FfiConverterTypeTodoError.lift(data);
|
||||
const functionCall = () => {
|
||||
return UniFFIScaffolding.callAsync(
|
||||
99, // todolist:todolist_aa33_TodoList_get_last_entry
|
||||
FfiConverterTypeTodoList.lower(this),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}}
|
||||
|
||||
getLast() {
|
||||
const liftResult = (result) => FfiConverterString.lift(result);
|
||||
const liftError = (data) => FfiConverterTypeTodoError.lift(data);
|
||||
const functionCall = () => {
|
||||
return UniFFIScaffolding.callAsync(
|
||||
100, // todolist:todolist_aa33_TodoList_get_last
|
||||
FfiConverterTypeTodoList.lower(this),
|
||||
)
|
||||
const liftResult = (result) => FfiConverterString.lift(result);
|
||||
const liftError = (data) => FfiConverterTypeTodoError.lift(data);
|
||||
const functionCall = () => {
|
||||
return UniFFIScaffolding.callAsync(
|
||||
100, // todolist:todolist_aa33_TodoList_get_last
|
||||
FfiConverterTypeTodoList.lower(this),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}}
|
||||
|
||||
getFirst() {
|
||||
const liftResult = (result) => FfiConverterString.lift(result);
|
||||
const liftError = (data) => FfiConverterTypeTodoError.lift(data);
|
||||
const functionCall = () => {
|
||||
return UniFFIScaffolding.callAsync(
|
||||
101, // todolist:todolist_aa33_TodoList_get_first
|
||||
FfiConverterTypeTodoList.lower(this),
|
||||
)
|
||||
const liftResult = (result) => FfiConverterString.lift(result);
|
||||
const liftError = (data) => FfiConverterTypeTodoError.lift(data);
|
||||
const functionCall = () => {
|
||||
return UniFFIScaffolding.callAsync(
|
||||
101, // todolist:todolist_aa33_TodoList_get_first
|
||||
FfiConverterTypeTodoList.lower(this),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}}
|
||||
|
||||
clearItem(todo) {
|
||||
const liftResult = (result) => undefined;
|
||||
const liftError = (data) => FfiConverterTypeTodoError.lift(data);
|
||||
const functionCall = () => {
|
||||
FfiConverterString.checkType("todo", todo);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
102, // todolist:todolist_aa33_TodoList_clear_item
|
||||
FfiConverterTypeTodoList.lower(this),
|
||||
FfiConverterString.lower(todo),
|
||||
)
|
||||
const liftResult = (result) => undefined;
|
||||
const liftError = (data) => FfiConverterTypeTodoError.lift(data);
|
||||
const functionCall = () => {
|
||||
FfiConverterString.checkType("todo", todo);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
102, // todolist:todolist_aa33_TodoList_clear_item
|
||||
FfiConverterTypeTodoList.lower(this),
|
||||
FfiConverterString.lower(todo),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}}
|
||||
|
||||
makeDefault() {
|
||||
const liftResult = (result) => undefined;
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
return UniFFIScaffolding.callAsync(
|
||||
103, // todolist:todolist_aa33_TodoList_make_default
|
||||
FfiConverterTypeTodoList.lower(this),
|
||||
)
|
||||
const liftResult = (result) => undefined;
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
return UniFFIScaffolding.callAsync(
|
||||
103, // todolist:todolist_aa33_TodoList_make_default
|
||||
FfiConverterTypeTodoList.lower(this),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}}
|
||||
|
||||
}
|
||||
|
||||
|
@ -546,6 +574,9 @@ class TodoDoesNotExist extends TodoError {
|
|||
super(...params);
|
||||
this.message = message;
|
||||
}
|
||||
toString() {
|
||||
return `TodoDoesNotExist: ${super.toString()}`
|
||||
}
|
||||
}
|
||||
EXPORTED_SYMBOLS.push("TodoDoesNotExist");
|
||||
class EmptyTodoList extends TodoError {
|
||||
|
@ -554,6 +585,9 @@ class EmptyTodoList extends TodoError {
|
|||
super(...params);
|
||||
this.message = message;
|
||||
}
|
||||
toString() {
|
||||
return `EmptyTodoList: ${super.toString()}`
|
||||
}
|
||||
}
|
||||
EXPORTED_SYMBOLS.push("EmptyTodoList");
|
||||
class DuplicateTodo extends TodoError {
|
||||
|
@ -562,6 +596,9 @@ class DuplicateTodo extends TodoError {
|
|||
super(...params);
|
||||
this.message = message;
|
||||
}
|
||||
toString() {
|
||||
return `DuplicateTodo: ${super.toString()}`
|
||||
}
|
||||
}
|
||||
EXPORTED_SYMBOLS.push("DuplicateTodo");
|
||||
class EmptyString extends TodoError {
|
||||
|
@ -570,6 +607,9 @@ class EmptyString extends TodoError {
|
|||
super(...params);
|
||||
this.message = message;
|
||||
}
|
||||
toString() {
|
||||
return `EmptyString: ${super.toString()}`
|
||||
}
|
||||
}
|
||||
EXPORTED_SYMBOLS.push("EmptyString");
|
||||
class DeligatedError extends TodoError {
|
||||
|
@ -578,6 +618,9 @@ class DeligatedError extends TodoError {
|
|||
super(...params);
|
||||
this.message = message;
|
||||
}
|
||||
toString() {
|
||||
return `DeligatedError: ${super.toString()}`
|
||||
}
|
||||
}
|
||||
EXPORTED_SYMBOLS.push("DeligatedError");
|
||||
|
||||
|
@ -595,9 +638,54 @@ class FfiConverterTypeTodoError extends FfiConverterArrayBuffer {
|
|||
case 5:
|
||||
return new DeligatedError(FfiConverterString.read(dataStream));
|
||||
default:
|
||||
return new Error("Unknown TodoError variant");
|
||||
throw new Error("Unknown TodoError variant");
|
||||
}
|
||||
}
|
||||
static computeSize(value) {
|
||||
// Size of the Int indicating the variant
|
||||
let totalSize = 4;
|
||||
if (value instanceof TodoDoesNotExist) {
|
||||
return totalSize;
|
||||
}
|
||||
if (value instanceof EmptyTodoList) {
|
||||
return totalSize;
|
||||
}
|
||||
if (value instanceof DuplicateTodo) {
|
||||
return totalSize;
|
||||
}
|
||||
if (value instanceof EmptyString) {
|
||||
return totalSize;
|
||||
}
|
||||
if (value instanceof DeligatedError) {
|
||||
return totalSize;
|
||||
}
|
||||
throw new Error("Unknown TodoError variant");
|
||||
}
|
||||
static write(dataStream, value) {
|
||||
if (value instanceof TodoDoesNotExist) {
|
||||
dataStream.writeInt32(1);
|
||||
return;
|
||||
}
|
||||
if (value instanceof EmptyTodoList) {
|
||||
dataStream.writeInt32(2);
|
||||
return;
|
||||
}
|
||||
if (value instanceof DuplicateTodo) {
|
||||
dataStream.writeInt32(3);
|
||||
return;
|
||||
}
|
||||
if (value instanceof EmptyString) {
|
||||
dataStream.writeInt32(4);
|
||||
return;
|
||||
}
|
||||
if (value instanceof DeligatedError) {
|
||||
dataStream.writeInt32(5);
|
||||
return;
|
||||
}
|
||||
throw new Error("Unknown TodoError variant");
|
||||
}
|
||||
|
||||
static errorClass = TodoError;
|
||||
}
|
||||
|
||||
// Export the FFIConverter object to make external types work.
|
||||
|
@ -707,56 +795,56 @@ EXPORTED_SYMBOLS.push("FfiConverterSequenceTypeTodoEntry");
|
|||
|
||||
function getDefaultList() {
|
||||
|
||||
const liftResult = (result) => FfiConverterOptionalTypeTodoList.lift(result);
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
return UniFFIScaffolding.callAsync(
|
||||
104, // todolist:todolist_aa33_get_default_list
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
const liftResult = (result) => FfiConverterOptionalTypeTodoList.lift(result);
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
return UniFFIScaffolding.callAsync(
|
||||
104, // todolist:todolist_aa33_get_default_list
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
|
||||
EXPORTED_SYMBOLS.push("getDefaultList");
|
||||
function setDefaultList(list) {
|
||||
|
||||
const liftResult = (result) => undefined;
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
FfiConverterTypeTodoList.checkType("list", list);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
105, // todolist:todolist_aa33_set_default_list
|
||||
FfiConverterTypeTodoList.lower(list),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
const liftResult = (result) => undefined;
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
FfiConverterTypeTodoList.checkType("list", list);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
105, // todolist:todolist_aa33_set_default_list
|
||||
FfiConverterTypeTodoList.lower(list),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
|
||||
EXPORTED_SYMBOLS.push("setDefaultList");
|
||||
function createEntryWith(todo) {
|
||||
|
||||
const liftResult = (result) => FfiConverterTypeTodoEntry.lift(result);
|
||||
const liftError = (data) => FfiConverterTypeTodoError.lift(data);
|
||||
const functionCall = () => {
|
||||
FfiConverterString.checkType("todo", todo);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
106, // todolist:todolist_aa33_create_entry_with
|
||||
FfiConverterString.lower(todo),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
const liftResult = (result) => FfiConverterTypeTodoEntry.lift(result);
|
||||
const liftError = (data) => FfiConverterTypeTodoError.lift(data);
|
||||
const functionCall = () => {
|
||||
FfiConverterString.checkType("todo", todo);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
106, // todolist:todolist_aa33_create_entry_with
|
||||
FfiConverterString.lower(todo),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
|
||||
EXPORTED_SYMBOLS.push("createEntryWith");
|
||||
|
|
|
@ -10,6 +10,7 @@ components = [
|
|||
"Arithmetic",
|
||||
"CustomTypes",
|
||||
"ExternalTypes",
|
||||
"FixtureCallbacks",
|
||||
"Geometry",
|
||||
"Rondpoint",
|
||||
"Sprites",
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const { logEvenNumbers, logEvenNumbersMainThread } = ChromeUtils.import(
|
||||
"resource://gre/modules/RustFixtureCallbacks.jsm"
|
||||
);
|
||||
|
||||
class Logger {
|
||||
constructor() {
|
||||
this.messages = [];
|
||||
this.finishedPromise = new Promise((resolve, reject) => {
|
||||
this.finishedResolve = resolve;
|
||||
this.finishedReject = reject;
|
||||
});
|
||||
}
|
||||
|
||||
log(message) {
|
||||
this.messages.push(message);
|
||||
}
|
||||
|
||||
finished() {
|
||||
this.finishedResolve(true);
|
||||
}
|
||||
|
||||
async waitForFinish() {
|
||||
// Set a timeout to avoid hanging the tests if the Rust code fails to call finished().
|
||||
do_timeout(2000, () =>
|
||||
this.finishedReject("Timeout waiting for finished()")
|
||||
);
|
||||
return this.finishedPromise;
|
||||
}
|
||||
}
|
||||
|
||||
add_task(async function testLogEvenNumbers() {
|
||||
async function runTest(logEvenNumbersFunc) {
|
||||
const logger = new Logger();
|
||||
logEvenNumbersFunc(logger, [1, 1, 2, 3, 5, 8, 13]);
|
||||
await logger.waitForFinish();
|
||||
Assert.deepEqual(logger.messages, [
|
||||
"Saw even number: 2",
|
||||
"Saw even number: 8",
|
||||
]);
|
||||
}
|
||||
|
||||
await runTest(logEvenNumbers);
|
||||
await runTest(logEvenNumbersMainThread);
|
||||
});
|
|
@ -1,4 +1,5 @@
|
|||
[test_arithmetic.js]
|
||||
[test_callbacks.js]
|
||||
[test_geometry.js]
|
||||
[test_rondpoint.js]
|
||||
[test_sprites.js]
|
||||
|
|
|
@ -20,6 +20,7 @@ FIXTURE_UDL_FILES = [
|
|||
"third_party/rust/uniffi-example-rondpoint/src/rondpoint.udl",
|
||||
"third_party/rust/uniffi-example-sprites/src/sprites.udl",
|
||||
"third_party/rust/uniffi-example-todolist/src/todolist.udl",
|
||||
"toolkit/components/uniffi-fixture-callbacks/src/callbacks.udl",
|
||||
"toolkit/components/uniffi-example-custom-types/src/custom-types.udl",
|
||||
"toolkit/components/uniffi-fixture-external-types/src/external-types.udl",
|
||||
]
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* 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/. */
|
||||
|
||||
//! Manage the universe of ComponentInterfaces
|
||||
//! Manage the universe of ComponentInterfaces / Configs
|
||||
//!
|
||||
//! uniffi-bindgen-gecko-js is unique because it generates bindings over a set of UDL files rather
|
||||
//! than just one. This is because we want to generate the WebIDL statically rather than generate
|
||||
|
@ -14,39 +14,43 @@
|
|||
//! This module manages the list of ComponentInterface and the object ids.
|
||||
|
||||
use crate::render::cpp::ComponentInterfaceCppExt;
|
||||
use crate::{Config, ConfigMap};
|
||||
use anyhow::{bail, Context, Result};
|
||||
use camino::Utf8PathBuf;
|
||||
use std::collections::{BTreeSet, HashMap, HashSet};
|
||||
use uniffi_bindgen::interface::{ComponentInterface, FFIFunction, Object};
|
||||
use uniffi_bindgen::interface::{CallbackInterface, ComponentInterface, FFIFunction, Object};
|
||||
|
||||
pub struct ComponentInterfaceUniverse {
|
||||
ci_list: Vec<ComponentInterface>,
|
||||
fixture_ci_list: Vec<ComponentInterface>,
|
||||
pub struct ComponentUniverse {
|
||||
pub components: Vec<(ComponentInterface, Config)>,
|
||||
pub fixture_components: Vec<(ComponentInterface, Config)>,
|
||||
}
|
||||
|
||||
impl ComponentInterfaceUniverse {
|
||||
pub fn new(udl_files: Vec<Utf8PathBuf>, fixture_udl_files: Vec<Utf8PathBuf>) -> Result<Self> {
|
||||
let ci_list = udl_files
|
||||
impl ComponentUniverse {
|
||||
pub fn new(
|
||||
udl_files: Vec<Utf8PathBuf>,
|
||||
fixture_udl_files: Vec<Utf8PathBuf>,
|
||||
config_map: ConfigMap,
|
||||
) -> Result<Self> {
|
||||
let components = udl_files
|
||||
.into_iter()
|
||||
.map(parse_udl_file)
|
||||
.map(|udl_file| parse_udl_file(udl_file, &config_map))
|
||||
.collect::<Result<Vec<_>>>()?;
|
||||
let fixture_ci_list = fixture_udl_files
|
||||
let fixture_components = fixture_udl_files
|
||||
.into_iter()
|
||||
.map(parse_udl_file)
|
||||
.map(|udl_file| parse_udl_file(udl_file, &config_map))
|
||||
.collect::<Result<Vec<_>>>()?;
|
||||
Self::check_udl_namespaces_unique(&ci_list, &fixture_ci_list)?;
|
||||
Ok(Self {
|
||||
ci_list,
|
||||
fixture_ci_list,
|
||||
})
|
||||
let universe = Self {
|
||||
components,
|
||||
fixture_components,
|
||||
};
|
||||
universe.check_udl_namespaces_unique()?;
|
||||
universe.check_callback_interfaces()?;
|
||||
Ok(universe)
|
||||
}
|
||||
|
||||
fn check_udl_namespaces_unique(
|
||||
ci_list: &Vec<ComponentInterface>,
|
||||
fixture_ci_list: &Vec<ComponentInterface>,
|
||||
) -> Result<()> {
|
||||
fn check_udl_namespaces_unique(&self) -> Result<()> {
|
||||
let mut set = HashSet::new();
|
||||
for ci in ci_list.iter().chain(fixture_ci_list.iter()) {
|
||||
for ci in self.iter_cis() {
|
||||
if !set.insert(ci.namespace()) {
|
||||
bail!("UDL files have duplicate namespace: {}", ci.namespace());
|
||||
}
|
||||
|
@ -54,22 +58,39 @@ impl ComponentInterfaceUniverse {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn ci_list(&self) -> &Vec<ComponentInterface> {
|
||||
&self.ci_list
|
||||
fn check_callback_interfaces(&self) -> Result<()> {
|
||||
// We don't currently support callback interfaces returning values or throwing errors.
|
||||
for ci in self.iter_cis() {
|
||||
for cbi in ci.callback_interface_definitions() {
|
||||
for method in cbi.methods() {
|
||||
if method.return_type().is_some() {
|
||||
bail!("Callback interface method {}.{} throws an error, which is not yet supported", cbi.name(), method.name())
|
||||
}
|
||||
if method.throws_type().is_some() {
|
||||
bail!("Callback interface method {}.{} returns a value, which is not yet supported", cbi.name(), method.name())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn fixture_ci_list(&self) -> &Vec<ComponentInterface> {
|
||||
&self.fixture_ci_list
|
||||
}
|
||||
|
||||
pub fn iter_all(&self) -> impl Iterator<Item = &ComponentInterface> {
|
||||
self.ci_list.iter().chain(self.fixture_ci_list.iter())
|
||||
pub fn iter_cis(&self) -> impl Iterator<Item = &ComponentInterface> {
|
||||
self.components
|
||||
.iter()
|
||||
.chain(self.fixture_components.iter())
|
||||
.map(|(ci, _)| ci)
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_udl_file(udl_file: Utf8PathBuf) -> Result<ComponentInterface> {
|
||||
fn parse_udl_file(
|
||||
udl_file: Utf8PathBuf,
|
||||
config_map: &ConfigMap,
|
||||
) -> Result<(ComponentInterface, Config)> {
|
||||
let udl = std::fs::read_to_string(&udl_file).context("Error reading UDL file")?;
|
||||
ComponentInterface::from_webidl(&udl).context("Failed to parse UDL")
|
||||
let ci = ComponentInterface::from_webidl(&udl).context("Failed to parse UDL")?;
|
||||
let config = config_map.get(ci.namespace()).cloned().unwrap_or_default();
|
||||
Ok((ci, config))
|
||||
}
|
||||
|
||||
pub struct FunctionIds<'a> {
|
||||
|
@ -78,10 +99,10 @@ pub struct FunctionIds<'a> {
|
|||
}
|
||||
|
||||
impl<'a> FunctionIds<'a> {
|
||||
pub fn new(cis: &'a ComponentInterfaceUniverse) -> Self {
|
||||
pub fn new(cis: &'a ComponentUniverse) -> Self {
|
||||
Self {
|
||||
map: cis
|
||||
.iter_all()
|
||||
.iter_cis()
|
||||
.flat_map(|ci| {
|
||||
ci.exposed_functions()
|
||||
.into_iter()
|
||||
|
@ -111,10 +132,10 @@ pub struct ObjectIds<'a> {
|
|||
}
|
||||
|
||||
impl<'a> ObjectIds<'a> {
|
||||
pub fn new(cis: &'a ComponentInterfaceUniverse) -> Self {
|
||||
pub fn new(cis: &'a ComponentUniverse) -> Self {
|
||||
Self {
|
||||
map: cis
|
||||
.iter_all()
|
||||
.iter_cis()
|
||||
.flat_map(|ci| {
|
||||
ci.object_definitions()
|
||||
.iter()
|
||||
|
@ -137,3 +158,36 @@ impl<'a> ObjectIds<'a> {
|
|||
format!("{}:{}", ci.namespace(), obj.name())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CallbackIds<'a> {
|
||||
// Map (CI namespace, callback name) -> Ids
|
||||
map: HashMap<(&'a str, &'a str), usize>,
|
||||
}
|
||||
|
||||
impl<'a> CallbackIds<'a> {
|
||||
pub fn new(cis: &'a ComponentUniverse) -> Self {
|
||||
Self {
|
||||
map: cis
|
||||
.iter_cis()
|
||||
.flat_map(|ci| {
|
||||
ci.callback_interface_definitions()
|
||||
.iter()
|
||||
.map(move |cb| (ci.namespace(), cb.name()))
|
||||
})
|
||||
.enumerate()
|
||||
.map(|(i, (namespace, name))| ((namespace, name), i))
|
||||
// Sort using BTreeSet to guarantee the IDs remain stable across runs
|
||||
.collect::<BTreeSet<_>>()
|
||||
.into_iter()
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(&self, ci: &ComponentInterface, cb: &CallbackInterface) -> usize {
|
||||
return *self.map.get(&(ci.namespace(), cb.name())).unwrap();
|
||||
}
|
||||
|
||||
pub fn name(&self, ci: &ComponentInterface, cb: &CallbackInterface) -> String {
|
||||
format!("{}:{}", ci.namespace(), cb.name())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,16 +6,18 @@ use anyhow::{Context, Result};
|
|||
use askama::Template;
|
||||
use camino::Utf8PathBuf;
|
||||
use clap::Parser;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use uniffi_bindgen::ComponentInterface;
|
||||
|
||||
mod ci_list;
|
||||
mod render;
|
||||
|
||||
pub use ci_list::{ComponentInterfaceUniverse, FunctionIds, ObjectIds};
|
||||
pub use render::cpp::CPPScaffoldingTemplate;
|
||||
pub use render::js::JSBindingsTemplate;
|
||||
use uniffi_bindgen::ComponentInterface;
|
||||
use ci_list::{CallbackIds, ComponentUniverse, FunctionIds, ObjectIds};
|
||||
use render::cpp::CPPScaffoldingTemplate;
|
||||
use render::js::JSBindingsTemplate;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
#[clap(name = "uniffi-bindgen-gecko-js")]
|
||||
|
@ -44,6 +46,25 @@ struct CliArgs {
|
|||
fixture_udl_files: Vec<Utf8PathBuf>,
|
||||
}
|
||||
|
||||
/// Configuration for all components, read from `uniffi.toml`
|
||||
type ConfigMap = HashMap<String, Config>;
|
||||
|
||||
/// Configuration for a single Component
|
||||
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
|
||||
pub struct Config {
|
||||
receiver_thread: ReceiverThreadConfig,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
|
||||
struct ReceiverThreadConfig {
|
||||
#[serde(default)]
|
||||
default: Option<String>,
|
||||
#[serde(default)]
|
||||
main: HashSet<String>,
|
||||
#[serde(default)]
|
||||
worker: HashSet<String>,
|
||||
}
|
||||
|
||||
fn render(out_path: Utf8PathBuf, template: impl Template) -> Result<()> {
|
||||
println!("rendering {}", out_path);
|
||||
let contents = template.render()?;
|
||||
|
@ -55,32 +76,37 @@ fn render(out_path: Utf8PathBuf, template: impl Template) -> Result<()> {
|
|||
fn render_cpp(
|
||||
path: Utf8PathBuf,
|
||||
prefix: &str,
|
||||
ci_list: &Vec<ComponentInterface>,
|
||||
components: &Vec<(ComponentInterface, Config)>,
|
||||
function_ids: &FunctionIds,
|
||||
object_ids: &ObjectIds,
|
||||
callback_ids: &CallbackIds,
|
||||
) -> Result<()> {
|
||||
render(
|
||||
path,
|
||||
CPPScaffoldingTemplate {
|
||||
prefix,
|
||||
ci_list,
|
||||
function_ids: &function_ids,
|
||||
object_ids: &object_ids,
|
||||
components,
|
||||
function_ids,
|
||||
object_ids,
|
||||
callback_ids,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fn render_js(
|
||||
out_dir: Utf8PathBuf,
|
||||
ci_list: &Vec<ComponentInterface>,
|
||||
components: &Vec<(ComponentInterface, Config)>,
|
||||
function_ids: &FunctionIds,
|
||||
object_ids: &ObjectIds,
|
||||
callback_ids: &CallbackIds,
|
||||
) -> Result<()> {
|
||||
for ci in ci_list {
|
||||
for (ci, config) in components {
|
||||
let template = JSBindingsTemplate {
|
||||
ci,
|
||||
function_ids: &function_ids,
|
||||
object_ids: &object_ids,
|
||||
config,
|
||||
function_ids,
|
||||
object_ids,
|
||||
callback_ids,
|
||||
};
|
||||
let path = out_dir.join(template.js_module_name());
|
||||
render(path, template)?;
|
||||
|
@ -90,30 +116,42 @@ fn render_js(
|
|||
|
||||
pub fn run_main() -> Result<()> {
|
||||
let args = CliArgs::parse();
|
||||
let cis = ComponentInterfaceUniverse::new(args.udl_files, args.fixture_udl_files)?;
|
||||
let function_ids = FunctionIds::new(&cis);
|
||||
let object_ids = ObjectIds::new(&cis);
|
||||
let config_map: ConfigMap =
|
||||
toml::from_str(include_str!("../config.toml")).expect("Error parsing config.toml");
|
||||
let components = ComponentUniverse::new(args.udl_files, args.fixture_udl_files, config_map)?;
|
||||
let function_ids = FunctionIds::new(&components);
|
||||
let object_ids = ObjectIds::new(&components);
|
||||
let callback_ids = CallbackIds::new(&components);
|
||||
|
||||
render_cpp(
|
||||
args.cpp_path,
|
||||
"UniFFI",
|
||||
cis.ci_list(),
|
||||
&components.components,
|
||||
&function_ids,
|
||||
&object_ids,
|
||||
&callback_ids,
|
||||
)?;
|
||||
render_cpp(
|
||||
args.fixture_cpp_path,
|
||||
"UniFFIFixtures",
|
||||
cis.fixture_ci_list(),
|
||||
&components.fixture_components,
|
||||
&function_ids,
|
||||
&object_ids,
|
||||
&callback_ids,
|
||||
)?;
|
||||
render_js(
|
||||
args.js_dir,
|
||||
&components.components,
|
||||
&function_ids,
|
||||
&object_ids,
|
||||
&callback_ids,
|
||||
)?;
|
||||
render_js(args.js_dir, cis.ci_list(), &function_ids, &object_ids)?;
|
||||
render_js(
|
||||
args.fixture_js_dir,
|
||||
cis.fixture_ci_list(),
|
||||
&components.fixture_components,
|
||||
&function_ids,
|
||||
&object_ids,
|
||||
&callback_ids,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -2,13 +2,15 @@
|
|||
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/. */
|
||||
|
||||
use crate::{FunctionIds, ObjectIds};
|
||||
use crate::{CallbackIds, Config, FunctionIds, ObjectIds};
|
||||
use askama::Template;
|
||||
use extend::ext;
|
||||
use heck::ToUpperCamelCase;
|
||||
use heck::{ToShoutySnakeCase, ToUpperCamelCase};
|
||||
use std::collections::HashSet;
|
||||
use std::iter;
|
||||
use uniffi_bindgen::interface::{ComponentInterface, FFIArgument, FFIFunction, FFIType, Object};
|
||||
use uniffi_bindgen::interface::{
|
||||
CallbackInterface, ComponentInterface, FFIArgument, FFIFunction, FFIType, Object,
|
||||
};
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(path = "UniFFIScaffolding.cpp", escape = "none")]
|
||||
|
@ -20,16 +22,17 @@ pub struct CPPScaffoldingTemplate<'a> {
|
|||
// - Have a hand-written stub function that always calls the first function and only calls
|
||||
// the second function in if MOZ_UNIFFI_FIXTURES is defined.
|
||||
pub prefix: &'a str,
|
||||
pub ci_list: &'a Vec<ComponentInterface>,
|
||||
pub components: &'a Vec<(ComponentInterface, Config)>,
|
||||
pub function_ids: &'a FunctionIds<'a>,
|
||||
pub object_ids: &'a ObjectIds<'a>,
|
||||
pub callback_ids: &'a CallbackIds<'a>,
|
||||
}
|
||||
|
||||
impl<'a> CPPScaffoldingTemplate<'a> {
|
||||
fn has_any_objects(&self) -> bool {
|
||||
self.ci_list
|
||||
self.components
|
||||
.iter()
|
||||
.any(|ci| ci.object_definitions().len() > 0)
|
||||
.any(|(ci, _)| ci.object_definitions().len() > 0)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -63,6 +66,11 @@ pub impl ComponentInterface {
|
|||
.object_definitions()
|
||||
.iter()
|
||||
.map(|o| o.ffi_object_free().name())
|
||||
.chain(
|
||||
self.callback_interface_definitions()
|
||||
.iter()
|
||||
.map(|cbi| cbi.ffi_init_callback().name()),
|
||||
)
|
||||
.collect();
|
||||
self.iter_user_ffi_function_definitions()
|
||||
.filter(move |f| !excluded.contains(f.name()))
|
||||
|
@ -140,8 +148,8 @@ pub impl FFIType {
|
|||
FFIType::Float64 => "double",
|
||||
FFIType::RustBuffer => "RustBuffer",
|
||||
FFIType::RustArcPtr(_) => "void *",
|
||||
FFIType::ForeignCallback => "ForeignCallback",
|
||||
FFIType::ForeignBytes => unimplemented!("ForeignBytes not supported"),
|
||||
FFIType::ForeignCallback => unimplemented!("ForeignCallback not supported"),
|
||||
}
|
||||
.to_owned()
|
||||
}
|
||||
|
@ -160,3 +168,23 @@ pub impl Object {
|
|||
self.name().to_upper_camel_case()
|
||||
}
|
||||
}
|
||||
|
||||
#[ext(name=CallbackInterfaceCppExt)]
|
||||
pub impl CallbackInterface {
|
||||
fn nm(&self) -> String {
|
||||
self.name().to_upper_camel_case()
|
||||
}
|
||||
|
||||
/// Name of the static pointer to the JS callback handler
|
||||
fn js_handler(&self) -> String {
|
||||
format!("JS_CALLBACK_HANDLER_{}", self.name().to_shouty_snake_case())
|
||||
}
|
||||
|
||||
/// Name of the C function handler
|
||||
fn c_handler(&self, prefix: &str) -> String {
|
||||
format!(
|
||||
"{prefix}CallbackHandler{}",
|
||||
self.name().to_upper_camel_case()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,13 +3,13 @@ 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/. */
|
||||
|
||||
use super::shared::*;
|
||||
use crate::{FunctionIds, ObjectIds};
|
||||
use crate::{CallbackIds, Config, FunctionIds, ObjectIds};
|
||||
use askama::Template;
|
||||
use extend::ext;
|
||||
use heck::{ToLowerCamelCase, ToShoutySnakeCase, ToUpperCamelCase};
|
||||
use uniffi_bindgen::interface::{
|
||||
Argument, ComponentInterface, Constructor, Enum, Error, Field, Function, Literal, Method,
|
||||
Object, Radix, Record, Type,
|
||||
Argument, CallbackInterface, ComponentInterface, Constructor, Enum, Error, Field, Function,
|
||||
Literal, Method, Object, Radix, Record, Type,
|
||||
};
|
||||
|
||||
fn arg_names(args: &[&Argument]) -> String {
|
||||
|
@ -42,8 +42,10 @@ fn render_enum_literal(typ: &Type, variant_name: &str) -> String {
|
|||
#[template(path = "js/wrapper.jsm", escape = "none")]
|
||||
pub struct JSBindingsTemplate<'a> {
|
||||
pub ci: &'a ComponentInterface,
|
||||
pub config: &'a Config,
|
||||
pub function_ids: &'a FunctionIds<'a>,
|
||||
pub object_ids: &'a ObjectIds<'a>,
|
||||
pub callback_ids: &'a CallbackIds<'a>,
|
||||
}
|
||||
|
||||
impl<'a> JSBindingsTemplate<'a> {
|
||||
|
@ -130,12 +132,31 @@ pub impl Record {
|
|||
}
|
||||
}
|
||||
|
||||
#[ext(name=CallbackInterfaceJSExt)]
|
||||
pub impl CallbackInterface {
|
||||
fn nm(&self) -> String {
|
||||
self.name().to_upper_camel_case()
|
||||
}
|
||||
|
||||
fn handler(&self) -> String {
|
||||
format!("callbackHandler{}", self.nm())
|
||||
}
|
||||
}
|
||||
|
||||
#[ext(name=FieldJSExt)]
|
||||
pub impl Field {
|
||||
fn nm(&self) -> String {
|
||||
self.name().to_lower_camel_case()
|
||||
}
|
||||
|
||||
fn lower_fn(&self) -> String {
|
||||
self.type_().lower_fn()
|
||||
}
|
||||
|
||||
fn lift_fn(&self) -> String {
|
||||
self.type_().lift_fn()
|
||||
}
|
||||
|
||||
fn write_datastream_fn(&self) -> String {
|
||||
self.type_().write_datastream_fn()
|
||||
}
|
||||
|
@ -144,6 +165,10 @@ pub impl Field {
|
|||
self.type_().read_datastream_fn()
|
||||
}
|
||||
|
||||
fn compute_size_fn(&self) -> String {
|
||||
self.type_().compute_size_fn()
|
||||
}
|
||||
|
||||
fn ffi_converter(&self) -> String {
|
||||
self.type_().ffi_converter()
|
||||
}
|
||||
|
@ -160,14 +185,34 @@ pub impl Field {
|
|||
|
||||
#[ext(name=ArgumentJSExt)]
|
||||
pub impl Argument {
|
||||
fn lower_fn_name(&self) -> String {
|
||||
format!("{}.lower", self.type_().ffi_converter())
|
||||
}
|
||||
|
||||
fn nm(&self) -> String {
|
||||
self.name().to_lower_camel_case()
|
||||
}
|
||||
|
||||
fn lower_fn(&self) -> String {
|
||||
self.type_().lower_fn()
|
||||
}
|
||||
|
||||
fn lift_fn(&self) -> String {
|
||||
self.type_().lift_fn()
|
||||
}
|
||||
|
||||
fn write_datastream_fn(&self) -> String {
|
||||
self.type_().write_datastream_fn()
|
||||
}
|
||||
|
||||
fn read_datastream_fn(&self) -> String {
|
||||
self.type_().read_datastream_fn()
|
||||
}
|
||||
|
||||
fn compute_size_fn(&self) -> String {
|
||||
self.type_().compute_size_fn()
|
||||
}
|
||||
|
||||
fn ffi_converter(&self) -> String {
|
||||
self.type_().ffi_converter()
|
||||
}
|
||||
|
||||
fn check_type(&self) -> String {
|
||||
format!(
|
||||
"{}.checkType(\"{}\", {})",
|
||||
|
@ -188,6 +233,14 @@ pub impl Type {
|
|||
}
|
||||
}
|
||||
|
||||
fn lower_fn(&self) -> String {
|
||||
format!("{}.lower", self.ffi_converter())
|
||||
}
|
||||
|
||||
fn lift_fn(&self) -> String {
|
||||
format!("{}.lift", self.ffi_converter())
|
||||
}
|
||||
|
||||
fn write_datastream_fn(&self) -> String {
|
||||
format!("{}.write", self.ffi_converter())
|
||||
}
|
||||
|
@ -196,6 +249,10 @@ pub impl Type {
|
|||
format!("{}.read", self.ffi_converter())
|
||||
}
|
||||
|
||||
fn compute_size_fn(&self) -> String {
|
||||
format!("{}.computeSize", self.ffi_converter())
|
||||
}
|
||||
|
||||
fn ffi_converter(&self) -> String {
|
||||
format!(
|
||||
"FfiConverter{}",
|
||||
|
|
|
@ -3,37 +3,37 @@ 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/. */
|
||||
|
||||
/// Extension traits that are shared across multiple render targets
|
||||
use crate::Config;
|
||||
use extend::ext;
|
||||
use uniffi_bindgen::interface::{Constructor, FFIFunction, Function, Method};
|
||||
use uniffi_bindgen::interface::{Function, Method, Object};
|
||||
|
||||
#[ext]
|
||||
pub impl FFIFunction {
|
||||
fn is_async(&self) -> bool {
|
||||
// TODO check `uniffi.toml` or some other configuration to figure this out
|
||||
fn is_async(config: &Config, spec: &str) -> bool {
|
||||
if config.receiver_thread.main.contains(spec) {
|
||||
false
|
||||
} else if config.receiver_thread.worker.contains(spec) {
|
||||
true
|
||||
} else {
|
||||
match &config.receiver_thread.default {
|
||||
Some(t) => t != "main",
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[ext]
|
||||
pub impl Function {
|
||||
fn is_async(&self) -> bool {
|
||||
// TODO check `uniffi.toml` or some other configuration to figure this out
|
||||
true
|
||||
fn is_async(&self, config: &Config) -> bool {
|
||||
is_async(config, self.name())
|
||||
}
|
||||
}
|
||||
|
||||
#[ext]
|
||||
pub impl Constructor {
|
||||
fn is_async(&self) -> bool {
|
||||
// TODO check `uniffi.toml` or some other configuration to figure this out
|
||||
true
|
||||
pub impl Object {
|
||||
fn is_constructor_async(&self, config: &Config) -> bool {
|
||||
is_async(config, self.name())
|
||||
}
|
||||
}
|
||||
|
||||
#[ext]
|
||||
pub impl Method {
|
||||
fn is_async(&self) -> bool {
|
||||
// TODO check `uniffi.toml` or some other configuration to figure this out
|
||||
true
|
||||
fn is_method_async(&self, method: &Method, config: &Config) -> bool {
|
||||
is_async(config, &format!("{}.{}", self.name(), method.name()))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,24 +2,29 @@
|
|||
|
||||
#include "nsString.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "mozilla/dom/UniFFICallbacks.h"
|
||||
#include "mozilla/dom/UniFFIScaffolding.h"
|
||||
#include "mozilla/dom/ScaffoldingCall.h"
|
||||
|
||||
namespace mozilla::uniffi {
|
||||
|
||||
using dom::ArrayBuffer;
|
||||
using dom::AutoEntryScript;
|
||||
using dom::GlobalObject;
|
||||
using dom::RootedDictionary;
|
||||
using dom::Promise;
|
||||
using dom::ScaffoldingType;
|
||||
using dom::Sequence;
|
||||
using dom::UniFFICallbackHandler;
|
||||
using dom::UniFFIPointer;
|
||||
using dom::UniFFIScaffoldingCallResult;
|
||||
|
||||
// Define scaffolding functions from UniFFI
|
||||
extern "C" {
|
||||
{%- for ci in ci_list %}
|
||||
{%- for (ci, config) in components %}
|
||||
{%- for func in ci.iter_user_ffi_function_definitions() %}
|
||||
{{ func.rust_return_type() }} {{ func.rust_name() }}({{ func.rust_arg_list() }});
|
||||
{%- endfor %}
|
||||
|
@ -27,20 +32,57 @@ extern "C" {
|
|||
}
|
||||
|
||||
// Define pointer types
|
||||
{%- for ci in ci_list %}
|
||||
{%- for (ci, config) in components %}
|
||||
{%- for object in ci.object_definitions() %}
|
||||
{%- let pointer_type = ci.pointer_type(object) %}
|
||||
const static mozilla::uniffi::UniFFIPointerType {{ pointer_type }} {
|
||||
"{{ "{}::{}"|format(ci.namespace(), object.name()) }}"_ns,
|
||||
{{ object.ffi_object_free().rust_name() }}
|
||||
};
|
||||
{%- endfor %}
|
||||
{%- endfor %}
|
||||
|
||||
// Define the data we need per-callback interface
|
||||
{%- for (ci, config) in components %}
|
||||
{%- for cbi in ci.callback_interface_definitions() %}
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
extern "C" int {{ cbi.c_handler(prefix) }}(uint64_t aHandle, uint32_t aMethod, RustBuffer aArgs, RustBuffer* aOutBuffer) {
|
||||
// Currently, we only support "fire-and-forget" async callbacks. These are
|
||||
// callbacks that run asynchronously without returning anything. The main
|
||||
// use case for callbacks is logging, which fits very well with this model.
|
||||
//
|
||||
// So, here we simple queue the callback and return immediately.
|
||||
mozilla::uniffi::QueueCallback({{ callback_ids.get(ci, cbi) }}, aHandle, aMethod, aArgs);
|
||||
return CALLBACK_INTERFACE_SUCCESS;
|
||||
}
|
||||
static StaticRefPtr<dom::UniFFICallbackHandler> {{ cbi.js_handler() }};
|
||||
{%- endfor %}
|
||||
{%- endfor %}
|
||||
|
||||
// Define a lookup function for our callback interface info
|
||||
Maybe<CallbackInterfaceInfo> {{ prefix }}GetCallbackInterfaceInfo(uint64_t aInterfaceId) {
|
||||
switch(aInterfaceId) {
|
||||
{%- for (ci, config) in components %}
|
||||
{%- for cbi in ci.callback_interface_definitions() %}
|
||||
case {{ callback_ids.get(ci, cbi) }}: { // {{ callback_ids.name(ci, cbi) }}
|
||||
return Some(CallbackInterfaceInfo {
|
||||
"{{ cbi.name() }}",
|
||||
&{{ cbi.js_handler() }},
|
||||
{{ cbi.c_handler(prefix) }},
|
||||
{{ cbi.ffi_init_callback().name() }},
|
||||
});
|
||||
}
|
||||
{%- endfor %}
|
||||
{%- endfor %}
|
||||
|
||||
default:
|
||||
return Nothing();
|
||||
}
|
||||
}
|
||||
|
||||
Maybe<already_AddRefed<Promise>> {{ prefix }}CallAsync(const GlobalObject& aGlobal, uint64_t aId, const Sequence<ScaffoldingType>& aArgs, ErrorResult& aError) {
|
||||
switch (aId) {
|
||||
{%- for ci in ci_list %}
|
||||
{%- for (ci, config) in components %}
|
||||
{%- for func in ci.exposed_functions() %}
|
||||
case {{ function_ids.get(ci, func) }}: { // {{ function_ids.name(ci, func) }}
|
||||
using CallHandler = {{ ci.scaffolding_call_handler(func) }};
|
||||
|
@ -54,7 +96,7 @@ Maybe<already_AddRefed<Promise>> {{ prefix }}CallAsync(const GlobalObject& aGlob
|
|||
|
||||
bool {{ prefix }}CallSync(const GlobalObject& aGlobal, uint64_t aId, const Sequence<ScaffoldingType>& aArgs, RootedDictionary<UniFFIScaffoldingCallResult>& aReturnValue, ErrorResult& aError) {
|
||||
switch (aId) {
|
||||
{%- for ci in ci_list %}
|
||||
{%- for (ci, config) in components %}
|
||||
{%- for func in ci.exposed_functions() %}
|
||||
case {{ function_ids.get(ci, func) }}: { // {{ function_ids.name(ci, func) }}
|
||||
using CallHandler = {{ ci.scaffolding_call_handler(func) }};
|
||||
|
@ -71,7 +113,7 @@ Maybe<already_AddRefed<UniFFIPointer>> {{ prefix }}ReadPointer(const GlobalObjec
|
|||
{%- if self.has_any_objects() %}
|
||||
const UniFFIPointerType* type;
|
||||
switch (aId) {
|
||||
{%- for ci in ci_list %}
|
||||
{%- for (ci, config) in components %}
|
||||
{%- for object in ci.object_definitions() %}
|
||||
case {{ object_ids.get(ci, object) }}: { // {{ object_ids.name(ci, object) }}
|
||||
type = &{{ ci.pointer_type(object) }};
|
||||
|
@ -92,7 +134,7 @@ bool {{ prefix }}WritePointer(const GlobalObject& aGlobal, uint64_t aId, const U
|
|||
{%- if self.has_any_objects() %}
|
||||
const UniFFIPointerType* type;
|
||||
switch (aId) {
|
||||
{%- for ci in ci_list %}
|
||||
{%- for (ci, config) in components %}
|
||||
{%- for object in ci.object_definitions() %}
|
||||
case {{ object_ids.get(ci, object) }}: { // {{ object_ids.name(ci, object) }}
|
||||
type = &{{ ci.pointer_type(object) }};
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
{%- let cbi = ci.get_callback_interface_definition(name).unwrap() %}
|
||||
{#- See CallbackInterfaceRuntime.jsm and CallbackInterfaceHandler.jsm for the callback interface handler definition, referenced here as `{{ cbi.handler() }}` #}
|
||||
class {{ ffi_converter }} extends FfiConverter {
|
||||
static lower(callbackObj) {
|
||||
return {{ cbi.handler() }}.storeCallbackObj(callbackObj)
|
||||
}
|
||||
|
||||
static lift(handleId) {
|
||||
return {{ cbi.handler() }}.getCallbackObj(handleId)
|
||||
}
|
||||
|
||||
static read(dataStream) {
|
||||
return this.lift(dataStream.readInt64())
|
||||
}
|
||||
|
||||
static write(dataStream, callbackObj) {
|
||||
dataStream.writeInt64(this.lower(callbackObj))
|
||||
}
|
||||
|
||||
static computeSize(callbackObj) {
|
||||
return 8;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
const {{ cbi.handler() }} = new UniFFICallbackHandler(
|
||||
"{{ callback_ids.name(ci, cbi) }}",
|
||||
{{ callback_ids.get(ci, cbi) }},
|
||||
[
|
||||
{%- for method in cbi.methods() %}
|
||||
new UniFFICallbackMethodHandler(
|
||||
"{{ method.nm() }}",
|
||||
[
|
||||
{%- for arg in method.arguments() %}
|
||||
{{ arg.ffi_converter() }},
|
||||
{%- endfor %}
|
||||
],
|
||||
),
|
||||
{%- endfor %}
|
||||
]
|
||||
);
|
||||
|
||||
// Allow the shutdown-related functionality to be tested in the unit tests
|
||||
UnitTestObjs.{{ cbi.handler() }} = {{ cbi.handler() }};
|
|
@ -0,0 +1,195 @@
|
|||
|
||||
/**
|
||||
* Handler for a single UniFFI CallbackInterface
|
||||
*
|
||||
* This class stores objects that implement a callback interface in a handle
|
||||
* map, allowing them to be referenced by the Rust code using an integer
|
||||
* handle.
|
||||
*
|
||||
* While the callback object is stored in the map, it allows the Rust code to
|
||||
* call methods on the object using the callback object handle, a method id,
|
||||
* and an ArrayBuffer packed with the method arguments.
|
||||
*
|
||||
* When the Rust code drops its reference, it sends a call with the methodId=0,
|
||||
* which causes callback object to be removed from the map.
|
||||
*/
|
||||
class UniFFICallbackHandler {
|
||||
#name;
|
||||
#interfaceId;
|
||||
#handleCounter;
|
||||
#handleMap;
|
||||
#methodHandlers;
|
||||
#allowNewCallbacks
|
||||
|
||||
/**
|
||||
* Create a UniFFICallbackHandler
|
||||
* @param {string} name - Human-friendly name for this callback interface
|
||||
* @param {int} interfaceId - Interface ID for this CallbackInterface.
|
||||
* @param {UniFFICallbackMethodHandler[]} methodHandlers -- UniFFICallbackHandler for each method, in the same order as the UDL file
|
||||
*/
|
||||
constructor(name, interfaceId, methodHandlers) {
|
||||
this.#name = name;
|
||||
this.#interfaceId = interfaceId;
|
||||
this.#handleCounter = 0;
|
||||
this.#handleMap = new Map();
|
||||
this.#methodHandlers = methodHandlers;
|
||||
this.#allowNewCallbacks = true;
|
||||
|
||||
UniFFIScaffolding.registerCallbackHandler(this.#interfaceId, this.invokeCallback.bind(this));
|
||||
Services.obs.addObserver(this, "xpcom-shutdown");
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a callback object in the handle map and return the handle
|
||||
*
|
||||
* @param {obj} callbackObj - Object that implements the callback interface
|
||||
* @returns {int} - Handle for this callback object, this is what gets passed back to Rust.
|
||||
*/
|
||||
storeCallbackObj(callbackObj) {
|
||||
if (!this.#allowNewCallbacks) {
|
||||
throw new UniFFIError(`No new callbacks allowed for ${this.#name}`);
|
||||
}
|
||||
const handle = this.#handleCounter;
|
||||
this.#handleCounter += 1;
|
||||
this.#handleMap.set(handle, new UniFFICallbackHandleMapEntry(callbackObj, Components.stack.caller.formattedStack.trim()));
|
||||
return handle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a previously stored callback object
|
||||
*
|
||||
* @param {int} handle - Callback object handle, returned from `storeCallbackObj()`
|
||||
* @returns {obj} - Callback object
|
||||
*/
|
||||
getCallbackObj(handle) {
|
||||
return this.#handleMap.get(handle).callbackObj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if new callbacks are allowed for this handler
|
||||
*
|
||||
* This is called with false during shutdown to ensure the callback maps don't
|
||||
* prevent JS objects from being GCed.
|
||||
*/
|
||||
setAllowNewCallbacks(allow) {
|
||||
this.#allowNewCallbacks = allow
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that no callbacks are currently registered
|
||||
*
|
||||
* If there are callbacks registered a UniFFIError will be thrown. This is
|
||||
* called during shutdown to generate an alert if there are leaked callback
|
||||
* interfaces.
|
||||
*/
|
||||
assertNoRegisteredCallbacks() {
|
||||
if (this.#handleMap.size > 0) {
|
||||
const entry = this.#handleMap.values().next().value;
|
||||
throw new UniFFIError(`UniFFI interface ${this.#name} has ${this.#handleMap.size} registered callbacks at xpcom-shutdown. This likely indicates a UniFFI callback leak.\nStack trace for the first leaked callback:\n${entry.stackTrace}.`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke a method on a stored callback object
|
||||
* @param {int} handle - Object handle
|
||||
* @param {int} methodId - Method identifier. This the 1-based index of
|
||||
* the method from the UDL file. 0 is the special drop method, which
|
||||
* removes the callback object from the handle map.
|
||||
* @param {ArrayBuffer} argsArrayBuffer - Arguments to pass to the method, packed in an ArrayBuffer
|
||||
*/
|
||||
invokeCallback(handle, methodId, argsArrayBuffer) {
|
||||
try {
|
||||
this.#invokeCallbackInner(handle, methodId, argsArrayBuffer);
|
||||
} catch (e) {
|
||||
console.error(`internal error invoking callback: ${e}`)
|
||||
}
|
||||
}
|
||||
|
||||
#invokeCallbackInner(handle, methodId, argsArrayBuffer) {
|
||||
const callbackObj = this.getCallbackObj(handle);
|
||||
if (callbackObj === undefined) {
|
||||
throw new UniFFIError(`${this.#name}: invalid callback handle id: ${handle}`);
|
||||
}
|
||||
|
||||
// Special-cased drop method, remove the object from the handle map and
|
||||
// return an empty array buffer
|
||||
if (methodId == 0) {
|
||||
this.#handleMap.delete(handle);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the method data, converting from 1-based indexing
|
||||
const methodHandler = this.#methodHandlers[methodId - 1];
|
||||
if (methodHandler === undefined) {
|
||||
throw new UniFFIError(`${this.#name}: invalid method id: ${methodId}`)
|
||||
}
|
||||
|
||||
methodHandler.call(callbackObj, argsArrayBuffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* xpcom-shutdown observer method
|
||||
*
|
||||
* This handles:
|
||||
* - Deregistering ourselves as the UniFFI callback handler
|
||||
* - Checks for any leftover stored callbacks which indicate memory leaks
|
||||
*/
|
||||
observe(aSubject, aTopic, aData) {
|
||||
if (aTopic == "xpcom-shutdown") {
|
||||
try {
|
||||
this.setAllowNewCallbacks(false);
|
||||
this.assertNoRegisteredCallbacks();
|
||||
UniFFIScaffolding.deregisterCallbackHandler(this.#interfaceId);
|
||||
} catch (ex) {
|
||||
console.error(`UniFFI Callback interface error during xpcom-shutdown: ${ex}`);
|
||||
Cc["@mozilla.org/xpcom/debug;1"]
|
||||
.getService(Ci.nsIDebug2)
|
||||
.abort(ex.filename, ex.lineNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles calling a single method for a callback interface
|
||||
*/
|
||||
class UniFFICallbackMethodHandler {
|
||||
#name;
|
||||
#argsConverters;
|
||||
|
||||
/**
|
||||
* Create a UniFFICallbackMethodHandler
|
||||
|
||||
* @param {string} name -- Name of the method to call on the callback object
|
||||
* @param {FfiConverter[]} argsConverters - FfiConverter for each argument type
|
||||
*/
|
||||
constructor(name, argsConverters) {
|
||||
this.#name = name;
|
||||
this.#argsConverters = argsConverters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke the method
|
||||
*
|
||||
* @param {obj} callbackObj -- Object implementing the callback interface for this method
|
||||
* @param {ArrayBuffer} argsArrayBuffer -- Arguments for the method, packed in an ArrayBuffer
|
||||
*/
|
||||
call(callbackObj, argsArrayBuffer) {
|
||||
const argsStream = new ArrayBufferDataStream(argsArrayBuffer);
|
||||
const args = this.#argsConverters.map(converter => converter.read(argsStream));
|
||||
callbackObj[this.#name](...args);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* UniFFICallbackHandler.handleMap entry
|
||||
*
|
||||
* @property callbackObj - Callback object, this must implement the callback interface.
|
||||
* @property {string} stackTrace - Stack trace from when the callback object was registered. This is used to proved extra context when debugging leaked callback objects.
|
||||
*/
|
||||
class UniFFICallbackHandleMapEntry {
|
||||
constructor(callbackObj, stackTrace) {
|
||||
this.callbackObj = callbackObj;
|
||||
this.stackTrace = stackTrace
|
||||
}
|
||||
}
|
|
@ -18,16 +18,19 @@ class {{ variant.name().to_upper_camel_case() }} extends {{ error.nm() }} {
|
|||
{{field.nm()}},
|
||||
{% endfor -%}
|
||||
...params
|
||||
) {
|
||||
super(...params);
|
||||
{%- for field in variant.fields() %}
|
||||
this.{{field.nm()}} = {{ field.nm() }};
|
||||
{%- endfor %}
|
||||
}
|
||||
) {
|
||||
super(...params);
|
||||
{%- for field in variant.fields() %}
|
||||
this.{{field.nm()}} = {{ field.nm() }};
|
||||
{%- endfor %}
|
||||
}
|
||||
{%- endif %}
|
||||
toString() {
|
||||
return `{{ variant.name().to_upper_camel_case() }}: ${super.toString()}`
|
||||
}
|
||||
}
|
||||
EXPORTED_SYMBOLS.push("{{ variant.name().to_upper_camel_case() }}");
|
||||
{%-endfor %}
|
||||
{%- endfor %}
|
||||
|
||||
class {{ ffi_converter }} extends FfiConverterArrayBuffer {
|
||||
static read(dataStream) {
|
||||
|
@ -45,7 +48,34 @@ class {{ ffi_converter }} extends FfiConverterArrayBuffer {
|
|||
{%- endif %}
|
||||
{%- endfor %}
|
||||
default:
|
||||
return new Error("Unknown {{ error.nm() }} variant");
|
||||
throw new Error("Unknown {{ error.nm() }} variant");
|
||||
}
|
||||
}
|
||||
static computeSize(value) {
|
||||
// Size of the Int indicating the variant
|
||||
let totalSize = 4;
|
||||
{%- for variant in error.variants() %}
|
||||
if (value instanceof {{ variant.name().to_upper_camel_case() }}) {
|
||||
{%- for field in variant.fields() %}
|
||||
totalSize += {{ field.ffi_converter() }}.computeSize(value.{{ field.nm() }});
|
||||
{%- endfor %}
|
||||
return totalSize;
|
||||
}
|
||||
{%- endfor %}
|
||||
throw new Error("Unknown {{ error.nm() }} variant");
|
||||
}
|
||||
static write(dataStream, value) {
|
||||
{%- for variant in error.variants() %}
|
||||
if (value instanceof {{ variant.name().to_upper_camel_case() }}) {
|
||||
dataStream.writeInt32({{ loop.index }});
|
||||
{%- for field in variant.fields() %}
|
||||
{{ field.ffi_converter() }}.write(dataStream, value.{{ field.nm() }});
|
||||
{%- endfor %}
|
||||
return;
|
||||
}
|
||||
{%- endfor %}
|
||||
throw new Error("Unknown {{ error.nm() }} variant");
|
||||
}
|
||||
|
||||
static errorClass = {{ error.nm() }};
|
||||
}
|
||||
|
|
|
@ -94,7 +94,6 @@ class ArrayBufferDataStream {
|
|||
this.pos += 8;
|
||||
}
|
||||
|
||||
|
||||
readFloat32() {
|
||||
let rv = this.dataView.getFloat32(this.pos);
|
||||
this.pos += 4;
|
||||
|
@ -193,6 +192,10 @@ class UniFFIError {
|
|||
constructor(message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
toString() {
|
||||
return `UniFFIError: ${this.message}`
|
||||
}
|
||||
}
|
||||
|
||||
class UniFFIInternalError extends UniFFIError {}
|
||||
|
|
|
@ -14,7 +14,7 @@ class {{ object.nm() }} {
|
|||
}
|
||||
|
||||
{%- for cons in object.constructors() %}
|
||||
{%- if cons.is_async() %}
|
||||
{%- if object.is_constructor_async(config) %}
|
||||
/**
|
||||
* An async constructor for {{ object.nm() }}.
|
||||
*
|
||||
|
@ -29,13 +29,14 @@ class {{ object.nm() }} {
|
|||
*/
|
||||
{%- endif %}
|
||||
static {{ cons.nm() }}({{cons.arg_names()}}) {
|
||||
{%- call js::call_constructor(cons, type_) -%}
|
||||
{%- call js::call_constructor(cons, type_, object.is_constructor_async(config)) -%}
|
||||
}
|
||||
{%- endfor %}
|
||||
|
||||
{%- for meth in object.methods() %}
|
||||
|
||||
{{ meth.nm() }}({{ meth.arg_names() }}) {
|
||||
{%- call js::call_method(meth, type_, object) -%}
|
||||
{%- call js::call_method(meth, type_, object.is_method_async(meth, config)) %}
|
||||
}
|
||||
{%- endfor %}
|
||||
|
||||
|
|
|
@ -33,4 +33,3 @@ class {{ ffi_converter }} extends FfiConverterArrayBuffer {
|
|||
return 1 + {{ inner.ffi_converter() }}.computeSize(value)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
{%- if !ci.callback_interface_definitions().is_empty() %}
|
||||
{%- include "CallbackInterfaceRuntime.jsm" %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
{%- for type_ in ci.iter_types() %}
|
||||
{%- let ffi_converter = type_.ffi_converter() %}
|
||||
{%- match type_ %}
|
||||
|
@ -65,6 +70,9 @@
|
|||
{%- when Type::External with { name, crate_name } %}
|
||||
{%- include "ExternalType.jsm" %}
|
||||
|
||||
{%- when Type::CallbackInterface with (name) %}
|
||||
{%- include "CallbackInterface.jsm" %}
|
||||
|
||||
{%- else %}
|
||||
{#- TODO implement the other types #}
|
||||
|
||||
|
@ -74,3 +82,11 @@
|
|||
EXPORTED_SYMBOLS.push("{{ ffi_converter }}");
|
||||
|
||||
{% endfor %}
|
||||
|
||||
{%- if !ci.callback_interface_definitions().is_empty() %}
|
||||
// Define callback interface handlers, this must come after the type loop since they reference the FfiConverters defined above.
|
||||
|
||||
{% for cbi in ci.callback_interface_definitions() %}
|
||||
{%- include "CallbackInterfaceHandler.jsm" %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
|
|
@ -1,55 +1,55 @@
|
|||
{%- macro call_scaffolding_function(func) %}
|
||||
{%- call _call_scaffolding_function(func, func.return_type(), "") -%}
|
||||
{%- call _call_scaffolding_function(func, func.return_type(), "", func.is_async(config)) -%}
|
||||
{%- endmacro %}
|
||||
|
||||
{%- macro call_constructor(cons, object_type) %}
|
||||
{%- call _call_scaffolding_function(cons, Some(object_type), "") -%}
|
||||
{%- macro call_constructor(cons, object_type, is_async) %}
|
||||
{%- call _call_scaffolding_function(cons, Some(object_type), "", is_async) -%}
|
||||
{%- endmacro %}
|
||||
|
||||
{%- macro call_method(method, object_type) %}
|
||||
{%- call _call_scaffolding_function(method, method.return_type(), object_type.ffi_converter()) -%}
|
||||
{%- macro call_method(method, object_type, is_async) %}
|
||||
{%- call _call_scaffolding_function(method, method.return_type(), object_type.ffi_converter(), is_async) -%}
|
||||
{%- endmacro %}
|
||||
|
||||
{%- macro _call_scaffolding_function(func, return_type, receiver_ffi_converter) %}
|
||||
{%- match return_type %}
|
||||
{%- when Some with (return_type) %}
|
||||
const liftResult = (result) => {{ return_type.ffi_converter() }}.lift(result);
|
||||
{%- else %}
|
||||
const liftResult = (result) => undefined;
|
||||
{%- endmatch %}
|
||||
{%- match func.throws_type() %}
|
||||
{%- when Some with (err_type) %}
|
||||
const liftError = (data) => {{ err_type.ffi_converter() }}.lift(data);
|
||||
{%- else %}
|
||||
const liftError = null;
|
||||
{%- endmatch %}
|
||||
const functionCall = () => {
|
||||
{%- for arg in func.arguments() %}
|
||||
{{ arg.check_type() }};
|
||||
{%- endfor %}
|
||||
|
||||
{%- if func.is_async() %}
|
||||
return UniFFIScaffolding.callAsync(
|
||||
{%- macro _call_scaffolding_function(func, return_type, receiver_ffi_converter, is_async) %}
|
||||
{%- match return_type %}
|
||||
{%- when Some with (return_type) %}
|
||||
const liftResult = (result) => {{ return_type.ffi_converter() }}.lift(result);
|
||||
{%- else %}
|
||||
return UniFFIScaffolding.callSync(
|
||||
{%- endif %}
|
||||
{{ function_ids.get(ci, func.ffi_func()) }}, // {{ function_ids.name(ci, func.ffi_func()) }}
|
||||
{%- if receiver_ffi_converter != "" %}
|
||||
{{ receiver_ffi_converter }}.lower(this),
|
||||
{%- endif %}
|
||||
const liftResult = (result) => undefined;
|
||||
{%- endmatch %}
|
||||
{%- match func.throws_type() %}
|
||||
{%- when Some with (err_type) %}
|
||||
const liftError = (data) => {{ err_type.ffi_converter() }}.lift(data);
|
||||
{%- else %}
|
||||
const liftError = null;
|
||||
{%- endmatch %}
|
||||
const functionCall = () => {
|
||||
{%- for arg in func.arguments() %}
|
||||
{{ arg.lower_fn_name() }}({{ arg.nm() }}),
|
||||
{{ arg.check_type() }};
|
||||
{%- endfor %}
|
||||
)
|
||||
}
|
||||
|
||||
{%- if func.is_async() %}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
{%- else %}
|
||||
return handleRustResult(functionCall(), liftResult, liftError);
|
||||
{%- endif %}
|
||||
{%- if is_async %}
|
||||
return UniFFIScaffolding.callAsync(
|
||||
{%- else %}
|
||||
return UniFFIScaffolding.callSync(
|
||||
{%- endif %}
|
||||
{{ function_ids.get(ci, func.ffi_func()) }}, // {{ function_ids.name(ci, func.ffi_func()) }}
|
||||
{%- if receiver_ffi_converter != "" %}
|
||||
{{ receiver_ffi_converter }}.lower(this),
|
||||
{%- endif %}
|
||||
{%- for arg in func.arguments() %}
|
||||
{{ arg.lower_fn() }}({{ arg.nm() }}),
|
||||
{%- endfor %}
|
||||
)
|
||||
}
|
||||
|
||||
{%- if is_async %}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
{%- else %}
|
||||
return handleRustResult(functionCall(), liftResult, liftError);
|
||||
{%- endif %}
|
||||
{%- endmacro %}
|
||||
|
|
|
@ -5,7 +5,10 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
var EXPORTED_SYMBOLS = [];
|
||||
// Objects intended to be used in the unit tests
|
||||
var UnitTestObjs = {};
|
||||
|
||||
var EXPORTED_SYMBOLS = ["UnitTestObjs"];
|
||||
|
||||
{% include "Helpers.jsm" %}
|
||||
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
[package]
|
||||
name = "uniffi-fixture-callbacks"
|
||||
edition = "2021"
|
||||
version = "0.21.0"
|
||||
authors = ["Firefox Sync Team <sync-team@mozilla.com>"]
|
||||
license = "MPL-2.0"
|
||||
publish = false
|
||||
|
||||
[dependencies]
|
||||
uniffi_macros = "0.21"
|
||||
uniffi = "0.21"
|
||||
thiserror = "1.0"
|
||||
|
||||
[build-dependencies]
|
||||
uniffi_build = "0.21"
|
|
@ -0,0 +1,7 @@
|
|||
/* 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/. */
|
||||
|
||||
fn main() {
|
||||
uniffi_build::generate_scaffolding("./src/callbacks.udl").unwrap();
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
callback interface Logger {
|
||||
void log(string message);
|
||||
void finished();
|
||||
};
|
||||
|
||||
namespace fixture_callbacks {
|
||||
// Log all even numbers in a vec, then call the finished() method
|
||||
void log_even_numbers(Logger logger, sequence<i32> items);
|
||||
// Works exactly the same as `log_even_numbers()`, except we configure this
|
||||
// to run on the main thread in `uniffi-bindgen-gecko-js/config.toml`
|
||||
void log_even_numbers_main_thread(Logger logger, sequence<i32> items);
|
||||
};
|
|
@ -0,0 +1,23 @@
|
|||
/* 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/. */
|
||||
|
||||
trait Logger {
|
||||
fn log(&self, message: String);
|
||||
fn finished(&self);
|
||||
}
|
||||
|
||||
fn log_even_numbers(logger: Box<dyn Logger>, items: Vec<i32>) {
|
||||
for i in items {
|
||||
if i % 2 == 0 {
|
||||
logger.log(format!("Saw even number: {i}"))
|
||||
}
|
||||
}
|
||||
logger.finished();
|
||||
}
|
||||
|
||||
fn log_even_numbers_main_thread(logger: Box<dyn Logger>, items: Vec<i32>) {
|
||||
log_even_numbers(logger, items)
|
||||
}
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/callbacks.uniffi.rs"));
|
|
@ -7,7 +7,7 @@ license = "MPL-2.0"
|
|||
publish = false
|
||||
|
||||
[dependencies]
|
||||
uniffi-example-geometry = { git = "https://github.com/mozilla/uniffi-rs.git", rev = "bb2039f077a29dba0879372a67e764e6ace8e33f" }
|
||||
uniffi-example-geometry = { git = "https://github.com/mozilla/uniffi-rs.git", rev = "846612a1d4fb5d11e246bf0682da4a499409424c" }
|
||||
uniffi_macros = "0.21"
|
||||
uniffi = "0.21"
|
||||
thiserror = "1.0"
|
||||
|
|
|
@ -0,0 +1,137 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsPrintfCString.h"
|
||||
#include "nsString.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "mozilla/dom/OwnedRustBuffer.h"
|
||||
#include "mozilla/dom/RootedDictionary.h"
|
||||
#include "mozilla/dom/UniFFIBinding.h"
|
||||
#include "mozilla/dom/UniFFICallbacks.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
|
||||
static mozilla::LazyLogModule UNIFFI_INVOKE_CALLBACK_LOGGER("uniffi");
|
||||
|
||||
namespace mozilla::uniffi {
|
||||
|
||||
using dom::ArrayBuffer;
|
||||
using dom::RootedDictionary;
|
||||
using dom::UniFFICallbackHandler;
|
||||
using dom::UniFFIScaffoldingCallCode;
|
||||
|
||||
static Maybe<CallbackInterfaceInfo> GetCallbackInterfaceInfo(
|
||||
uint64_t aInterfaceId) {
|
||||
const Maybe<CallbackInterfaceInfo> cbiInfo =
|
||||
UniFFIGetCallbackInterfaceInfo(aInterfaceId);
|
||||
#ifdef MOZ_UNIFFI_FIXTURES
|
||||
if (!cbiInfo) {
|
||||
return UniFFIFixturesGetCallbackInterfaceInfo(aInterfaceId);
|
||||
}
|
||||
#endif
|
||||
return cbiInfo;
|
||||
}
|
||||
|
||||
void RegisterCallbackHandler(uint64_t aInterfaceId,
|
||||
UniFFICallbackHandler& aCallbackHandler,
|
||||
ErrorResult& aError) {
|
||||
// We should only be mutating mHandler on the main thread
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
Maybe<CallbackInterfaceInfo> cbiInfo = GetCallbackInterfaceInfo(aInterfaceId);
|
||||
if (!cbiInfo.isSome()) {
|
||||
aError.ThrowUnknownError(
|
||||
nsPrintfCString("Unknown interface id: %" PRIu64, aInterfaceId));
|
||||
return;
|
||||
}
|
||||
|
||||
if (*cbiInfo->mHandler) {
|
||||
MOZ_LOG(UNIFFI_INVOKE_CALLBACK_LOGGER, LogLevel::Error,
|
||||
("[UniFFI] Callback handler already registered for %s",
|
||||
cbiInfo->mName));
|
||||
return;
|
||||
}
|
||||
*cbiInfo->mHandler = &aCallbackHandler;
|
||||
RustCallStatus status = {0};
|
||||
cbiInfo->mInitForeignCallback(cbiInfo->mForeignCallback, &status);
|
||||
// Just use MOZ_DIAGNOSTIC_ASSERT to check the status, since the call should
|
||||
// always succeed. The RustCallStatus out param only exists because UniFFI
|
||||
// adds it to all FFI calls.
|
||||
MOZ_DIAGNOSTIC_ASSERT(status.code == RUST_CALL_SUCCESS);
|
||||
}
|
||||
|
||||
void DeregisterCallbackHandler(uint64_t aInterfaceId, ErrorResult& aError) {
|
||||
// We should only be mutating mHandler on the main thread
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
Maybe<CallbackInterfaceInfo> cbiInfo = GetCallbackInterfaceInfo(aInterfaceId);
|
||||
if (!cbiInfo.isSome()) {
|
||||
aError.ThrowUnknownError(
|
||||
nsPrintfCString("Unknown interface id: %" PRIu64, aInterfaceId));
|
||||
return;
|
||||
}
|
||||
*cbiInfo->mHandler = nullptr;
|
||||
}
|
||||
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
static void QueueCallbackInner(uint64_t aInterfaceId, uint64_t aHandle,
|
||||
uint32_t aMethod, OwnedRustBuffer aArgs) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
Maybe<CallbackInterfaceInfo> cbiInfo = GetCallbackInterfaceInfo(aInterfaceId);
|
||||
if (!cbiInfo.isSome()) {
|
||||
MOZ_LOG(UNIFFI_INVOKE_CALLBACK_LOGGER, LogLevel::Error,
|
||||
("[UniFFI] Unknown inferface id: %" PRIu64, aInterfaceId));
|
||||
return;
|
||||
}
|
||||
|
||||
// Take our own reference to the callback handler to ensure that it stays
|
||||
// alive for the duration of this call
|
||||
RefPtr<UniFFICallbackHandler> ihandler = *cbiInfo->mHandler;
|
||||
|
||||
if (!ihandler) {
|
||||
MOZ_LOG(UNIFFI_INVOKE_CALLBACK_LOGGER, LogLevel::Error,
|
||||
("[UniFFI] JS handler for %s not registered", cbiInfo->mName));
|
||||
return;
|
||||
}
|
||||
|
||||
JSObject* global = ihandler->CallbackGlobalOrNull();
|
||||
if (!global) {
|
||||
MOZ_LOG(UNIFFI_INVOKE_CALLBACK_LOGGER, LogLevel::Error,
|
||||
("[UniFFI] JS handler for %s has null global", cbiInfo->mName));
|
||||
return;
|
||||
}
|
||||
|
||||
dom::AutoEntryScript aes(global, cbiInfo->mName);
|
||||
IgnoredErrorResult error;
|
||||
JS::Rooted<JSObject*> args(aes.cx(), aArgs.IntoArrayBuffer(aes.cx()));
|
||||
|
||||
ihandler->Call(aHandle, aMethod, args, error);
|
||||
|
||||
if (error.Failed()) {
|
||||
MOZ_LOG(UNIFFI_INVOKE_CALLBACK_LOGGER, LogLevel::Error,
|
||||
("[UniFFI] Error invoking JS handler for %s", cbiInfo->mName));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void QueueCallback(uint64_t aInterfaceId, uint64_t aHandle, uint32_t aMethod,
|
||||
RustBuffer aArgs) {
|
||||
nsresult dispatchResult =
|
||||
GetMainThreadSerialEventTarget()->Dispatch(NS_NewRunnableFunction(
|
||||
"UniFFI callback", [=]() MOZ_CAN_RUN_SCRIPT_BOUNDARY {
|
||||
QueueCallbackInner(aInterfaceId, aHandle, aMethod,
|
||||
OwnedRustBuffer(aArgs));
|
||||
}));
|
||||
|
||||
if (NS_FAILED(dispatchResult)) {
|
||||
MOZ_LOG(UNIFFI_INVOKE_CALLBACK_LOGGER, LogLevel::Error,
|
||||
("[UniFFI] Error dispatching UniFFI callback task"));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mozilla::uniffi
|
|
@ -0,0 +1,75 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_UniFFICallbacks_h
|
||||
#define mozilla_UniFFICallbacks_h
|
||||
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "mozilla/dom/UniFFIRust.h"
|
||||
#include "mozilla/dom/UniFFIScaffolding.h"
|
||||
|
||||
namespace mozilla::uniffi {
|
||||
|
||||
/**
|
||||
* UniFFI-generated scaffolding function to initialize a callback interface
|
||||
*
|
||||
* The Rust code expests us to pass it a ForeignCallback entrypoint for each
|
||||
* callback interface.
|
||||
*/
|
||||
typedef void (*CallbackInitFunc)(ForeignCallback, RustCallStatus*);
|
||||
|
||||
/**
|
||||
* All the information needed to handle a callback interface.
|
||||
*
|
||||
* The generated code includes a function that maps interface ids to one of
|
||||
* these structs
|
||||
*/
|
||||
struct CallbackInterfaceInfo {
|
||||
// Human-friendly name
|
||||
const char* mName;
|
||||
// JS handler
|
||||
StaticRefPtr<dom::UniFFICallbackHandler>* mHandler;
|
||||
// Handler function, defined in the generated C++ code
|
||||
ForeignCallback mForeignCallback;
|
||||
// Init function, defined in the generated Rust scaffolding. mForeignCallback
|
||||
// should be passed to this.
|
||||
CallbackInitFunc mInitForeignCallback;
|
||||
};
|
||||
|
||||
Maybe<CallbackInterfaceInfo> UniFFIGetCallbackInterfaceInfo(
|
||||
uint64_t aInterfaceId);
|
||||
|
||||
#ifdef MOZ_UNIFFI_FIXTURES
|
||||
Maybe<CallbackInterfaceInfo> UniFFIFixturesGetCallbackInterfaceInfo(
|
||||
uint64_t aInterfaceId);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Register the JS handler for a callback interface
|
||||
*/
|
||||
void RegisterCallbackHandler(uint64_t aInterfaceId,
|
||||
dom::UniFFICallbackHandler& aCallbackHandler,
|
||||
ErrorResult& aError);
|
||||
|
||||
/**
|
||||
* Deregister the JS handler for a callback interface
|
||||
*/
|
||||
void DeregisterCallbackHandler(uint64_t aInterfaceId, ErrorResult& aError);
|
||||
|
||||
/**
|
||||
* Queue a UniFFI callback interface function to run at some point
|
||||
*
|
||||
* This function is for fire-and-forget callbacks where the caller doesn't care
|
||||
* about the return value and doesn't want to wait for the call to finish. A
|
||||
* good use case for this is logging.
|
||||
*/
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
void QueueCallback(size_t aInterfaceId, uint64_t aHandle, uint32_t aMethod,
|
||||
RustBuffer aArgs);
|
||||
|
||||
} // namespace mozilla::uniffi
|
||||
|
||||
#endif // mozilla_UniFFICallbacks_h
|
|
@ -2,18 +2,23 @@
|
|||
|
||||
#include "nsString.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "mozilla/dom/UniFFICallbacks.h"
|
||||
#include "mozilla/dom/UniFFIScaffolding.h"
|
||||
#include "mozilla/dom/ScaffoldingCall.h"
|
||||
|
||||
namespace mozilla::uniffi {
|
||||
|
||||
using dom::ArrayBuffer;
|
||||
using dom::AutoEntryScript;
|
||||
using dom::GlobalObject;
|
||||
using dom::RootedDictionary;
|
||||
using dom::Promise;
|
||||
using dom::ScaffoldingType;
|
||||
using dom::Sequence;
|
||||
using dom::UniFFICallbackHandler;
|
||||
using dom::UniFFIPointer;
|
||||
using dom::UniFFIScaffoldingCallResult;
|
||||
|
||||
|
@ -111,6 +116,9 @@ extern "C" {
|
|||
RustBuffer todolist_aa33_get_default_list(RustCallStatus*);
|
||||
void todolist_aa33_set_default_list(void *, RustCallStatus*);
|
||||
RustBuffer todolist_aa33_create_entry_with(RustBuffer, RustCallStatus*);
|
||||
void ffi_fixture_callbacks_1107_Logger_init_callback(ForeignCallback, RustCallStatus*);
|
||||
void fixture_callbacks_1107_log_even_numbers(uint64_t, RustBuffer, RustCallStatus*);
|
||||
void fixture_callbacks_1107_log_even_numbers_main_thread(uint64_t, RustBuffer, RustCallStatus*);
|
||||
RustBuffer custom_types_8ecd_get_custom_types_demo(RustBuffer, RustCallStatus*);
|
||||
double external_types_54cc_gradient(RustBuffer, RustCallStatus*);
|
||||
}
|
||||
|
@ -137,6 +145,36 @@ const static mozilla::uniffi::UniFFIPointerType kTodolistTodoListPointerType {
|
|||
ffi_todolist_aa33_TodoList_object_free
|
||||
};
|
||||
|
||||
// Define the data we need per-callback interface
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
extern "C" int UniFFIFixturesCallbackHandlerLogger(uint64_t aHandle, uint32_t aMethod, RustBuffer aArgs, RustBuffer* aOutBuffer) {
|
||||
// Currently, we only support "fire-and-forget" async callbacks. These are
|
||||
// callbacks that run asynchronously without returning anything. The main
|
||||
// use case for callbacks is logging, which fits very well with this model.
|
||||
//
|
||||
// So, here we simple queue the callback and return immediately.
|
||||
mozilla::uniffi::QueueCallback(0, aHandle, aMethod, aArgs);
|
||||
return CALLBACK_INTERFACE_SUCCESS;
|
||||
}
|
||||
static StaticRefPtr<dom::UniFFICallbackHandler> JS_CALLBACK_HANDLER_LOGGER;
|
||||
|
||||
// Define a lookup function for our callback interface info
|
||||
Maybe<CallbackInterfaceInfo> UniFFIFixturesGetCallbackInterfaceInfo(uint64_t aInterfaceId) {
|
||||
switch(aInterfaceId) {
|
||||
case 0: { // fixture_callbacks:Logger
|
||||
return Some(CallbackInterfaceInfo {
|
||||
"Logger",
|
||||
&JS_CALLBACK_HANDLER_LOGGER,
|
||||
UniFFIFixturesCallbackHandlerLogger,
|
||||
ffi_fixture_callbacks_1107_Logger_init_callback,
|
||||
});
|
||||
}
|
||||
|
||||
default:
|
||||
return Nothing();
|
||||
}
|
||||
}
|
||||
|
||||
Maybe<already_AddRefed<Promise>> UniFFIFixturesCallAsync(const GlobalObject& aGlobal, uint64_t aId, const Sequence<ScaffoldingType>& aArgs, ErrorResult& aError) {
|
||||
switch (aId) {
|
||||
case 20: { // geometry:geometry_1cce_gradient
|
||||
|
@ -487,11 +525,19 @@ Maybe<already_AddRefed<Promise>> UniFFIFixturesCallAsync(const GlobalObject& aGl
|
|||
using CallHandler = ScaffoldingCallHandler<ScaffoldingConverter<RustBuffer>, ScaffoldingConverter<RustBuffer>>;
|
||||
return Some(CallHandler::CallAsync(todolist_aa33_create_entry_with, aGlobal, aArgs, "todolist_aa33_create_entry_with: "_ns, aError));
|
||||
}
|
||||
case 107: { // custom_types:custom_types_8ecd_get_custom_types_demo
|
||||
case 107: { // fixture_callbacks:fixture_callbacks_1107_log_even_numbers
|
||||
using CallHandler = ScaffoldingCallHandler<ScaffoldingConverter<void>, ScaffoldingConverter<uint64_t>, ScaffoldingConverter<RustBuffer>>;
|
||||
return Some(CallHandler::CallAsync(fixture_callbacks_1107_log_even_numbers, aGlobal, aArgs, "fixture_callbacks_1107_log_even_numbers: "_ns, aError));
|
||||
}
|
||||
case 108: { // fixture_callbacks:fixture_callbacks_1107_log_even_numbers_main_thread
|
||||
using CallHandler = ScaffoldingCallHandler<ScaffoldingConverter<void>, ScaffoldingConverter<uint64_t>, ScaffoldingConverter<RustBuffer>>;
|
||||
return Some(CallHandler::CallAsync(fixture_callbacks_1107_log_even_numbers_main_thread, aGlobal, aArgs, "fixture_callbacks_1107_log_even_numbers_main_thread: "_ns, aError));
|
||||
}
|
||||
case 109: { // custom_types:custom_types_8ecd_get_custom_types_demo
|
||||
using CallHandler = ScaffoldingCallHandler<ScaffoldingConverter<RustBuffer>, ScaffoldingConverter<RustBuffer>>;
|
||||
return Some(CallHandler::CallAsync(custom_types_8ecd_get_custom_types_demo, aGlobal, aArgs, "custom_types_8ecd_get_custom_types_demo: "_ns, aError));
|
||||
}
|
||||
case 108: { // external_types:external_types_54cc_gradient
|
||||
case 110: { // external_types:external_types_54cc_gradient
|
||||
using CallHandler = ScaffoldingCallHandler<ScaffoldingConverter<double>, ScaffoldingConverter<RustBuffer>>;
|
||||
return Some(CallHandler::CallAsync(external_types_54cc_gradient, aGlobal, aArgs, "external_types_54cc_gradient: "_ns, aError));
|
||||
}
|
||||
|
@ -936,12 +982,22 @@ bool UniFFIFixturesCallSync(const GlobalObject& aGlobal, uint64_t aId, const Seq
|
|||
CallHandler::CallSync(todolist_aa33_create_entry_with, aGlobal, aArgs, aReturnValue, "todolist_aa33_create_entry_with: "_ns, aError);
|
||||
return true;
|
||||
}
|
||||
case 107: { // custom_types:custom_types_8ecd_get_custom_types_demo
|
||||
case 107: { // fixture_callbacks:fixture_callbacks_1107_log_even_numbers
|
||||
using CallHandler = ScaffoldingCallHandler<ScaffoldingConverter<void>, ScaffoldingConverter<uint64_t>, ScaffoldingConverter<RustBuffer>>;
|
||||
CallHandler::CallSync(fixture_callbacks_1107_log_even_numbers, aGlobal, aArgs, aReturnValue, "fixture_callbacks_1107_log_even_numbers: "_ns, aError);
|
||||
return true;
|
||||
}
|
||||
case 108: { // fixture_callbacks:fixture_callbacks_1107_log_even_numbers_main_thread
|
||||
using CallHandler = ScaffoldingCallHandler<ScaffoldingConverter<void>, ScaffoldingConverter<uint64_t>, ScaffoldingConverter<RustBuffer>>;
|
||||
CallHandler::CallSync(fixture_callbacks_1107_log_even_numbers_main_thread, aGlobal, aArgs, aReturnValue, "fixture_callbacks_1107_log_even_numbers_main_thread: "_ns, aError);
|
||||
return true;
|
||||
}
|
||||
case 109: { // custom_types:custom_types_8ecd_get_custom_types_demo
|
||||
using CallHandler = ScaffoldingCallHandler<ScaffoldingConverter<RustBuffer>, ScaffoldingConverter<RustBuffer>>;
|
||||
CallHandler::CallSync(custom_types_8ecd_get_custom_types_demo, aGlobal, aArgs, aReturnValue, "custom_types_8ecd_get_custom_types_demo: "_ns, aError);
|
||||
return true;
|
||||
}
|
||||
case 108: { // external_types:external_types_54cc_gradient
|
||||
case 110: { // external_types:external_types_54cc_gradient
|
||||
using CallHandler = ScaffoldingCallHandler<ScaffoldingConverter<double>, ScaffoldingConverter<RustBuffer>>;
|
||||
CallHandler::CallSync(external_types_54cc_gradient, aGlobal, aArgs, aReturnValue, "external_types_54cc_gradient: "_ns, aError);
|
||||
return true;
|
||||
|
|
|
@ -2,18 +2,23 @@
|
|||
|
||||
#include "nsString.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "mozilla/dom/UniFFICallbacks.h"
|
||||
#include "mozilla/dom/UniFFIScaffolding.h"
|
||||
#include "mozilla/dom/ScaffoldingCall.h"
|
||||
|
||||
namespace mozilla::uniffi {
|
||||
|
||||
using dom::ArrayBuffer;
|
||||
using dom::AutoEntryScript;
|
||||
using dom::GlobalObject;
|
||||
using dom::RootedDictionary;
|
||||
using dom::Promise;
|
||||
using dom::ScaffoldingType;
|
||||
using dom::Sequence;
|
||||
using dom::UniFFICallbackHandler;
|
||||
using dom::UniFFIPointer;
|
||||
using dom::UniFFIScaffoldingCallResult;
|
||||
|
||||
|
@ -53,6 +58,17 @@ const static mozilla::uniffi::UniFFIPointerType kTabsTabsBridgedEnginePointerTyp
|
|||
ffi_tabs_edc9_TabsBridgedEngine_object_free
|
||||
};
|
||||
|
||||
// Define the data we need per-callback interface
|
||||
|
||||
// Define a lookup function for our callback interface info
|
||||
Maybe<CallbackInterfaceInfo> UniFFIGetCallbackInterfaceInfo(uint64_t aInterfaceId) {
|
||||
switch(aInterfaceId) {
|
||||
|
||||
default:
|
||||
return Nothing();
|
||||
}
|
||||
}
|
||||
|
||||
Maybe<already_AddRefed<Promise>> UniFFICallAsync(const GlobalObject& aGlobal, uint64_t aId, const Sequence<ScaffoldingType>& aArgs, ErrorResult& aError) {
|
||||
switch (aId) {
|
||||
case 0: { // tabs:tabs_edc9_TabsStore_new
|
||||
|
|
|
@ -18,6 +18,13 @@ constexpr int8_t RUST_CALL_SUCCESS = 0;
|
|||
constexpr int8_t RUST_CALL_ERROR = 1;
|
||||
constexpr int8_t RUST_CALL_INTERNAL_ERROR = 2;
|
||||
|
||||
// Return values for callback interfaces (See
|
||||
// https://github.com/mozilla/uniffi-rs/blob/main/uniffi/src/ffi/foreigncallbacks.rs
|
||||
// for details)
|
||||
constexpr int8_t CALLBACK_INTERFACE_SUCCESS = 1;
|
||||
constexpr int8_t CALLBACK_INTERFACE_INTERNAL_ERROR = -1;
|
||||
constexpr int8_t CALLBACK_INTERFACE_ERROR = -2;
|
||||
|
||||
// structs/functions from UniFFI
|
||||
extern "C" {
|
||||
struct RustBuffer {
|
||||
|
@ -31,6 +38,9 @@ struct RustCallStatus {
|
|||
RustBuffer error_buf;
|
||||
};
|
||||
|
||||
typedef int (*ForeignCallback)(uint64_t handle, uint32_t method,
|
||||
RustBuffer args, RustBuffer* buf_ptr);
|
||||
|
||||
RustBuffer uniffi_rustbuffer_alloc(int32_t size, RustCallStatus* call_status);
|
||||
void uniffi_rustbuffer_free(RustBuffer buf, RustCallStatus* call_status);
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "nsPrintfCString.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/dom/UniFFIScaffolding.h"
|
||||
#include "mozilla/dom/UniFFICallbacks.h"
|
||||
|
||||
// This file implements the UniFFI WebIDL interface by leveraging the generate
|
||||
// code in UniFFIScaffolding.cpp and UniFFIFixtureScaffolding.cpp. It's main
|
||||
|
@ -22,6 +23,7 @@ using mozilla::dom::Promise;
|
|||
using mozilla::dom::RootedDictionary;
|
||||
using mozilla::dom::ScaffoldingType;
|
||||
using mozilla::dom::Sequence;
|
||||
using mozilla::dom::UniFFICallbackHandler;
|
||||
using mozilla::dom::UniFFIPointer;
|
||||
using mozilla::dom::UniFFIScaffoldingCallResult;
|
||||
|
||||
|
@ -145,4 +147,16 @@ void UniFFIScaffolding::WritePointer(const GlobalObject& aGlobal, uint64_t aId,
|
|||
aError.ThrowUnknownError(nsPrintfCString("Unknown object id: %" PRIu64, aId));
|
||||
}
|
||||
|
||||
void UniFFIScaffolding::RegisterCallbackHandler(
|
||||
GlobalObject& aGlobal, uint64_t aInterfaceId,
|
||||
UniFFICallbackHandler& aCallbackHandler, ErrorResult& aError) {
|
||||
uniffi::RegisterCallbackHandler(aInterfaceId, aCallbackHandler, aError);
|
||||
}
|
||||
|
||||
void UniFFIScaffolding::DeregisterCallbackHandler(GlobalObject& aGlobal,
|
||||
uint64_t aInterfaceId,
|
||||
ErrorResult& aError) {
|
||||
uniffi::DeregisterCallbackHandler(aInterfaceId, aError);
|
||||
}
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
|
|
@ -20,23 +20,31 @@ using ScaffoldingType = OwningDoubleOrArrayBufferOrUniFFIPointer;
|
|||
class UniFFIScaffolding {
|
||||
public:
|
||||
static already_AddRefed<Promise> CallAsync(
|
||||
const GlobalObject& aUniFFIGlobal, uint64_t aId,
|
||||
const Sequence<ScaffoldingType>& aArgs, ErrorResult& aUniFFIErrorResult);
|
||||
const GlobalObject& aGlobal, uint64_t aId,
|
||||
const Sequence<ScaffoldingType>& aArgs, ErrorResult& aErrorResult);
|
||||
|
||||
static void CallSync(
|
||||
const GlobalObject& aUniFFIGlobal, uint64_t aId,
|
||||
const GlobalObject& aGlobal, uint64_t aId,
|
||||
const Sequence<ScaffoldingType>& aArgs,
|
||||
RootedDictionary<UniFFIScaffoldingCallResult>& aUniFFIReturnValue,
|
||||
ErrorResult& aUniFFIErrorResult);
|
||||
RootedDictionary<UniFFIScaffoldingCallResult>& aReturnValue,
|
||||
ErrorResult& aErrorResult);
|
||||
|
||||
static already_AddRefed<UniFFIPointer> ReadPointer(
|
||||
const GlobalObject& aUniFFIGlobal, uint64_t aId,
|
||||
const ArrayBuffer& aArrayBuff, long aPosition, ErrorResult& aError);
|
||||
const GlobalObject& aGlobal, uint64_t aId, const ArrayBuffer& aArrayBuff,
|
||||
long aPosition, ErrorResult& aError);
|
||||
|
||||
static void WritePointer(const GlobalObject& aUniFFIGlobal, uint64_t aId,
|
||||
static void WritePointer(const GlobalObject& aGlobal, uint64_t aId,
|
||||
const UniFFIPointer& aPtr,
|
||||
const ArrayBuffer& aArrayBuff, long aPosition,
|
||||
ErrorResult& aError);
|
||||
|
||||
static void RegisterCallbackHandler(GlobalObject& aGlobal,
|
||||
uint64_t interfaceId,
|
||||
UniFFICallbackHandler& aCallbackHandler,
|
||||
ErrorResult& aError);
|
||||
static void DeregisterCallbackHandler(GlobalObject& aGlobal,
|
||||
uint64_t interfaceId,
|
||||
ErrorResult& aError);
|
||||
};
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
|
|
@ -8,6 +8,7 @@ FINAL_LIBRARY = "xul"
|
|||
|
||||
UNIFIED_SOURCES += [
|
||||
"OwnedRustBuffer.cpp",
|
||||
"UniFFICallbacks.cpp",
|
||||
"UniFFIGeneratedScaffolding.cpp",
|
||||
"UniFFIPointer.cpp",
|
||||
"UniFFIScaffolding.cpp",
|
||||
|
@ -23,6 +24,7 @@ EXPORTS.mozilla.dom += [
|
|||
"OwnedRustBuffer.h",
|
||||
"ScaffoldingCall.h",
|
||||
"ScaffoldingConverter.h",
|
||||
"UniFFICallbacks.h",
|
||||
"UniFFIPointer.h",
|
||||
"UniFFIPointerType.h",
|
||||
"UniFFIRust.h",
|
||||
|
|
|
@ -75,12 +75,13 @@ origin-trials-ffi = { path = "../../../../dom/origin-trials/ffi" }
|
|||
jog = { path = "../../../components/glean/bindings/jog" }
|
||||
dap_ffi = { path = "../../../components/telemetry/dap/ffi" }
|
||||
data-encoding-ffi = { path = "../../../../dom/fs/parent/rust/data-encoding-ffi" }
|
||||
uniffi-example-arithmetic = { git = "https://github.com/mozilla/uniffi-rs.git", rev = "bb2039f077a29dba0879372a67e764e6ace8e33f", optional = true }
|
||||
uniffi-example-geometry = { git = "https://github.com/mozilla/uniffi-rs.git", rev = "bb2039f077a29dba0879372a67e764e6ace8e33f", optional = true }
|
||||
uniffi-example-rondpoint = { git = "https://github.com/mozilla/uniffi-rs.git", rev = "bb2039f077a29dba0879372a67e764e6ace8e33f", optional = true }
|
||||
uniffi-example-sprites = { git = "https://github.com/mozilla/uniffi-rs.git", rev = "bb2039f077a29dba0879372a67e764e6ace8e33f", optional = true }
|
||||
uniffi-example-todolist = { git = "https://github.com/mozilla/uniffi-rs.git", rev = "bb2039f077a29dba0879372a67e764e6ace8e33f", optional = true }
|
||||
uniffi-example-arithmetic = { git = "https://github.com/mozilla/uniffi-rs.git", rev = "846612a1d4fb5d11e246bf0682da4a499409424c", optional = true }
|
||||
uniffi-example-geometry = { git = "https://github.com/mozilla/uniffi-rs.git", rev = "846612a1d4fb5d11e246bf0682da4a499409424c", optional = true }
|
||||
uniffi-example-rondpoint = { git = "https://github.com/mozilla/uniffi-rs.git", rev = "846612a1d4fb5d11e246bf0682da4a499409424c", optional = true }
|
||||
uniffi-example-sprites = { git = "https://github.com/mozilla/uniffi-rs.git", rev = "846612a1d4fb5d11e246bf0682da4a499409424c", optional = true }
|
||||
uniffi-example-todolist = { git = "https://github.com/mozilla/uniffi-rs.git", rev = "846612a1d4fb5d11e246bf0682da4a499409424c", optional = true }
|
||||
uniffi-example-custom-types = { path = "../../../components/uniffi-example-custom-types/", optional = true }
|
||||
uniffi-fixture-callbacks = { path = "../../../components/uniffi-fixture-callbacks/", optional = true }
|
||||
uniffi-fixture-external-types = { path = "../../../components/uniffi-fixture-external-types/", optional = true }
|
||||
binary_http = { path = "../../../../netwerk/protocol/http/binary_http" }
|
||||
oblivious_http = { path = "../../../../netwerk/protocol/http/oblivious_http" }
|
||||
|
@ -146,7 +147,8 @@ with_dbus = ["audio_thread_priority/with_dbus"]
|
|||
thread_sanitizer = ["xpcom/thread_sanitizer"]
|
||||
uniffi_fixtures = [
|
||||
"uniffi-example-arithmetic", "uniffi-example-geometry", "uniffi-example-rondpoint", "uniffi-example-sprites",
|
||||
"uniffi-example-todolist", "uniffi-example-custom-types", "uniffi-fixture-external-types",
|
||||
"uniffi-example-todolist", "uniffi-example-custom-types", "uniffi-fixture-callbacks",
|
||||
"uniffi-fixture-external-types",
|
||||
]
|
||||
webmidi_midir_impl = ["midir_impl"]
|
||||
|
||||
|
|
|
@ -70,9 +70,9 @@ extern crate mdns_service;
|
|||
extern crate neqo_glue;
|
||||
extern crate wgpu_bindings;
|
||||
|
||||
extern crate aa_stroke;
|
||||
extern crate qcms;
|
||||
extern crate wpf_gpu_raster;
|
||||
extern crate aa_stroke;
|
||||
|
||||
extern crate unic_langid;
|
||||
extern crate unic_langid_ffi;
|
||||
|
@ -121,6 +121,7 @@ mod uniffi_fixtures {
|
|||
extern crate uniffi_todolist;
|
||||
|
||||
arithmetical::uniffi_reexport_scaffolding!();
|
||||
uniffi_fixture_callbacks::uniffi_reexport_scaffolding!();
|
||||
uniffi_custom_types::uniffi_reexport_scaffolding!();
|
||||
uniffi_fixture_external_types::uniffi_reexport_scaffolding!();
|
||||
uniffi_geometry::uniffi_reexport_scaffolding!();
|
||||
|
|
Загрузка…
Ссылка в новой задаче