skylerlipthay / ducc Goto Github PK
View Code? Open in Web Editor NEWRust bindings for Duktape, the embedded JavaScript engine
License: MIT License
Rust bindings for Duktape, the embedded JavaScript engine
License: MIT License
Currently, Ducc::new()
always creates a new Duktape heap for the context. However, this means values cannot be shared across contexts except through serialization.
The Duktape guide has a section on contexts and heaps that describes how to create a context using a shared heap with duk_push_thread
or duk_push_thread_new_globalenv
.
For prior art, the v8-rs
crate exposes a similar concept with the Context
and Isolate
types. So, library users would first call Isolate::new()
to create a new isolated v8 instance (analogous to a Duktape heap), then Context::new(&isolate)
to create the context (analogous to a Duktape context).
I noticed a lot of warnings while trying to compile this library on stable rustc 1.39.0 (4560ea788 2019-11-04)
on Windows 10:
warning: trait objects without an explicit `dyn` are deprecated
--> ducc\src\ducc.rs:106:74
|
106 | pub fn set_user_data<K, T>(&mut self, key: K, data: T) -> Option<Box<Any + 'static>>
| ^^^^^^^^^^^^^ help: use `dyn`: `dyn Any + 'static`
|
= note: `#[warn(bare_trait_objects)]` on by default
warning: trait objects without an explicit `dyn` are deprecated
--> ducc\src\ducc.rs:132:65
|
132 | pub fn remove_user_data(&mut self, key: &str) -> Option<Box<Any + 'static>> {
| ^^^^^^^^^^^^^ help: use `dyn`: `dyn Any + 'static`
warning: trait objects without an explicit `dyn` are deprecated
--> ducc\src\ducc.rs:439:31
|
439 | pub cancel_fn: Option<Box<Fn() -> bool>>,
| ^^^^^^^^^^^^ help: use `dyn`: `dyn Fn() -> bool`
warning: trait objects without an explicit `dyn` are deprecated
--> ducc\src\error.rs:48:23
|
48 | ExternalError(Box<RuntimeError + 'static>),
| ^^^^^^^^^^^^^^^^^^^^^^ help: use `dyn`: `dyn RuntimeError + 'static`
warning: trait objects without an explicit `dyn` are deprecated
--> ducc\src\error.rs:307:6
|
307 | impl RuntimeError {
| ^^^^^^^^^^^^ help: use `dyn`: `dyn RuntimeError`
warning: trait objects without an explicit `dyn` are deprecated
--> ducc\src\error.rs:313:45
|
313 | unsafe { Some(&*(self as *const RuntimeError as *const T)) }
| ^^^^^^^^^^^^ help: use `dyn`: `dyn RuntimeError`
warning: trait objects without an explicit `dyn` are deprecated
--> ducc\src\types.rs:33:9
|
33 | Box<Fn(&'ducc Ducc, Value<'ducc>, Values<'ducc>) -> Result<Value<'ducc>> + 'a>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `dyn`: `dyn Fn(&'ducc Ducc, Value<'ducc>, Values<'ducc>) -> Result<Value<'ducc>> + 'a`
warning: trait objects without an explicit `dyn` are deprecated
--> ducc\src\types.rs:35:47
|
35 | pub(crate) type AnyMap = BTreeMap<String, Box<Any + 'static>>;
| ^^^^^^^^^^^^^ help: use `dyn`: `dyn Any + 'static`
warning: use of deprecated item 'std::sync::ONCE_INIT': the `new` function is now preferred
--> ducc\src\util.rs:8:23
|
8 | use std::sync::{Once, ONCE_INIT};
| ^^^^^^^^^
|
= note: `#[warn(deprecated)]` on by default
warning: use of deprecated item 'std::sync::ONCE_INIT': the `new` function is now preferred
--> ducc\src\util.rs:317:25
|
317 | static INIT: Once = ONCE_INIT;
| ^^^^^^^^^ help: replace the use of the deprecated item: `Once::new()`
warning: unused boxed boxed `std::ops::Fn` trait object that must be used
--> ducc\src\function.rs:118:9
|
118 | Box::from_raw(ffi::duk_get_pointer(ctx, -1) as *mut Callback);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(unused_must_use)]` on by default
= note: closures are lazy and do nothing unless called
Hey, great library! I have a usecase where I'm trying to store hooks (ducc::Function
s) inside userdata, so they can be called from Rust code later when needed. However, the 'static
lifetime requirement for userdata values is making this quite difficult.
How viable do you think it would be to change the set_user_data
data lifetime to for instance 'ducc
? As far as I understand, this would then make it possible to store Ducc values inside userdata.
Hello again!
Some code I'm writing would benefit from duk_def_prop, i.e. implementing properties with getters and setters straight in Rust. It's doable by calling defineProperty
in JS, but doing it in Rust might feel a bit nicer.
I would be open to implementing the feature, but I'm not sure what the API should look like since duk_def_prop
accepts quite a varying set of arguments.
When testing JS errors I found that there is not a clear way to handle this error without the program crashing.
Rust code:
use ducc::{Ducc, ExecSettings};
fn main() {
let ducc = Ducc::new();
ducc.exec("throw 'test'", None, ExecSettings::default()).unwrap()
}
Running this code on rust 1.42.0 stable-i686-pc-windows-msvc results in:
Running `target\debug\ducctest.exe`
fatal error from duktape: uncaught: 'cannot write property [Symbol hidden \x27?error\x27] of \x27test\x27'
error: process didn't exit successfully: `target\debug\ducctest.exe` (exit code: 0xc0000409, STATUS_STACK_BUFFER_OVERRUN)
Is there another way to wrap exec so that these errors can be handled? Thank you.
The library currently only works on Windows 7 if it was compiled on a Windows 7 (or older) machine. See this code from duk_config_default.h
:
/* GetSystemTimePreciseAsFileTime() available from Windows 8:
* https://msdn.microsoft.com/en-us/library/windows/desktop/hh706895(v=vs.85).aspx
*/
#if defined(DUK_USE_DATE_NOW_WINDOWS_SUBMS) || defined(DUK_USE_DATE_NOW_WINDOWS)
/* User forced provider. */
#else
#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0602)
#define DUK_USE_DATE_NOW_WINDOWS_SUBMS
#else
#define DUK_USE_DATE_NOW_WINDOWS
#endif
#endif
We use this library and ran into this issue, see latex-lsp/texlab#101. Therefore, it would be nice to have a feature flag for ducc
to enable Windows 7 support.
Hello there, I'm trying the following code:
use ducc::{Ducc};
fn main() {
let ducc = Ducc::new();
let func = ducc.create_function(|inv| {
let (a, b): (usize, usize) = inv.args.into(inv.ducc).uwrap();
Ok(a + b)
});
ducc.globals().set("add", func).unwrap();
}
But the following error occurs:
error: linking with `cc` failed: exit code: 1
|
= note: "cc" "-m64" "-L" "/Users/alanhoff/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib" "/Users/alanhoff/Projects/ductest/target/debug/deps/$uctest-4ed857ff77ff2a19.15uc7ccwcv2sggoy.rcgu.o" "/Users/alanhoff/Projects/ductest/target/debug/deps/ductest-4ed857ff77ff2a19.1h2mhh1lezhmpl1b.rcgu.o" "/Users/alanhoff/Projects/duc$est/target/debug/deps/ductest-4ed857ff77ff2a19.1o9sak0djwp0cu9n.rcgu.o" "/Users/alanhoff/Projects/ductest/target/debug/deps/ductest-4ed857ff77ff2a19.1tl0jw7in6toutg7.rcgu.o" "/User$/alanhoff/Projects/ductest/target/debug/deps/ductest-4ed857ff77ff2a19.204he97yf1e9g301.rcgu.o" "/Users/alanhoff/Projects/ductest/target/debug/deps/ductest-4ed857ff77ff2a19.2d212p7h$3vspiqx.rcgu.o" "/Users/alanhoff/Projects/ductest/target/debug/deps/ductest-4ed857ff77ff2a19.2kvknh1drs918t6p.rcgu.o" "/Users/alanhoff/Projects/ductest/target/debug/deps/ductest-4e$857ff77ff2a19.2tbbw9d7852eyw12.rcgu.o" "/Users/alanhoff/Projects/ductest/target/debug/deps/ductest-4ed857ff77ff2a19.35ntzgf66nbpfb7o.rcgu.o" "/Users/alanhoff/Projects/ductest/targe$/debug/deps/ductest-4ed857ff77ff2a19.36x511b9a354ayv.rcgu.o" "/Users/alanhoff/Projects/ductest/target/debug/deps/ductest-4ed857ff77ff2a19.3ewclrwmtpeldov8.rcgu.o" "/Users/alanhoff/$rojects/ductest/target/debug/deps/ductest-4ed857ff77ff2a19.3fut51dpensxzkbn.rcgu.o" "/Users/alanhoff/Projects/ductest/target/debug/deps/ductest-4ed857ff77ff2a19.3xts6afcmj37ti5j.rc$u.o" "/Users/alanhoff/Projects/ductest/target/debug/deps/ductest-4ed857ff77ff2a19.4f7hnqpd7k57m48q.rcgu.o" "/Users/alanhoff/Projects/ductest/target/debug/deps/ductest-4ed857ff77ff2$19.4ha6rjmfou7z0ced.rcgu.o" "/Users/alanhoff/Projects/ductest/target/debug/deps/ductest-4ed857ff77ff2a19.4muhw3oestqi42wo.rcgu.o" "/Users/alanhoff/Projects/ductest/target/debug/dep$/ductest-4ed857ff77ff2a19.59fpeycpfwwwbhlm.rcgu.o" "/Users/alanhoff/Projects/ductest/target/debug/deps/ductest-4ed857ff77ff2a19.5c9u4ogk35o2haqn.rcgu.o" "/Users/alanhoff/Projects/d$ctest/target/debug/deps/ductest-4ed857ff77ff2a19.dplgs6d9c1051ds.rcgu.o" "/Users/alanhoff/Projects/ductest/target/debug/deps/ductest-4ed857ff77ff2a19.x4ygs4r5khhuakb.rcgu.o" "-o" "$Users/alanhoff/Projects/ductest/target/debug/deps/ductest-4ed857ff77ff2a19" "/Users/alanhoff/Projects/ductest/target/debug/deps/ductest-4ed857ff77ff2a19.15n3gzqcp366zbjw.rcgu.o" "-$l,-dead_strip" "-nodefaultlibs" "-L" "/Users/alanhoff/Projects/ductest/target/debug/deps" "-L" "/Users/alanhoff/Projects/ductest/target/debug/build/ducc-sys-56fed41fa3b28b30/out" "$L" "/Users/alanhoff/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib" "/Users/alanhoff/Projects/ductest/target/debug/deps/libducc-41fdc7277bd506d2$rlib" "/Users/alanhoff/Projects/ductest/target/debug/deps/libducc_sys-6a7f687dcd36b241.rlib" "/Users/alanhoff/Projects/ductest/target/debug/deps/libcesu8-6b61ba793b4c8e70.rlib" "/U$ers/alanhoff/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libstd-d8e5437473efc55d.rlib" "/Users/alanhoff/.rustup/toolchains/nightly-x86_64-app$e-darwin/lib/rustlib/x86_64-apple-darwin/lib/libpanic_unwind-978f8f77602b2ff8.rlib" "/Users/alanhoff/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/$ib/libbacktrace_sys-a67ac3e54cec1633.rlib" "/Users/alanhoff/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/librustc_demangle-95f0e5e52206fff4.rl$b" "/Users/alanhoff/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libhashbrown-9d60b8ff6d472505.rlib" "/Users/alanhoff/.rustup/toolchains/night$y-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/librustc_std_workspace_alloc-b50df887d56819fa.rlib" "/Users/alanhoff/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/ru$
tlib/x86_64-apple-darwin/lib/libunwind-b1a59c9cbbe22ae5.rlib" "/Users/alanhoff/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/liblibc-534a39ff35$
41e78.rlib" "/Users/alanhoff/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/liballoc-c8c18cd805f8cabb.rlib" "/Users/alanhoff/.rustup/toolchains/$
ightly-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/librustc_std_workspace_core-624ba95ad15c67c4.rlib" "/Users/alanhoff/.rustup/toolchains/nightly-x86_64-apple-darwin/li$
/rustlib/x86_64-apple-darwin/lib/libcore-4d41bd37e688d569.rlib" "/Users/alanhoff/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libcompiler_buil$
ins-df33d2651a37ff5a.rlib" "-lSystem" "-lresolv" "-lc" "-lm"
= note: Undefined symbols for architecture x86_64:
"DUK_VARARGS", referenced from:
ducc::function::create_callback::he06e3bfbb8a50d3c in libducc-41fdc7277bd506d2.rlib(ducc-41fdc7277bd506d2.ducc.u323l1gq-cgu.15.rcgu.o)
(maybe you meant: _DUK_VARARGS)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
This is my Cargo.toml
[package]
name = "ductest"
version = "0.1.0"
authors = ["Alan Hoffmeister"]
edition = "2018"
[dependencies]
ducc = { git = "https://github.com/SkylerLipthay/ducc.git" }
And my machine's info:
cargo 1.36.0-nightly (c4fcfb725 2019-05-15)
rustc 1.36.0-nightly (6afcb5628 2019-05-19)
Darwin Alans-MacBook-Pro.local 16.7.0 Darwin Kernel Version 16.7.0: Wed Feb 27 00:29:57 PST 2019; root:xnu-3789.73.43~1/RELEASE_X86_64 x86_64
while compiling for arm, got the following errors:
error[E0308]: mismatched types
--> /build/texlab-1.7.0-vendor/ducc/src/util.rs:117:38
|
117 | ffi::duk_get_prop_string(ctx, 0, ERROR_KEY.as_ptr());
| ^^^^^^^^^^^^^^^^^^ expected u8, found i8
|
= note: expected type `*const u8`
found type `*const i8`
error[E0308]: mismatched types
--> /build/texlab-1.7.0-vendor/ducc/src/util.rs:121:38
|
121 | ffi::duk_put_prop_string(ctx, 0, ERROR_KEY.as_ptr());
| ^^^^^^^^^^^^^^^^^^ expected u8, found i8
|
= note: expected type `*const u8`
found type `*const i8`
error[E0308]: mismatched types
--> /build/texlab-1.7.0-vendor/ducc/src/util.rs:157:43
|
157 | ffi::duk_put_prop_string(ctx, -2, ERROR_KEY.as_ptr());
| ^^^^^^^^^^^^^^^^^^ expected u8, found i8
|
= note: expected type `*const u8`
found type `*const i8`
error[E0308]: mismatched types
--> /build/texlab-1.7.0-vendor/ducc/src/util.rs:167:43
|
167 | ffi::duk_get_prop_string(ctx, -1, ERROR_KEY.as_ptr());
| ^^^^^^^^^^^^^^^^^^ expected u8, found i8
|
= note: expected type `*const u8`
found type `*const i8`
error[E0308]: mismatched types
--> /build/texlab-1.7.0-vendor/ducc/src/util.rs:171:43
|
171 | ffi::duk_put_prop_string(ctx, -2, ERROR_KEY.as_ptr());
| ^^^^^^^^^^^^^^^^^^ expected u8, found i8
|
= note: expected type `*const u8`
found type `*const i8`
error[E0308]: mismatched types
--> /build/texlab-1.7.0-vendor/ducc/src/util.rs:260:37
|
260 | ffi::duk_put_global_string(ctx, UDATA.as_ptr());
| ^^^^^^^^^^^^^^ expected u8, found i8
|
= note: expected type `*const u8`
found type `*const i8`
error[E0308]: mismatched types
--> /build/texlab-1.7.0-vendor/ducc/src/util.rs:264:37
|
264 | ffi::duk_put_global_string(ctx, ANYMAP.as_ptr());
| ^^^^^^^^^^^^^^^ expected u8, found i8
|
= note: expected type `*const u8`
found type `*const i8`
error[E0308]: mismatched types
--> /build/texlab-1.7.0-vendor/ducc/src/util.rs:276:37
|
276 | ffi::duk_get_global_string(ctx, UDATA.as_ptr());
| ^^^^^^^^^^^^^^ expected u8, found i8
|
= note: expected type `*const u8`
found type `*const i8`
error[E0308]: mismatched types
--> /build/texlab-1.7.0-vendor/ducc/src/util.rs:283:37
|
283 | ffi::duk_get_global_string(ctx, ANYMAP.as_ptr());
| ^^^^^^^^^^^^^^^ expected u8, found i8
|
= note: expected type `*const u8`
found type `*const i8`
error[E0308]: mismatched types
--> /build/texlab-1.7.0-vendor/ducc/src/ducc.rs:367:50
|
367 | ffi::duk_get_global_string(self.ctx, STASH_KEY.as_ptr());
| ^^^^^^^^^^^^^^^^^^ expected u8, found i8
|
= note: expected type `*const u8`
found type `*const i8`
error[E0308]: mismatched types
--> /build/texlab-1.7.0-vendor/ducc/src/ducc.rs:390:50
|
390 | ffi::duk_put_global_string(self.ctx, STASH_KEY.as_ptr());
| ^^^^^^^^^^^^^^^^^^ expected u8, found i8
|
= note: expected type `*const u8`
found type `*const i8`
error[E0308]: mismatched types
--> /build/texlab-1.7.0-vendor/ducc/src/function.rs:130:52
|
130 | ffi::duk_put_prop_string(ducc.ctx, -2, FUNC.as_ptr());
| ^^^^^^^^^^^^^ expected u8, found i8
|
= note: expected type `*const u8`
found type `*const i8`
error[E0308]: mismatched types
--> /build/texlab-1.7.0-vendor/ducc/src/function.rs:86:47
|
86 | ffi::duk_get_prop_string(ctx, -1, FUNC.as_ptr());
| ^^^^^^^^^^^^^ expected u8, found i8
|
= note: expected type `*const u8`
found type `*const i8`
error[E0308]: mismatched types
--> /build/texlab-1.7.0-vendor/ducc/src/function.rs:117:42
|
117 | ffi::duk_get_prop_string(ctx, 0, FUNC.as_ptr());
| ^^^^^^^^^^^^^ expected u8, found i8
|
= note: expected type `*const u8`
found type `*const i8`
error[E0308]: mismatched types
--> /build/texlab-1.7.0-vendor/ducc/src/function.rs:121:42
|
121 | ffi::duk_put_prop_string(ctx, 0, FUNC.as_ptr());
| ^^^^^^^^^^^^^ expected u8, found i8
|
= note: expected type `*const u8`
found type `*const i8`
error: aborting due to 15 previous errors
For more information about this error,
full log: https://logs.nix.ci/?key=nixos/nixpkgs.73839&attempt_id=c7ed5679-f27e-4199-adbd-cb2100515246
@SkylerLipthay Hi! Is there a way to set userdata inside a JS invoked function. Thanks
fn set_name(inv: Invocation) -> Result<Value, DuccError>{
let this = inv.this.as_object().unwrap();
let engine = inv.ducc;
engine.set_user_data("name", "Ducc Rocks!");
//Compile error here: cannot borrow `*engine` as mutable, as it is behind a `&` reference
return Ok(Value::Boolean(true));
}
Hi! While I've gotten used to storing everything in ducc.globals()
, I still get a bit annoyed at the whole retrieve everything from globals every time. For instance, for many calls crossing the Rust<->JS boundary I'll have to do something like ducc.globals().get("namespace").get("library").get("_refs").get(index)
.
However, I got an idea for a potential way to kind of store references to Duktape for faster and nicer retrieval, without sacrificing any safety guarantees. Basically, it'd be a handle type looking something like this:
#[derive(Clone)]
struct ObjectHandle {
rc: Rc<ffi::duk_uarridx_t>
}
impl ObjectHandle {
pub fn get_object(ducc: &Ducc) -> Object {
// return object from heap stash
}
}
and API for retrieving an ObjectHandle from an Object somewhere.
Some practical concerns would be making sure that GC doesn't remove our object when we hold a handle (but is able to if we don't), which depends on Duktape's support for it. One scary bit is Drop for ObjectHandle; how can we inform Duktape that it's okay to GC the referenced object without access to &Ducc? Maybe a drop_object_reference(&Ducc)
that must be called before Drop or it will panic.
The benefits of this approach would be the ability to keep a reference certain objects without caring about what is happening in the JS world, and I think the ergonomics of using it are better than the global referencing as well. If this works, it could be extended to FunctionHandle etc as well.
Does this sound like a viable/safe idea? If it turns out well, maybe the same approach would work with Mini-V8 as well.
Is there support for modules already available?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.