Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion crates/cli/benches/benchmark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ impl FunctionCase {
))?,
)?;
let instance = linker.instantiate(store.as_context_mut(), &plugin)?;
linker.instance(store.as_context_mut(), "javy_quickjs_provider_v3", instance)?;
linker.instance(store.as_context_mut(), "javy_quickjs_provider_v4", instance)?;
}

Ok((linker, store))
Expand Down
21 changes: 5 additions & 16 deletions crates/cli/tests/dylib_test.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,13 @@
use anyhow::Result;
use javy_runner::{Plugin, Runner, RunnerError, UseExportedFn};
use javy_runner::{Plugin, Runner, RunnerError};
use std::str;

#[test]
fn test_dylib() -> Result<()> {
fn test_dylib_with_no_fn_name() -> Result<()> {
let js_src = "console.error(42);";
let mut runner = Runner::with_dylib(plugin_module()?)?;

let (_, logs, _) = runner.exec_through_dylib(js_src, UseExportedFn::EvalBytecode)?;
assert_eq!("42\n", str::from_utf8(&logs)?);

Ok(())
}

#[test]
fn test_dylib_with_invoke_with_no_fn_name() -> Result<()> {
let js_src = "console.error(42);";
let mut runner = Runner::with_dylib(plugin_module()?)?;

let (_, logs, _) = runner.exec_through_dylib(js_src, UseExportedFn::Invoke(None))?;
let (_, logs, _) = runner.exec_through_dylib(js_src, None)?;
assert_eq!("42\n", str::from_utf8(&logs)?);

Ok(())
Expand All @@ -30,7 +19,7 @@ fn test_dylib_with_error() -> Result<()> {

let mut runner = Runner::with_dylib(plugin_module()?)?;

let res = runner.exec_through_dylib(js_src, UseExportedFn::EvalBytecode);
let res = runner.exec_through_dylib(js_src, None);

assert!(res.is_err());

Expand All @@ -50,7 +39,7 @@ fn test_dylib_with_exported_func() -> Result<()> {

let mut runner = Runner::with_dylib(plugin_module()?)?;

let (_, logs, _) = runner.exec_through_dylib(js_src, UseExportedFn::Invoke(Some("foo")))?;
let (_, logs, _) = runner.exec_through_dylib(js_src, Some("foo"))?;
assert_eq!("Toplevel\nIn foo\n", str::from_utf8(&logs)?);

Ok(())
Expand Down
12 changes: 5 additions & 7 deletions crates/codegen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,6 @@ impl Generator {
match self.linking {
LinkingKind::Static => {
let canonical_abi_realloc_fn = module.exports.get_func("canonical_abi_realloc")?;
let eval_bytecode = module.exports.get_func("eval_bytecode").ok();
let invoke = module.exports.get_func("invoke")?;
let ExportItem::Memory(memory) = module
.exports
Expand All @@ -296,7 +295,7 @@ impl Generator {
};
Ok(Identifiers::new(
canonical_abi_realloc_fn,
eval_bytecode,
None,
invoke,
memory,
))
Expand All @@ -319,9 +318,8 @@ impl Generator {
);

// User plugins can use `invoke` with a null function name.
// User plugins also won't have an `eval_bytecode` function to
// import. We want to remove `eval_bytecode` from the default
// plugin so we don't want to emit more uses of it.
// Non-v2 plugins also won't have an `eval_bytecode` function to
// import.
let eval_bytecode_fn_id = if self.plugin_kind == PluginKind::V2 {
let eval_bytecode_type = module.types.add(&[ValType::I32, ValType::I32], &[]);
let (eval_bytecode_fn_id, _) = module.add_import_func(
Expand Down Expand Up @@ -480,8 +478,8 @@ impl Generator {
// Remove no longer necessary exports.
module.exports.remove("canonical_abi_realloc")?;

// Only internal plugins expose eval_bytecode function.
if self.plugin_kind == PluginKind::Default || self.plugin_kind == PluginKind::V2 {
// Only v2 plugin exposes eval_bytecode function.
if self.plugin_kind == PluginKind::V2 {
module.exports.remove("eval_bytecode")?;
}

Expand Down
4 changes: 4 additions & 0 deletions crates/plugin-api/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Removed

- The `eval_bytecode` function was deleted.

## [3.2.0] - 2025-07-24

### Added
Expand Down
2 changes: 1 addition & 1 deletion crates/plugin-api/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "javy-plugin-api"
version = "3.2.1-alpha.1"
version = "4.0.0-alpha.1"
authors.workspace = true
edition.workspace = true
license.workspace = true
Expand Down
8 changes: 1 addition & 7 deletions crates/plugin-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,13 +158,7 @@ pub unsafe extern "C" fn invoke(
run_bytecode(bytecode, fn_name);
}

/// Evaluate the given bytecode.
///
/// Deprecated for use outside of this crate.
///
/// Evaluating also prepares (or "instantiates") the state of the JavaScript
/// engine given all the information encoded in the bytecode.
pub fn run_bytecode(bytecode: &[u8], fn_name: Option<&str>) {
fn run_bytecode(bytecode: &[u8], fn_name: Option<&str>) {
let runtime = unsafe { RUNTIME.get() }.unwrap();
runtime
.context()
Expand Down
16 changes: 1 addition & 15 deletions crates/plugin/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@ use javy_plugin_api::{import_namespace, Config};
use shared_config::SharedConfig;
use std::io;
use std::io::Read;
use std::slice;

mod shared_config;

import_namespace!("javy_quickjs_provider_v3");
import_namespace!("javy_quickjs_provider_v4");

/// Used by Wizer to preinitialize the module.
#[export_name = "initialize_runtime"]
Expand Down Expand Up @@ -34,16 +33,3 @@ pub extern "C" fn initialize_runtime() {

javy_plugin_api::initialize_runtime(config, |runtime| runtime).unwrap();
}

/// Evaluates QuickJS bytecode
///
/// # Safety
///
/// * `bytecode_ptr` must reference a valid array of unsigned bytes of `bytecode_len` length
// This will be removed as soon as we stop emitting calls to it in dynamically
// linked modules.
#[export_name = "eval_bytecode"]
pub unsafe extern "C" fn eval_bytecode(bytecode_ptr: *const u8, bytecode_len: usize) {
let bytecode = slice::from_raw_parts(bytecode_ptr, bytecode_len);
javy_plugin_api::run_bytecode(bytecode, None);
}
29 changes: 8 additions & 21 deletions crates/runner/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ impl Plugin {
Self::V2 => "javy_quickjs_provider_v2",
// Could try and derive this but not going to for now since tests
// will break if it changes.
Self::Default | Self::DefaultAsUser => "javy_quickjs_provider_v3",
Self::Default | Self::DefaultAsUser => "javy_quickjs_provider_v4",
Self::User { .. } => "test_plugin",
}
}
Expand Down Expand Up @@ -276,12 +276,6 @@ impl StoreContext {
}
}

#[derive(Debug)]
pub enum UseExportedFn {
EvalBytecode,
Invoke(Option<&'static str>),
}

impl Runner {
#[allow(clippy::too_many_arguments)]
fn build(
Expand Down Expand Up @@ -690,28 +684,21 @@ impl Runner {
pub fn exec_through_dylib(
&mut self,
src: &str,
use_exported_fn: UseExportedFn,
func: Option<&str>,
) -> Result<(Vec<u8>, Vec<u8>, u64)> {
let mut store = Self::setup_store(self.linker.engine(), vec![])?;
let module = Module::from_binary(self.linker.engine(), &self.wasm)?;

let instance = self.linker.instantiate(store.as_context_mut(), &module)?;

let (bc_ptr, bc_len) = Self::compile(src.as_bytes(), store.as_context_mut(), &instance)?;
let res = match use_exported_fn {
UseExportedFn::EvalBytecode => instance
.get_typed_func::<(u32, u32), ()>(store.as_context_mut(), "eval_bytecode")?
.call(store.as_context_mut(), (bc_ptr, bc_len)),
UseExportedFn::Invoke(func) => {
let (fn_ptr, fn_len) = match func {
Some(func) => Self::copy_func_name(func, &instance, store.as_context_mut())?,
None => (0, 0),
};
instance
.get_typed_func::<(u32, u32, u32, u32), ()>(store.as_context_mut(), "invoke")?
.call(store.as_context_mut(), (bc_ptr, bc_len, fn_ptr, fn_len))
}
let (fn_ptr, fn_len) = match func {
Some(func) => Self::copy_func_name(func, &instance, store.as_context_mut())?,
None => (0, 0),
};
let res = instance
.get_typed_func::<(u32, u32, u32, u32), ()>(store.as_context_mut(), "invoke")?
.call(store.as_context_mut(), (bc_ptr, bc_len, fn_ptr, fn_len));

self.extract_store_data(res, store)
}
Expand Down
2 changes: 1 addition & 1 deletion docs/docs-using-dynamic-linking.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,6 @@ Run:
$ echo 'console.log("hello world!");' > my_code.js
$ javy emit-plugin -o plugin.wasm
$ javy build -C dynamic -C plugin=plugin.wasm -o my_code.wasm my_code.js
$ wasmtime run --preload javy_quickjs_provider_v3=plugin.wasm my_code.wasm
$ wasmtime run --preload javy_quickjs_provider_v4=plugin.wasm my_code.wasm
hello world!
```
2 changes: 1 addition & 1 deletion docs/docs-using-nodejs.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ async function runJavy(pluginModule, embeddedModule, input) {
wasi.getImportObject(),
);
const instance = await WebAssembly.instantiate(embeddedModule, {
javy_quickjs_provider_v3: pluginInstance.exports,
javy_quickjs_provider_v4: pluginInstance.exports,
});

// Javy plugin is a WASI reactor see https://github.com/WebAssembly/WASI/blob/main/legacy/application-abi.md?plain=1
Expand Down