Skip to content

Commit

Permalink
Make event loop a runtime config instead of a Cargo feature
Browse files Browse the repository at this point in the history
  • Loading branch information
jeffcharles committed Nov 22, 2024
1 parent f955893 commit c91eca7
Show file tree
Hide file tree
Showing 20 changed files with 100 additions and 80 deletions.
29 changes: 0 additions & 29 deletions .github/workflows/cli-features.yml

This file was deleted.

2 changes: 1 addition & 1 deletion .github/workflows/wpt.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:

- name: WPT
run: |
cargo build --package=javy-plugin --release --target=wasm32-wasip1 --features=experimental_event_loop
cargo build --package=javy-plugin --release --target=wasm32-wasip1
CARGO_PROFILE_RELEASE_LTO=off cargo build --package=javy-cli --release
npm install --prefix wpt
npm test --prefix wpt
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.

6 changes: 1 addition & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,7 @@ test-cli: plugin build-test-plugin
test-runner:
cargo test --package=javy-runner -- --nocapture

# WPT requires a Javy build with the experimental_event_loop feature to pass
test-wpt: export PLUGIN_FEATURES ?= experimental_event_loop
test-wpt:
# Can't use a prerequisite here b/c a prequisite will not cause a rebuild of the CLI
$(MAKE) cli
test-wpt: cli
npm install --prefix wpt
npm test --prefix wpt

Expand Down
1 change: 0 additions & 1 deletion crates/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ path = "src/main.rs"

[features]
dump_wat = ["dep:wasmprinter"]
experimental_event_loop = []

[dependencies]
wizer = { workspace = true }
Expand Down
25 changes: 14 additions & 11 deletions crates/cli/tests/integration_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,19 +181,20 @@ fn test_readme_script(builder: &mut Builder) -> Result<()> {
Ok(())
}

#[cfg(feature = "experimental_event_loop")]
#[javy_cli_test]
fn test_promises(builder: &mut Builder) -> Result<()> {
let mut runner = builder.input("promise.js").build()?;
#[javy_cli_test(commands(not(Compile)))]
fn test_promises_with_event_loop(builder: &mut Builder) -> Result<()> {
let mut runner = builder
.input("promise.js")
.experimental_event_loop(true)
.build()?;

let (output, _, _) = run(&mut runner, &[]);
assert_eq!("\"foo\"\"bar\"".as_bytes(), output);
Ok(())
}

#[cfg(not(feature = "experimental_event_loop"))]
#[javy_cli_test]
fn test_promises(builder: &mut Builder) -> Result<()> {
fn test_promises_without_event_loop(builder: &mut Builder) -> Result<()> {
use javy_runner::RunnerError;

let mut runner = builder.input("promise.js").build()?;
Expand All @@ -204,10 +205,12 @@ fn test_promises(builder: &mut Builder) -> Result<()> {
Ok(())
}

#[cfg(feature = "experimental_event_loop")]
#[javy_cli_test]
#[javy_cli_test(commands(not(Compile)))]
fn test_promise_top_level_await(builder: &mut Builder) -> Result<()> {
let mut runner = builder.input("top-level-await.js").build()?;
let mut runner = builder
.input("top-level-await.js")
.experimental_event_loop(true)
.build()?;
let (out, _, _) = run(&mut runner, &[]);

assert_eq!("bar", String::from_utf8(out)?);
Expand All @@ -229,13 +232,13 @@ fn test_exported_functions(builder: &mut Builder) -> Result<()> {
Ok(())
}

#[cfg(feature = "experimental_event_loop")]
#[javy_cli_test]
#[javy_cli_test(commands(not(Compile)))]
fn test_exported_promises(builder: &mut Builder) -> Result<()> {
let mut runner = builder
.input("exported-promise-fn.js")
.wit("exported-promise-fn.wit")
.world("exported-promise-fn")
.experimental_event_loop(true)
.build()?;
let (_, logs, _) = run_fn(&mut runner, "foo", &[]);
assert_eq!("Top-level\ninside foo\n", logs);
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]

### Changed

- `initialize_runtime` accepts a `javy_plugin_api::Config` instead of a `javy_plugin_api::javy::Config`

## [1.0.0] - 2024-11-12

Initial release
3 changes: 1 addition & 2 deletions 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 = "1.0.1-alpha.1"
version = "2.0.0-alpha.1"
authors.workspace = true
edition.workspace = true
license.workspace = true
Expand All @@ -14,5 +14,4 @@ anyhow = { workspace = true }
javy = { workspace = true, features = ["export_alloc_fns"] }

[features]
experimental_event_loop = []
json = ["javy/json"]
2 changes: 1 addition & 1 deletion crates/plugin-api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Example usage:

```rust
use javy_plugin_api::import_namespace;
use javy_plugin_api::javy::Config;
use javy_plugin_api::Config;

// Dynamically linked modules will use `my_javy_plugin_v1` as the import
// namespace.
Expand Down
32 changes: 32 additions & 0 deletions crates/plugin-api/src/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
use std::ops::{Deref, DerefMut};

#[derive(Default)]
/// A configuration for the Javy plugin API.
pub struct Config {
/// The runtime config.
pub(crate) runtime_config: javy::Config,
/// Whether to enable the experimental event loop.
pub(crate) experimental_event_loop: bool,
}

impl Config {
/// Whether to enable the experimental event loop.
pub fn experimental_event_loop(&mut self, enabled: bool) -> &mut Self {
self.experimental_event_loop = enabled;
self
}
}

impl Deref for Config {
type Target = javy::Config;

fn deref(&self) -> &Self::Target {
&self.runtime_config
}
}

impl DerefMut for Config {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.runtime_config
}
}
18 changes: 10 additions & 8 deletions crates/plugin-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
//! Example usage:
//! ```rust
//! use javy_plugin_api::import_namespace;
//! use javy_plugin_api::javy::Config;
//! use javy_plugin_api::Config;
//!
//! // Dynamically linked modules will use `my_javy_plugin_v1` as the import
//! // namespace.
Expand All @@ -28,28 +28,29 @@
//! * [`import_namespace`] - required to provide an import namespace when the
//! plugin is used to generate dynamically linked modules.
//! * [`initialize_runtime`] - used to configure the QuickJS runtime with a
//! [`javy::Config`] and to add behavior to the created [`javy::Runtime`].
//! [`Config`] to add behavior to the created [`javy::Runtime`].
//!
//! # Features
//! * `experimental_event_loop` - enables the JS event loop. A number of
//! important things are not yet supported so be careful when enabling.
//! * `json` - enables the `json` feature in the `javy` crate.
use anyhow::{anyhow, bail, Error, Result};
pub use config::Config;
use javy::quickjs::{self, Ctx, Error as JSError, Function, Module, Value};
use javy::{from_js_error, Config, Runtime};
use javy::{from_js_error, Runtime};
use std::cell::OnceCell;
use std::{process, slice, str};

pub use javy;

mod config;
mod namespace;

const FUNCTION_MODULE_NAME: &str = "function.mjs";

static mut COMPILE_SRC_RET_AREA: [u32; 2] = [0; 2];

static mut RUNTIME: OnceCell<Runtime> = OnceCell::new();
static mut EVENT_LOOP_ENABLED: bool = false;

static EVENT_LOOP_ERR: &str = r#"
Pending jobs in the event queue.
Expand All @@ -62,7 +63,7 @@ pub fn initialize_runtime<F>(config: Config, modify_runtime: F) -> Result<()>
where
F: FnOnce(Runtime) -> Runtime,
{
let runtime = Runtime::new(config).unwrap();
let runtime = Runtime::new(config.runtime_config).unwrap();
let runtime = modify_runtime(runtime);
unsafe {
RUNTIME.take(); // Allow re-initializing.
Expand All @@ -73,6 +74,7 @@ where
// implement `Debug`.
.map_err(|_| anyhow!("Could not pre-initialize javy::Runtime"))
.unwrap();
EVENT_LOOP_ENABLED = config.experimental_event_loop;
};
Ok(())
}
Expand Down Expand Up @@ -182,7 +184,7 @@ pub fn run_bytecode(bytecode: &[u8], fn_name: Option<&str>) {
fn handle_maybe_promise(this: Ctx, value: Value) -> quickjs::Result<()> {
match value.as_promise() {
Some(promise) => {
if cfg!(feature = "experimental_event_loop") {
if unsafe { EVENT_LOOP_ENABLED } {
// If the experimental event loop is enabled, trigger it.
let resolved = promise.finish::<Value>();
// `Promise::finish` returns Err(Wouldblock) when the all
Expand All @@ -205,7 +207,7 @@ fn handle_maybe_promise(this: Ctx, value: Value) -> quickjs::Result<()> {
}

fn ensure_pending_jobs(rt: &Runtime) -> Result<()> {
if cfg!(feature = "experimental_event_loop") {
if unsafe { EVENT_LOOP_ENABLED } {
rt.resolve_pending_jobs()
} else if rt.has_pending_jobs() {
bail!(EVENT_LOOP_ERR);
Expand Down
3 changes: 0 additions & 3 deletions crates/plugin/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,3 @@ anyhow = { workspace = true }
javy-plugin-api = { path = "../plugin-api", features = ["json"] }
serde = { workspace = true }
serde_json = { workspace = true }

[features]
experimental_event_loop = ["javy-plugin-api/experimental_event_loop"]
3 changes: 1 addition & 2 deletions crates/plugin/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use javy_plugin_api::import_namespace;
use javy_plugin_api::javy::Config;
use javy_plugin_api::{import_namespace, Config};
use shared_config::SharedConfig;
use std::io;
use std::io::Read;
Expand Down
8 changes: 7 additions & 1 deletion crates/plugin/src/shared_config/mod.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
//! APIs and data structures for receiving runtime configuration from the Javy CLI.
use anyhow::Result;
use javy_plugin_api::Config;
use serde::Deserialize;
use std::io::{stdout, Write};

mod runtime_config;

use crate::{runtime_config, Config};
use crate::runtime_config;

runtime_config! {
#[derive(Debug, Default, Deserialize)]
Expand All @@ -25,6 +26,8 @@ runtime_config! {
/// Whether to enable support for the `TextEncoder` and `TextDecoder`
/// APIs.
text_encoding: Option<bool>,
/// Whether to enable the experimental event loop.
experimental_event_loop: Option<bool>,
}
}

Expand All @@ -49,6 +52,9 @@ impl SharedConfig {
if let Some(enable) = self.text_encoding {
config.text_encoding(enable);
}
if let Some(enable) = self.experimental_event_loop {
config.experimental_event_loop(enable);
}
}
}

Expand Down
Loading

0 comments on commit c91eca7

Please sign in to comment.