GithubHelp home page GithubHelp logo

theduke / quickjs-rs Goto Github PK

View Code? Open in Web Editor NEW
558.0 12.0 49.0 1.26 MB

Rust wrapper for the quickjs Javascript engine.

License: MIT License

Rust 8.10% C 91.48% Makefile 0.41% Nix 0.01%
rust-lang rust javascript-engine javascript

quickjs-rs's Introduction

quickjs-rs

Crates.io docs.rs [Build Status

A Rust wrapper for QuickJS.

QuickJS is a new, small Javascript engine by Fabrice Bellard and Charlie Gordon. It is fast and supports the full ES2020 specification.

This crate allows you to easily run and integrate with Javascript code from Rust.

Quickstart

[dependencies]
quick-js = "0.4.1"
use quick_js::{Context, JsValue};

let context = Context::new().unwrap();

// Eval.

let value = context.eval("1 + 2").unwrap();
assert_eq!(value, JsValue::Int(3));

let value = context.eval_as::<String>(" var x = 100 + 250; x.toString() ").unwrap();
assert_eq!(&value, "350");

// Callbacks.

context.add_callback("myCallback", |a: i32, b: i32| a + b).unwrap();

context.eval(r#"
    // x will equal 30
    var x = myCallback(10, 20);
"#).unwrap();

Optional Features

The crate supports the following features:

  • chrono: chrono integration

    • adds a JsValue::Date variant that can be (de)serialized to/from a JS Date
  • bigint: arbitrary precision integer support via num-bigint

  • log: allows forwarding console.log messages to the log crate. Note: must be enabled with ContextBuilder::console(quick_js::console::LogConsole);

  • patched Enabled automatically for some other features, like bigint. You should not need to enable this manually. Applies QuickJS patches that can be found in libquickjs-sys/embed/patches directory.

Installation

By default, quickjs is bundled with the libquickjs-sys crate and automatically compiled, assuming you have the appropriate dependencies.

Windows Support

Windows is only supported with the MSYS2 environment and x86_64-pc-windows-gnu target architecture.

If you have MSYS2 installed and the MSYS bin directory in your path, you can compile quickjs with cargo build --target="x86_64-pc-windows-gnu".

The target can also be configured permanently via a cargo config file or the CARGO_BUILD_TARGET env var.

System installation

To use the system installation, without the bundled feature, first install the required dependencies, and then compile and install quickjs.

# Debian/Ubuntu: apt-get install -y curl xz-utils build-essential gcc-multilib libclang-dev clang
mkdir quickjs 
curl -L https://bellard.org/quickjs/quickjs-2019-07-09.tar.xz | tar xJv -C quickjs --strip-components 1
cd quickjs
sudo make install

You then need to disable the bundled feature in the libquickjs-sys crate to force using the system version.

quickjs-rs's People

Contributors

andrieshiemstra avatar chayleaf avatar coolreader18 avatar errord avatar graham avatar llgoer avatar mrmaxmeier avatar rail-ka avatar theduke avatar xu-cheng avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

quickjs-rs's Issues

Enable Object deserialization to JsObject::Object

Currently objects can't be converrted to JsObject::Object because quickjs does not expose the JS_GetOwnProperties.

Implement this once quickjs exposes a relevant function.

We could also manually patch quickjs for the embedded version, but that is rather awkward.

chrono Integration

Integration with chrono::DateTime<Utc> via a chrono feature and a JsValue::Date variant.

Adding multiple callbacks causes `Err(Exception(String("SyntaxError: stack overflow")))`

If I add multiple callbacks and then call ctx.eval(...), no matter what I put in the eval statement, it causes a fatal error: Err(Exception(String("SyntaxError: stack overflow"))). See the following example to reproduce.

use quick_js::{Context, ContextError, JsValue};

fn qjs_add(x: i32, y: i32) -> i32 {
    x + y
}
fn qjs_sleep(ms: i32) -> JsValue {
    std::thread::sleep(std::time::Duration::from_millis(ms as u64));
    JsValue::Null
}

fn main() {
    let ctx = Context::new().unwrap();
    ctx.add_callback("qjs_add", qjs_add).unwrap();
    ctx.add_callback("qjs_sleep", qjs_sleep).unwrap();

    let result = ctx.eval(";").unwrap();
}

Causes the following error:

Exception(String("SyntaxError: stack overflow"))thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Exception(String("SyntaxError: stack overflow"))', src/main.rs

This error shows up no matter what I put in ctx.eval("..."), unless I limit the calls to add_callback(...) to 1. Is there a limit of one callback?

Questions about design/architecture

Hi theduke,

So i thought i'd share some of my advancements on functionality as discussed in #78, #53, #40, #24

The first four are a bit more complicated than i anticipated because i rely quite a bit on my JSValueRef which automatically calls DupValue and FreeValue on clone/drop (see https://github.com/HiRoFa/quickjs_es_runtime/blob/master/src/valueref.rs)

So my first question is: Would it be ok to alter your OwnedValueRef in the same way?

Second, since you made a optional feature out of bigint would i be correctly assuming you would also want optional features for bytecodecompilation/modules/reflection etc to keep binaries as compact as possible?

i thould i'd make a "utils" mod with some mods nested there

  • compile.rs for #53
  • fetch.rs for #24
  • modules.rs for #40
  • reflection.rs (create proxies and such) for #78

Kind regards

Track JavaScript data lifetimes

I'm embedding this in a rendering application where rendered objects can be scripted in the frontend. The problem is that the rendered objects are managed in Rust but created in JavaScript. When the JS objects are garbage collected, they remain in the Rust backend. Ideally this should be automated so when the JS objects are deleted there is some automated way of having the Rust data associated be deleted too. Is there a way of achieving this currently or a implementation that could enable this?

Cannot build crates that depend on quickjs-rs on Windows

I tried to build a project called mdbook-katek which depends on this crate. The patched feature was enabled, as stated here, and I've used the x86_64-pc-windows-gnu target, as described in the README.

Below there is the GitHub Action script:

jobs:

  windows-binary:

    runs-on: windows-latest

    steps:
    - uses: actions/checkout@v2

    - name: Install stable
      uses: actions-rs/toolchain@v1
      with:
        profile: minimal
        toolchain: stable
        target: x86_64-pc-windows-gnu # Not msvc because of quickjs-rs dependency
        override: true

    - name: Setup msys64 and mingw64
      run: |
        $Paths = "C:\msys64\mingw64\bin;C:\msys64\usr\bin"
        echo "$Paths" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
        echo "CARGO_BUILD_TARGET=x86_64-pc-windows-gnu" >> $GITHUB_ENV
   
    - name: Build mdbook-katex
      run: |
        cargo build --release --target x86_64-pc-windows-gnu

And this is the error that I got: https://github.com/Luni-4/mdbook-katex/runs/1765047155?check_suite_focus=true#step:5:371

It seems the job wasn't able to find the patches contained in the libquickjs-sys/embed/patches/ directory because the CARGO_MANIFEST_PATH is different. This problem does not happen on Linux and MacOS though.

Thanks in advance for your help! :)

Unable to accept arrays as callback params

this works;

    context.add_callback("name", move |param: i32| {
        JsValue::Null
    }).unwrap();

this doesnt;

    context.add_callback("name", move |param: Vec<i32>| {
        JsValue::Null
    }).unwrap();

neither does;

    context.add_callback("name", move |param: &[i32]| {
        JsValue::Null
    }).unwrap();

and gives the error: the trait Callback<_> is not implemented for [closure@src/bind.rs:98:34: 100:6]

I see you can use Arguments to work around this, but it seems like Vec should work too

Bytecode compilation

QuickJS supports compilation down to byte code and running from byte code.
This skips a huge chunk of code and potentially reduces script execution time.

I could imagine the following new API for context:

  • pub fn compile(&self, code: &str) -> Result<Vec<u8>, ExecutionError>: Same as eval(), but uses the JS_EVAL_FLAG_COMPILE_ONLY flag on JS_Eval internally followed by a JS_WriteObject. Returns byte code via a vector.
  • pub fn run(&self, bytecode: &[u8]) -> Result<JsValue, ExecutionError>: Same as eval(), but runs bytecode instead of first parsing the script. Internally uses js_std_eval_binary.

Cheers, David

Evaluation timeout

JS_SetInterruptHandler() configures an interrupt handler that can be used to implement a evaluation timeout.

Expose this via a builder api.

Fix `set_global()` use after free. almost....?

i was also looking into freeing/not freeing JSValue's and are you sure your fix is complete?

your set_property_raw eventually calls quickjs's JS_SetPropertyInternal method which frees the val if the method fails, in that case std::mem::forget is not called leaving you with a pointer that will be dropped and freed?

       unsafe {
            self.set_property_raw(name, qval.value)?; // AH: if this fails, Err will be returned here because of ?
            // set_property_raw takes ownership, so we must prevent a free.
            std::mem::forget(qval); // AH: this will not have been called, but the pointer will have been freed by quickjs::JS_SetPropertyInternal
        }
        Ok(())

Serde support

Implement serde support for (de)serializing Rust values to/from Javascript values.

Move JS objects to Rust JSValues without deserialization

I'm wondering is it possible to store JavaScript objects as Rust values without deserialization, so that objects with richer structure can be passed back to call_function. For example, this code

let val = context.eval("new Date()").unwrap();                                                            
context.eval("display = x => x.toString()").unwrap();                                                    
let result = context.call_function("display", vec![val]).unwrap();                                       
println!("result: {:?}", result);                                                                         

outputs now result: String("[object Object]"), but I would like it to output result: String("Mon Aug 12 2019 15:55:15 GMT+0000").

Replace copy_dir

copy_dir is quite outdated and tends to introduce a duplicate dependency on walkdir.

We can either ship a compressed version of the code, which is then uncompressed instead of copying the source directory.
Or switch to a different dependency like fs-extra.

See libquickjs-sys/build.rs.

Link failed on openSUSE Tumbleweed

I cloned this project and the link failed when running the cargo test command:

โžœ  quickjs-rs git:(master) LANG=en.US cargo test --verbose
       Fresh winapi-build v0.1.1
       Fresh winapi v0.2.8
       Fresh once_cell v1.3.1
       Fresh kernel32-sys v0.2.2
       Fresh walkdir v0.1.8
       Fresh copy_dir v0.1.2
       Fresh libquickjs-sys v0.4.0 (/storage/code/quickjs-rs/libquickjs-sys)
   Compiling quick-js v0.3.0 (/storage/code/quickjs-rs)
     Running `rustc --edition=2018 --crate-name quick_js src/lib.rs --error-format=json --json=diagnostic-rendered-ansi --emit=dep-info,link -C debuginfo=2 --test -C metadata=631cac6ef7510601 -C extra-filename=-631cac6ef7510601 --out-dir /storage/code/quickjs-rs/target/debug/deps -C incremental=/storage/code/quickjs-rs/target/debug/incremental -L dependency=/storage/code/quickjs-rs/target/debug/deps --extern libquickjs_sys=/storage/code/quickjs-rs/target/debug/deps/liblibquickjs_sys-b2ecec6b3499f3e9.rlib --extern once_cell=/storage/code/quickjs-rs/target/debug/deps/libonce_cell-4abb1dfbf2230707.rlib -L native=/storage/code/quickjs-rs/target/debug/build/libquickjs-sys-b0a9c4a9f9f377bd/out/quickjs`
error: linking with `cc` failed: exit code: 1
  |
  = note: "cc" "-Wl,--as-needed" "-Wl,-z,noexecstack" "-m64" "-L" "/home/hentioe/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.17bu91rbd7mv49b9.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.19lqolajh3t49to2.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.1ar764j4d28pkb27.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.1c979rj1i0ximt8t.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.1cjqj8699835csbz.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.1dohomxa1d3ea3bd.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.1g56jifpzndomzn7.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.1gxkon52a1mkyw9w.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.1h7zz85yp0jzlj7q.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.1h9j2pxb8sfnlymp.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.1hd7hj9mjyfrq4jd.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.1hha2nzr2va0zoo5.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.1hp4uvdtwx03hcnu.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.1i26owdrsroi4n1k.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.1jr7t2a2fxrb6pqk.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.1mc3oxe7qh7f42se.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.1o3qzrbolmmgb61s.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.1pnoiod18pwcielm.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.1tbn364rt55q5wwl.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.1tx9dbi8leumwgz7.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.1xatblassaetcrqo.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.1zepm3lhul3opmcd.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.1zrqkcdp9l5c9rh4.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.22a13pe3c38fzq0e.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.22vjt265xkofjasa.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.22wd7mvv6kbzh8yr.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.278rntwrv2o7pqhb.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.279c4xr366fhgwyt.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.2b9hha7a59ubqnne.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.2d69z8wu4pvtzmg7.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.2dq35gk36lnfza2i.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.2f1a76k3xjm3575e.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.2j03ukbkvfg89nsz.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.2n30vzlbx8ki50be.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.2ohi6rjw6l8ad5ms.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.2pcnol7uu0o472im.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.2ru9xgrafhhpy0zk.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.2sxdt21c8ztaobh4.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.2u8bx0cow3f39ula.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.2xcdb3whfsroch76.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.2yad7fr9x7kar4no.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.2z3vk4kzqju5418z.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.3186zrfzvuh8pv0y.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.35drpxc1sms7m7ht.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.36g2iebq3djnbgac.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.37r00y3taq42khlm.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.39w88gfv36frw040.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.3bmxlf2xu0x7wnzu.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.3m7ca61t3efslr7c.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.3n81vdud32pi37j9.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.3o29wrku5dk9ad1i.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.3rylh6n0pv94of26.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.3tasgvjnbmo77zp4.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.3tebq4yu6exivlyj.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.3xmofvdkgaury4st.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.418hv31qp0ygk7g4.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.41ql0ya8d4guo4fy.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.42x46iggqn6h68bw.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.43d2o5tm2c8y3d86.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.45xdugb8sgxif2jg.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.474xpzv2yu5zjpmc.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.48u8wgnuhqhfefx2.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.4bblhwurw8zfyaq2.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.4c499xgkyrwv5166.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.4e09wm32gyu1pjik.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.4e3l8r4iy38ewgji.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.4jg0p21zjul1soka.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.4l43vqx8sat84sny.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.4pnfsoaic6lem6d2.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.4rm6qkqdr3w69b0f.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.4spuxacazjbo3s7c.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.4uy88wm3ea5u3tvj.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.4vu5rmy0ga88gkrn.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.4vvceev5g5i59let.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.4yfn1sexl36s0x4l.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.4yy4iv9376cjxdh6.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.4z409h2gayfy04a8.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.512uyvizddjk5trb.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.51tv6769rss3ryt8.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.54hymnncnfhtc1a6.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.55iom4wpch0o290y.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.584w82xnm2qswqu2.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.5ce10aietm666hn9.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.5e83q80kt63b2qe1.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.5ecuv14hfgcemuzi.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.5edrqwupjg3voytm.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.5g2q90hfm5m5emk5.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.769q2my7uf0evbn.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.af7g38pk24oq52w.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.as4snjpw65dw6rv.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.brnnme12a68d0vp.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.cjx6spwgwd6veef.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.e66gt89d7opihtq.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.ea893wzm2ahkwb2.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.ehatzhayl9z6k4d.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.fvg7a3oe6w7icbe.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.kqt3mw18fxfcbsc.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.lcoc1kaiz9smbg3.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.owbmafjkfawdpmy.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.pcim2qbdg0381zp.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.w19r3jo1y32rsgm.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.w3wk2rw3y61mulr.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.yabrlt602eln2ju.rcgu.o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.yu1qku1jqjpac5k.rcgu.o" "-o" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601" "/storage/code/quickjs-rs/target/debug/deps/quick_js-631cac6ef7510601.4xmlshfnemwk88j1.rcgu.o" "-Wl,--gc-sections" "-pie" "-Wl,-zrelro" "-Wl,-znow" "-nodefaultlibs" "-L" "/storage/code/quickjs-rs/target/debug/deps" "-L" "/storage/code/quickjs-rs/target/debug/build/libquickjs-sys-b0a9c4a9f9f377bd/out/quickjs" "-L" "/home/hentioe/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-Wl,-Bstatic" "/home/hentioe/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libtest-6f3c013d04a65363.rlib" "/home/hentioe/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libterm-08355c1ebddd12c5.rlib" "/home/hentioe/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libgetopts-0e1cc2db75776f2e.rlib" "/home/hentioe/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libunicode_width-3c999474a70e3537.rlib" "/home/hentioe/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_std_workspace_std-0d89e7caa0be9cd8.rlib" "/storage/code/quickjs-rs/target/debug/deps/liblibquickjs_sys-b2ecec6b3499f3e9.rlib" "-Wl,--start-group" "/home/hentioe/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-a2a766dac798f7cf.rlib" "/home/hentioe/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libpanic_unwind-a85f7d74095723ea.rlib" "/home/hentioe/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libhashbrown-4ed27bd07d52ec56.rlib" "/home/hentioe/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_std_workspace_alloc-4c323f23cb5b2482.rlib" "/home/hentioe/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libbacktrace-2e6de4a7e177acee.rlib" "/home/hentioe/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libbacktrace_sys-80571e4a1921bf51.rlib" "/home/hentioe/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_demangle-1772b65d0f093257.rlib" "/home/hentioe/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libunwind-37ebc98487d077f2.rlib" "/home/hentioe/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcfg_if-fa7cce2e70cf53f1.rlib" "/home/hentioe/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liblibc-a60fcf932d3053cd.rlib" "/home/hentioe/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc-da705bf7dd482e5a.rlib" "/home/hentioe/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_std_workspace_core-8a2e90edf20d7f0b.rlib" "/home/hentioe/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcore-4888dfadf2ff3780.rlib" "-Wl,--end-group" "/home/hentioe/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcompiler_builtins-a0ee5f37b860b20a.rlib" "-Wl,-Bdynamic" "-ldl" "-lrt" "-lpthread" "-lgcc_s" "-lc" "-lm" "-lrt" "-lpthread" "-lutil" "-lutil"
  = note: /usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld: /storage/code/quickjs-rs/target/debug/deps/liblibquickjs_sys-b2ecec6b3499f3e9.rlib(quickjs.nolto.o): relocation R_X86_64_32S against `.rodata' can not be used when making a PIE object; recompile with -fPIE
          /usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld: /storage/code/quickjs-rs/target/debug/deps/liblibquickjs_sys-b2ecec6b3499f3e9.rlib(libregexp.nolto.o): relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a PIE object; recompile with -fPIE
          /usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld: /storage/code/quickjs-rs/target/debug/deps/liblibquickjs_sys-b2ecec6b3499f3e9.rlib(libunicode.nolto.o): relocation R_X86_64_32 against `.rodata' can not be used when making a PIE object; recompile with -fPIE
          /usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld: /storage/code/quickjs-rs/target/debug/deps/liblibquickjs_sys-b2ecec6b3499f3e9.rlib(cutils.nolto.o): relocation R_X86_64_32 against `.text' can not be used when making a PIE object; recompile with -fPIE
          /usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld: /storage/code/quickjs-rs/target/debug/deps/liblibquickjs_sys-b2ecec6b3499f3e9.rlib(libbf.nolto.o): relocation R_X86_64_32S against `.rodata' can not be used when making a PIE object; recompile with -fPIE
          /usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld: final link failed: nonrepresentable section on output
          collect2: error: ld returned 1 exit status
          

error: aborting due to previous error

error: could not compile `quick-js`.

Caused by:
  process didn't exit successfully: `rustc --edition=2018 --crate-name quick_js src/lib.rs --error-format=json --json=diagnostic-rendered-ansi --emit=dep-info,link -C debuginfo=2 --test -C metadata=631cac6ef7510601 -C extra-filename=-631cac6ef7510601 --out-dir /storage/code/quickjs-rs/target/debug/deps -C incremental=/storage/code/quickjs-rs/target/debug/incremental -L dependency=/storage/code/quickjs-rs/target/debug/deps --extern libquickjs_sys=/storage/code/quickjs-rs/target/debug/deps/liblibquickjs_sys-b2ecec6b3499f3e9.rlib --extern once_cell=/storage/code/quickjs-rs/target/debug/deps/libonce_cell-4abb1dfbf2230707.rlib -L native=/storage/code/quickjs-rs/target/debug/build/libquickjs-sys-b0a9c4a9f9f377bd/out/quickjs` (exit code: 1)

OS Version: openSUSE Tumbleweed (Release: 20200224)
quickjs-rs Version: 0.3.0
Rust Version: 1.41.1

module init macro

It'd be cool to have a fancy macro to build the extern function required to create a native module that can be imported by the qjs CLI. With qjs you can build and import native modules from *.so files by simply having a function something like:

JSModuleDef* js_init_module_qjsc_my_module(JSContext* ctx, const char* module_name);

Then in JS you just do:

import * from 'my_module.so'

Stack overflow weirdness

So i've been busy lately wrapping quickjs-rs in my own project and every now and then i got unexpected stack-overflows which seemed to appear and disappear quite randomly.

Now i've finally reproduced that behaviour in a small program and stuff just got weirder...

my cargo.toml, with a ref to my own quickjs-rs branch which has the latest quickjs version (please note that the 0.8.0 release had the same issues)

[package]
name = "untitled"
version = "0.1.0"
authors = ["Andries Hiemstra <[email protected]>"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
libquickjs-sys = {git="https://github.com/HiRoFa/quickjs-rs", branch="issue87"}

main.rs

use libquickjs_sys as q;
use std::ffi::CString;

struct RtWrapper {
    runtime: *mut q::JSRuntime,
}

impl RtWrapper {
    fn new() -> Self {
        println!("creating new QuickJsRuntime");
        let runtime = unsafe { q::JS_NewRuntime() };
        if runtime.is_null() {
            panic!("RuntimeCreationFailed");
        }
        Self { runtime }
    }
}

impl Drop for RtWrapper {
    fn drop(&mut self) {
        println!("before JS_FreeRuntime");
        unsafe { q::JS_FreeRuntime(self.runtime) };
        println!("after JS_FreeRuntime");
    }
}

fn main() {
    unsafe {

        let null = q::JSValue {
            u: q::JSValueUnion { int32: 0 },
            tag: 2,
        };

        let wrapper = RtWrapper::new();

        let runtime = wrapper.runtime;

        let context: *mut q::JSContext = q::JS_NewContext(runtime);

        let script = "(function err(){throw Error('Oh dear, stuff failed');});";
        let script_cstring = CString::new(script).ok().unwrap();
        let filename_cstring = CString::new("test_err.js").ok().unwrap();

        let value_raw = q::JS_Eval(
            context,
            script_cstring.as_ptr(),
            script.len() as _,
            filename_cstring.as_ptr(),
            q::JS_EVAL_TYPE_GLOBAL as i32,
        );

        if q::JS_IsException(value_raw ) {
            panic!("eval returned error");
        }

        // should be an Object (function)
        assert_eq!(value_raw.tag, -1);

        let func_res = q::JS_Call(
            context,
            value_raw,
            null,
            0,
            vec![].as_mut_ptr(),
        );

        if !q::JS_IsException(func_res ) {
            panic!("call did not error");
        }

        let exception_val = q::JS_GetException(context);

        let message_prop_name = CString::new("message").ok().unwrap();
        let exception_msg = q::JS_GetPropertyStr(context, exception_val, message_prop_name.as_ptr());

        let msg = val_to_str(context, exception_msg);

        q::JS_FreeValue(context, value_raw);
        q::JS_FreeValue(context, func_res);
        q::JS_FreeValue(context, exception_val);
        q::JS_FreeValue(context, exception_msg);

        if !msg.contains("stuff failed") {
            println!("err msg was unexpected val of {}", msg);
        } else {
            println!("we got a stuff failed err which is what we wanted");
        }

        run_pending_jobs_if_any(runtime);

        q::JS_FreeContext(context);

        println!("done");

    }
}

unsafe fn run_pending_jobs_if_any(runtime: *mut q::JSRuntime) {
    while q::JS_IsJobPending(runtime) > 0 {
        let mut ctx: *mut q::JSContext = std::ptr::null_mut();
        let res = q::JS_ExecutePendingJob(runtime, &mut ctx);
        if res < 0 {
            panic!("running pending job failed");
        }
    }
}

unsafe fn val_to_str(context: *mut q::JSContext, val: q::JSValue) -> String {
    let ptr = q::JS_ToCStringLen2(context, std::ptr::null_mut(), val, 0);
    let cstr = std::ffi::CStr::from_ptr(ptr);
    let s = cstr.to_str().expect("invalid string").to_string();

    // Free the c string.
    q::JS_FreeCString(context, ptr);
    s
}

In this case i'm throwing an error from a function, please note that i've had the same issue when Promises we're dropped

When running this with cargo run i get the following output

creating new QuickJsRuntime
err msg was unexpected val of stack overflow
done
before JS_FreeRuntime
after JS_FreeRuntime

Process finished with exit code 0

So the JS_Call throws a Exception as expected bu the message of the exception is stack overflow

Now for the weird, if i run the same code with cargo run --release i get the error and output i expected

we got a stuff failed err which is what we wanted
done
before JS_FreeRuntime
after JS_FreeRuntime

Process finished with exit code 0

And now for the really weird, if i remove the println!("creating new QuickJsRuntime"); line before creating the runtime i also get the output i expected

we got a stuff failed err which is what we wanted
done
before JS_FreeRuntime
after JS_FreeRuntime

Process finished with exit code 0

Anyone out there having similar issues or have any idea what's going on here?

Use #![deny(warnings)] and #![deny(missing_docs)] only for tests

Recently I questioned what would happen to projects dependent on this crate if a new Rust release starts to generate warnings for some parts of the crate's code (for example, like it started to show warnings for usage of Box<Trait> instead of Box<dyn Trait>). As far as I tested, this would prevent dependent projects from compiling.

Maybe putting #![deny(warnings)] and #![deny(missing_docs)] in lib.rs behind #[cfg(test)] can make the crate more future-proof?

Callbacks on next tick are not called

This code prints the message:

use quick_js::{Context, JsValue};                                                                                       
                                                                                                                        
fn main() {                                                                                                             
    let context = Context::new().unwrap();                                                                              
    context                                                                                                             
        .add_callback("print_cb", |s: String| {                                                              
            println!("value: {}", s);                                                                                   
            JsValue::Null                                                                                               
        })                                                                                                              
        .unwrap();                                                                                                      
    context.eval("print_cb('hi')").unwrap();                                                                            
}                                                                                                                       

However, this code doesn't:

use quick_js::{Context, JsValue};                                                                                       
                                                                                                                        
fn main() {                                                                                                             
    let context = Context::new().unwrap();                                                                              
    context                                                                                                             
        .add_callback("print_cb", |s: String| {                                                              
            println!("value: {}", s);                                                                                   
            JsValue::Null                                                                                               
        })                                                                                                              
        .unwrap();                                                                                                      
    context                                                                                                             
        .eval("new Promise(resolve => resolve('hi')).then(print_cb); null")                                             
        .unwrap();                                                                                                      
}

It is not the case that the program doesn't wait until the callback is called, as adding for example

std::thread::sleep(std::time::Duration::from_millis(1000));                                                         
context.eval("null").unwrap();                                                                                      

at the end of main still doesn't output the message.

Module Loading Support

Hi,

Thank you so much for this wrapper!

I'm running into some problems when loading modules, all I get back is ReferenceError: could not load module when running for example the following:

use quick_js::{Context};

fn main() {
    let context = Context::new().unwrap();
    let value = context.eval_as::<String>("(async () => {const test = await import('./js/module.js'); return test();})();").unwrap();
    println!("{}", &value);
}

With this in module.js:

export default () => {
    return 'Not working?';
};

Am I missing something obvious or is this just not supported yet?

Windows Support

I noticed that this project does not currently support windows. Do we have such a plan?

Add full logging example

Using

 let ctx = Context::builder().console(quick_js::console::LogConsole).build()?;

and later I evaluate some code that uses console.log, the code will run but nothing will be printed.

[Bug] Strings cause memory free errors & segfaults.

Minimal repro:

fn main() {
    let ctx = quick_js::Context::new().unwrap();
    ctx.set_global("a", "a").unwrap();
    ctx.eval("a").unwrap();
}
double free or corruption (!prev)
Aborted
Segmentation fault

Performing a computation causes a segfault:

fn main() {
    let ctx = quick_js::Context::new().unwrap();
    ctx.set_global("a", "a").unwrap();
    ctx.eval("a + 1").unwrap();
}
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Exception(String("InternalError: string too long"))', src/main.rs:4:23
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Segmentation fault
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Exception(String("InternalError: string too long"))', src/main.rs:4:23
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
free(): invalid pointer
Aborted

Tested it on two x86_64-pc-linux-gnu machines. GCC 9.3.0 on both, and rustc 1.50.0-nightly/1.47.0. Not sure what other info is needed to reproduce.

Console

Add a console.log implementation that prints to stdout.
Should be opt-in, enabled via ContextBuilder.

Cloning context for SSR

let ctx = Context::new().unwrap();
let renderer = read_to_string(RENDERER)?;
let render = read_to_string(RENDER)?;
let bundle = read_to_string(BUNDLE)?;

let _loaded_renderer = ctx.eval(&renderer).unwrap();
let _loaded_bundle = ctx.eval(&bundle).unwrap();

let routes = warp::path!(String)
    .map(|path| {
        println!("Rendering {}", path);
        let reply = ctx.eval(&render).unwrap();
        Ok(reply::html(reply.as_str().unwrap()))
    });

When trying to compile this, I get:

error[E0277]: `*mut libquickjs_sys::JSRuntime` cannot be shared between threads safely

Is there a way to safely (and quickly) clone a JS context?

Build failed on windows

Build failed on windows with toolchain stable-x86_64-pc-windows-gnu, msys2/MinGW64, and the following enviornments.

$ cargo --version
cargo 1.46.0 (149022b1d 2020-07-17)
$ rustc --version 
rustc 1.46.0 (04488afe3 2020-08-24)

I found the issue comes from the following line from the build.rs file.

.arg(fs::canonicalize(patch.path()).expect("Cannot canonicalize patch path"))

The fs::canonicalize returns a path with a '\\?\' prefix (after unwrap), which will result in the calling of the patch command fail. See also canonicalize doc

I temporily replaced the line to

.arg(patch.path())

to make it work. Any better ideas?

expose all static inline functions from quickjs.h

like

JS_VALUE_GET_FLOAT64
JS_VALUE_IS_NAN
JS_IsNumber
etc

could we do that programatically from build.rs? (in order to be future proof)

  • find all static inline fn in quickjs.h,
  • add them to static-functions.c
  • add them to lib.rs
    etc

i'll get into this later this week

MSVC Toolchain Support

Provide a clean error message when building -sys on Windows with msvc.

(Just a reminder for myself)

Support wasm32-unknown-unknown Target

Thanks for this project!

Is there any way to compile this in a lib crate to target wasm32-unknown-unknown? (ex. cargo build --release --target=wasm32-unknown-unknown)

I'm suspecting no. I tried and got this error:

error: failed to run custom build command for `libquickjs-sys v0.6.0`

Caused by:
  process didn't exit successfully: `/mnt/v/dprint/crates/test-plugin/target/release/build/libquickjs-sys-7f85a6e12a75c9e1/build-script-build` (exit code: 1)
--- stdout
TARGET = Some("wasm32-unknown-unknown")
HOST = Some("x86_64-unknown-linux-gnu")
CC_wasm32-unknown-unknown = None
CC_wasm32_unknown_unknown = None
TARGET_CC = None
CC = None
CFLAGS_wasm32-unknown-unknown = None
CFLAGS_wasm32_unknown_unknown = None
TARGET_CFLAGS = None
CFLAGS = None
CRATE_CC_NO_DEFAULTS = None
DEBUG = Some("false")
CC_wasm32-unknown-unknown = None
CC_wasm32_unknown_unknown = None
TARGET_CC = None
CC = None
CFLAGS_wasm32-unknown-unknown = None
CFLAGS_wasm32_unknown_unknown = None
TARGET_CFLAGS = None
CFLAGS = None
CRATE_CC_NO_DEFAULTS = None
CC_wasm32-unknown-unknown = None
CC_wasm32_unknown_unknown = None
TARGET_CC = None
CC = None
CFLAGS_wasm32-unknown-unknown = None
CFLAGS_wasm32_unknown_unknown = None
TARGET_CFLAGS = None
CFLAGS = None
CRATE_CC_NO_DEFAULTS = None
CC_wasm32-unknown-unknown = None
CC_wasm32_unknown_unknown = None
TARGET_CC = None
CC = None
CFLAGS_wasm32-unknown-unknown = None
CFLAGS_wasm32_unknown_unknown = None
TARGET_CFLAGS = None
CFLAGS = None
CRATE_CC_NO_DEFAULTS = None
CC_wasm32-unknown-unknown = None
CC_wasm32_unknown_unknown = None
TARGET_CC = None
CC = None
CFLAGS_wasm32-unknown-unknown = None
CFLAGS_wasm32_unknown_unknown = None
TARGET_CFLAGS = None
CFLAGS = None
CRATE_CC_NO_DEFAULTS = None
CC_wasm32-unknown-unknown = None
CC_wasm32_unknown_unknown = None
TARGET_CC = None
CC = None
CFLAGS_wasm32-unknown-unknown = None
CFLAGS_wasm32_unknown_unknown = None
TARGET_CFLAGS = None
CFLAGS = None
CRATE_CC_NO_DEFAULTS = None
CC_wasm32-unknown-unknown = None
CC_wasm32_unknown_unknown = None
TARGET_CC = None
CC = None
CFLAGS_wasm32-unknown-unknown = None
CFLAGS_wasm32_unknown_unknown = None
TARGET_CFLAGS = None
CFLAGS = None
CRATE_CC_NO_DEFAULTS = None
CC_wasm32-unknown-unknown = None
CC_wasm32_unknown_unknown = None
TARGET_CC = None
CC = None
CFLAGS_wasm32-unknown-unknown = None
CFLAGS_wasm32_unknown_unknown = None
TARGET_CFLAGS = None
CFLAGS = None
CRATE_CC_NO_DEFAULTS = None
CC_wasm32-unknown-unknown = None
CC_wasm32_unknown_unknown = None
TARGET_CC = None
CC = None
CFLAGS_wasm32-unknown-unknown = None
CFLAGS_wasm32_unknown_unknown = None
TARGET_CFLAGS = None
CFLAGS = None
CRATE_CC_NO_DEFAULTS = None
CC_wasm32-unknown-unknown = None
CC_wasm32_unknown_unknown = None
TARGET_CC = None
CC = None
CFLAGS_wasm32-unknown-unknown = None
CFLAGS_wasm32_unknown_unknown = None
TARGET_CFLAGS = None
CFLAGS = None
CRATE_CC_NO_DEFAULTS = None
CC_wasm32-unknown-unknown = None
CC_wasm32_unknown_unknown = None
TARGET_CC = None
CC = None
CFLAGS_wasm32-unknown-unknown = None
CFLAGS_wasm32_unknown_unknown = None
TARGET_CFLAGS = None
CFLAGS = None
CRATE_CC_NO_DEFAULTS = None
CC_wasm32-unknown-unknown = None
CC_wasm32_unknown_unknown = None
TARGET_CC = None
CC = None
CFLAGS_wasm32-unknown-unknown = None
CFLAGS_wasm32_unknown_unknown = None
TARGET_CFLAGS = None
CFLAGS = None
CRATE_CC_NO_DEFAULTS = None
CC_wasm32-unknown-unknown = None
CC_wasm32_unknown_unknown = None
TARGET_CC = None
CC = None
CFLAGS_wasm32-unknown-unknown = None
CFLAGS_wasm32_unknown_unknown = None
TARGET_CFLAGS = None
CFLAGS = None
CRATE_CC_NO_DEFAULTS = None
CC_wasm32-unknown-unknown = None
CC_wasm32_unknown_unknown = None
TARGET_CC = None
CC = None
CFLAGS_wasm32-unknown-unknown = None
CFLAGS_wasm32_unknown_unknown = None
TARGET_CFLAGS = None
CFLAGS = None
CRATE_CC_NO_DEFAULTS = None
running: "clang" "-O2" "-ffunction-sections" "-fdata-sections" "-fPIC" "--target=wasm32-unknown-unknown" "-Wall" "-Wextra" "-D_GNU_SOURCE" "-DCONFIG_VERSION=\"2020-04-12\"" "-DCONFIG_BIGNUM" "-o" "/mnt/v/dprint/crates/test-plugin/target/wasm32-unknown-unknown/release/build/libquickjs-sys-62382c90b72b3b52/out/quickjs/cutils.o" "-c" "/mnt/v/dprint/crates/test-plugin/target/wasm32-unknown-unknown/release/build/libquickjs-sys-62382c90b72b3b52/out/quickjs/cutils.c"
cargo:warning=In file included from /mnt/v/dprint/crates/test-plugin/target/wasm32-unknown-unknown/release/build/libquickjs-sys-62382c90b72b3b52/out/quickjs/cutils.c:25:
cargo:warning=/usr/include/stdlib.h:25:10: fatal error: 'bits/libc-header-start.h' file not found
cargo:warning=#include <bits/libc-header-start.h>
cargo:warning=         ^~~~~~~~~~~~~~~~~~~~~~~~~~
cargo:warning=1 error generated.
exit code: 1

--- stderr
Compiling quickjs...


error occurred: Command "clang" "-O2" "-ffunction-sections" "-fdata-sections" "-fPIC" "--target=wasm32-unknown-unknown" "-Wall" "-Wextra" "-D_GNU_SOURCE" "-DCONFIG_VERSION=\"2020-04-12\"" "-DCONFIG_BIGNUM" "-o" "/mnt/v/dprint/crates/test-plugin/target/wasm32-unknown-unknown/release/build/libquickjs-sys-62382c90b72b3b52/out/quickjs/cutils.o" "-c" "/mnt/v/dprint/crates/test-plugin/target/wasm32-unknown-unknown/release/build/libquickjs-sys-62382c90b72b3b52/out/quickjs/cutils.c" with args "clang" did not execute successfully (status code exit code: 1).

Link failed as in #58

I'm getting the same issue as in #58 but cannot fix the same way, as I've included the this via Cargo.toml. Also, I'm quite new to rust :/

Anybody knows how to fix this?

I'm on fedora 32.

question: Requirement of RefUnwindSafe for Console and Callbacks

I'm curious why the requirement for RefUnwindSafe trait for Console and Callback traits is there. As I understand it, callbacks called by QuickJS might be interrupted, but it is still not clear to me how can it happen and is it possible to work around it.

I want to use tracing to log data logged in JS code using console.* functions. However, in order to do it it seems to be necessary to pass application's dispatcher inside the closure, for example like this:

let mut dispatcher = std::sync::Arc::new(tracing::dispatcher::get_default(|d| d.clone()));                              
let mut builder = Context::builder().console(                                                                           
    move |level: quick_js::console::Level, args: Vec<JsValue>| {                                                        
        tracing::dispatcher::with_default(&mut *dispatcher, || {})                                                      
    },                                                                                                                  
);                                                                                                                      

However, requirement for RefUnwindSafe trait prevents doing it:

(dyn tracing::Subscriber + std::marker::Send + std::marker::Sync + 'static)` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary

Although It is possible to use for example mpsc channels to send log events from the console closure to the main thread, I want to ensure that there is no cleaner way to do it.

Convert JsValue (Serialize, Deserialize) to standart rust types

Is there any way to convert
{"x": Int(1), "y": Int(2)} into HashMap<String, i32> - {"x": 1, "y": 2}
or
Array([Int(1), Int(2), Int(3)]) into Vec<i32>[1,2,3]?

Full code:

let context = Context::new().unwrap();

    let value = context
        .eval_as::<JsValue>(" var x = eval([1,2,3]); JSON.stringify(x); x")
        .unwrap();

    println!("{:?}", value);

    match value {
        JsValue::Null => {}
        JsValue::Bool(x) => println!("bool = {:?}", x),
        JsValue::Int(x) => println!("int = {:?}", x),
        JsValue::Float(x) => println!("float = {:?}", x),
        JsValue::String(x) => println!("string = {:?}", x),
        JsValue::Array(x) => println!("array = {:?}", x),
        JsValue::Object(x) => println!("object = {:?}", x),
        JsValue::__NonExhaustive => {}
    };

Add `bignum` feature

I've experimented with enabling Bignum extension (seems to be working just fine, can be enabled just by changing static lib name in Rust flags from quickjs to quickjs.bn). However I'm not sure what would be the correct types to map.

My idea is to have num-bigint feature that would use num-bigint crate to store values from JavaScript BigInt, which is currently stage3 and implemented by major browsers. At the same time I think maybeQuickJS's BigFloat can be ignored for now, as it is something non-standard, and also I haven't found a crate that would be a good fit to store BigFloat values in Rust.

JS_DuplValue / JS_FreeValue support in quickjs_sys bindings?

Hi,

i'm using your quickjs_sys crate for my own version of a wrapper lib (https://github.com/HiRoFa/quickjs_es_runtime) and was wondering why the JS_DupValue and JS_FreeValue from quickjs.h are not available,

Upping and downing the refcount ourselves by casting and deciding when to free seems a bit hacky?

see https://github.com/HiRoFa/quickjs_es_runtime/blob/master/src/valueref.rs#L83 for my updated version of OwnedValueRef

the quickjs impl of JS_DupValue and JS_FreeValue pretty much seem to do exactly what i do with increment_ref_count and decrement_ref_count.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.