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
4 changes: 4 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@
runner = 'wasmtime run --dir=.::/cwd --dir=. --dir=/tmp -Sinherit-env=y,inherit-network=y,http=y,tcp=y,udp=y -C native-unwind-info=n'

[target.wasm32-wasip2]
# Keep in sync with the RUSTFLAGS overrides in scripts/build-runtime.sh and scripts/build-dylib.sh.
rustflags = ["-C", "target-feature=+simd128"]
runner = 'wasmtime run --dir=.::/cwd --dir=. --dir=/tmp -Sinherit-env=y,inherit-network=y,http=y,tcp=y,udp=y -C native-unwind-info=n'

[target.wasm32-wasip3]
# Keep in sync with the RUSTFLAGS overrides in scripts/build-runtime.sh and scripts/build-dylib.sh.
rustflags = ["-C", "target-feature=+simd128"]
runner = 'wasmtime run --dir=.::/cwd --dir=. --dir=/tmp -Sinherit-env=y,inherit-network=y,http=y,tcp=y,udp=y -C native-unwind-info=n'
47 changes: 28 additions & 19 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ oxc_resolver = "11"
platform = { path = "crates/platform" }
reqwest = { version = "0.13", default-features = false, features = ["rustls", "stream"] }
serve-test-support = { path = "crates/serve-test-support" }
smallvec = "1.16"
starling-macro = { path = "crates/starling-macro" }
tokio = { version = "1", features = ["rt", "time", "net", "io-util"] }
url = "2.5.8"
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ Options:
--legacy-script Run as a classic script instead of an ES module
-v, --verbose Enable verbose logging
-d, --debug Enable script debugging via socket
--async-stacks Show async parent frames in Error.stack (always on under a debugger)
--wpt-mode Enable WPT (Web Platform Tests) mode
--init-location <URL> Override the location URL for initialization
--strip-path-prefix <PREFIX> Strip this prefix from script paths
Expand Down Expand Up @@ -140,6 +141,10 @@ is `undefined` at the top level.
**Legacy script mode** (`--legacy-script`) — sloppy mode, no
`import`/`export`, `this` is the global object.

**Exit status** — `0` when the script and all the work it scheduled complete, `1`
when the script throws or an initializer, the event loop or the runtime fails (the
error is printed to stderr), and `2` for invalid command-line arguments.

---

## Extending with Custom Builtins
Expand Down
7 changes: 7 additions & 0 deletions crates/builtins/cpp-builtins/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,13 @@ fn main() {
.flag("-mthread-model")
.flag("single")
.flag("-m32");

// `cc` does not pass the target features rustc is given on to clang, so the C++ code is
// compiled with the wasm features enabled for the Rust code here.
let features = env::var("CARGO_CFG_TARGET_FEATURE").unwrap_or_default();
if features.split(',').any(|enabled| enabled == "simd128") {
build.flag("-msimd128");
}
}

// Single unity file instead of individual sources.
Expand Down
3 changes: 2 additions & 1 deletion crates/builtins/cpp-builtins/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ mod tests {
fn eval(code: &str) -> bool {
libstarling::register_builtins();
let rt =
libstarling::runtime::Runtime::init(&libstarling::config::RuntimeConfig::default());
libstarling::runtime::Runtime::init(&libstarling::config::RuntimeConfig::default())
.expect("runtime init");
let scope = rt.default_global();
let rval = js::compile::evaluate_with_filename(&scope, code, "test.js", 1)
.expect("eval failed");
Expand Down
4 changes: 2 additions & 2 deletions crates/builtins/fetch-event/src/extendable_event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
use core_runtime::event_loop::{with_active_event_loop, InterestHandle};
use core_runtime::{jsclass, jsmethods};
use core_runtime::{webidl_dictionary, webidl_interface, webidl_methods};
use js::conversion::FromJSVal;
use js::error::{ExnThrown, ThrowException};
use js::function::cast_payload;
use js::function::CallbackArgs;
use js::gc::handle::Heap;
use js::gc::scope::Scope;
Expand Down Expand Up @@ -174,7 +174,7 @@ fn lifetime_promise_settled_cb(
_args: CallbackArgs,
payload: HandleValue,
) -> Result<Value, ExnThrown> {
let holder = LifetimePromisePayload::from_jsval(scope, payload, ()).unwrap();
let holder = cast_payload::<LifetimePromisePayload>(scope, payload);
holder
.data()
.event
Expand Down
39 changes: 22 additions & 17 deletions crates/builtins/fetch-event/src/fetch_event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use core_runtime::{webidl_dictionary, webidl_interface, webidl_methods};
use js::class::Ref;
use js::conversion::FromJSVal;
use js::error::{ExnThrown, ThrowException};
use js::function::cast_payload;
use js::function::CallbackArgs;
use js::gc::handle::Heap;
use js::gc::scope::Scope;
Expand All @@ -17,7 +18,7 @@ use js::{value, Function, Promise, PromiseOf};
use std::ops::Deref;
use web_fetch::request::{Request, RequestImpl};
use web_fetch::response::{Response, ResponseImpl};
use web_globals::dom_exception::DOMExceptionError;
use web_globals::dom_exception::{DOMException, DOMExceptionError};
use web_globals::events::algorithms::ScriptStackState;
use web_globals::events::EventTarget;

Expand Down Expand Up @@ -283,7 +284,7 @@ fn on_respond_fulfilled(
args: CallbackArgs<'_>,
payload: HandleValue<'_>,
) -> Result<Value, ExnThrown> {
let event = FetchEvent::from_jsval(scope, payload, ()).unwrap();
let event = cast_payload::<FetchEvent>(scope, payload);
// Step 10.1: If _response_ is not a `Response` object, then set the `respond-with error
// flag`.
let response =
Expand All @@ -292,22 +293,23 @@ fn on_respond_fulfilled(
// Step 10.2.2.1: If _response_ is `unusable`, then set the `respond-with error flag` and abort
// these steps.
let unusable = response.is_body_unusable(scope);
// Step 10.2.1: Let _potentialResponse_ be a copy of _response_’s associated response, except
// for its body.
// Only copying the headers, since everything else is effectively unchangeable from content.
let headers = (!unusable).then(|| response.headers_list(scope));
if !unusable {
// Steps 10.2.2 to 10.2.5 are implemented at the platform layer instead of here, except
// for the effect step 10.2.2's transform has on the response handed in, which is to take
// its body, and step 10.2.5.1's getting a reader for the body's stream, which
// `reserve_body_for_sending` acquires now so author code can no longer read from it.
response.reserve_body_for_sending(scope)?;
}
{
let mut data = event.data_mut();
if unusable {
data.respond_with_error = true;
} else {
// Steps 10.2.2 to 10.2.5 are implemented at the platform layer instead of here, except
// for the effect step 10.2.2's transform has on the response handed in, which is to
// take its body.
// `mark_body_used` has the same content-visible effect as step 10.2.5.1's getting a
// reader for the body: it locks the stream, so no other readers can be acquired.
response.mark_body_used();
data.potential_response_headers = headers;
// Step 10.2.1: Let _potentialResponse_ be a copy of _response_’s associated response,
// except for its body.
// Note: We only copy the headers, since everything else is effectively unchangeable
// from content.
data.potential_response_headers = Some(response.headers_list(scope));
// Step 10.2.6: Set _event_’s `potential response` to _potentialResponse_.
data.potential_response.set(response);
}
Expand All @@ -331,7 +333,7 @@ fn on_respond_rejected(
args: CallbackArgs<'_>,
payload: HandleValue<'_>,
) -> Result<Value, ExnThrown> {
let event = FetchEvent::from_jsval(scope, payload, ()).unwrap();
let event = cast_payload::<FetchEvent>(scope, payload);
{
let mut data = event.data_mut();
// Step 9.1: Set _event_’s `respond-with error flag`.
Expand All @@ -358,7 +360,7 @@ fn describe_rejection(scope: &Scope<'_>, reason: HandleValue<'_>) -> String {
match String::from_jsval(scope, reason, ()) {
Ok(text) => text,
Err(_) => {
let _ = js::exception::take_pending_or_undefined(scope);
js::exception::clear(scope);
"a value that could not be converted to a string".to_string()
}
}
Expand Down Expand Up @@ -398,8 +400,11 @@ impl<'s> FetchEvent<'s> {
} else {
"the fetch event was not responded to"
};
let _ = DOMExceptionError::new("NetworkError", reason).throw(scope);
handled.reject_with_pending(scope).and_then(|()| {
match DOMException::new(scope, reason.into(), "NetworkError".into()) {
Ok(exception) => handled.reject(scope, exception),
Err(_) => handled.reject_with_pending(scope),
}
.and_then(|()| {
// Most handlers never look at `handled`, and a rejection nobody subscribed to is
// reported as an unhandled rejection, which would put a spurious warning on the
// stderr of every failed request.
Expand Down
Loading
Loading