WASI Target Support #1633
-
|
Originally posted by @milas in #9 :
Originally posted by @milas in #1616 (comment): Hi! I'm interested in this PR from the perspective of WASI compatibility: #9 (comment) I attached a diff from a POC -- I successfully compiled/used (mainline) VRL via WASI (Go/wazero) but was focused on getting something compiling just to understand how far off we are currently. vrl-wasi.patchcommit 50ccec7c2207b0f6e1bc593585dd9e7c9e302502
Author: Milas Bowman <milas@realm.security>
Date: Wed Jan 21 19:50:45 2026 -0500
feat: add wasm32-wasi support
This commit enables VRL to compile for the wasm32-wasip1 target by:
- Gating OS-specific dependencies (iana-time-zone, hostname) to non-WASM targets.
- Removing the 'wasmbind' feature from chrono.
- Adding a fallback to UTC for 'TimeZone::Local' on WASM, since WASI lacks system local time.
diff --git a/Cargo.lock b/Cargo.lock
index 40d21b0e8..1db2e4e34 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -450,10 +450,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2"
dependencies = [
"iana-time-zone",
- "js-sys",
"num-traits",
"serde",
- "wasm-bindgen",
"windows-link 0.2.0",
]
diff --git a/Cargo.toml b/Cargo.toml
index ee2b101b8..4793ceadc 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -134,7 +134,7 @@ base64-simd = { version = "0.8", optional = true }
bytes = { version = "1", default-features = false, optional = true }
charset = { version = "0.1", optional = true }
encoding_rs = { version = "0.8.35", optional = true }
-chrono = { version = "0.4", default-features = false, features = ["clock", "serde", "wasmbind"], optional = true }
+chrono = { version = "0.4", default-features = false, features = ["serde"], optional = true }
chrono-tz = { version = "0.10", default-features = false, optional = true }
ciborium = { version = "0.2.2", default-features = false, optional = true }
cidr = { version = "0.3", optional = true }
@@ -149,7 +149,6 @@ exitcode = { version = "1", optional = true }
flate2 = { version = "1.1.2", default-features = false, features = ["zlib-rs"], optional = true }
hex = { version = "0.4", optional = true }
hmac = { version = "0.12", optional = true }
-iana-time-zone = { version = "0.1", optional = true }
idna = { version = "1.0", optional = true }
indexmap = { version = "2", default-features = false, features = ["std"], optional = true }
influxdb-line-protocol = { version = "2.0.0", optional = true }
@@ -206,7 +205,7 @@ xxhash-rust = { version = "0.8", optional = true, features = [
] }
community-id = { version = "0.2", optional = true }
-zstd = { version = "0.13", default-features = false, features = ["wasm"], optional = true }
+zstd = { version = "0.13", default-features = false, features = ["wasm", "thin"], optional = true }
# Cryptography
aes = { version = "0.8", optional = true }
@@ -235,9 +234,11 @@ reqwest-retry = { version = "0.7", default-features = false }
# Dependencies used for non-WASM
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
+chrono = { version = "0.4", default-features = false, features = ["clock"] }
+iana-time-zone = { version = "0.1", optional = true }
+hostname = { version = "0.4", optional = true }
dns-lookup = { version = "2", optional = true }
domain = { version = "0.11.0", optional = true, features = ["resolv-sync", "serde"] }
-hostname = { version = "0.4", optional = true }
grok = { version = "2.4", optional = true }
onig = { version = "6", default-features = false, optional = true }
tokio = { version = "1.45", optional = true, features = ["io-util", "macros", "net", "time", "sync", "rt", "rt-multi-thread"] }
diff --git a/src/compiler/datetime.rs b/src/compiler/datetime.rs
index 2d3ab280c..080c68f59 100644
--- a/src/compiler/datetime.rs
+++ b/src/compiler/datetime.rs
@@ -1,7 +1,9 @@
use std::fmt::Debug;
use chrono::format::{Parsed, StrftimeItems, parse};
-use chrono::{DateTime, FixedOffset, Local, Offset, ParseError, TimeZone as _, Utc};
+use chrono::{DateTime, FixedOffset, Offset, ParseError, TimeZone as _, Utc};
+#[cfg(not(target_arch = "wasm32"))]
+use chrono::Local;
use chrono_tz::Tz;
use serde::{Deserialize, Serialize};
@@ -39,8 +41,16 @@ impl TimeZone {
match self {
Self::Local => {
- let local_datetime = parsed.to_datetime_with_timezone(&Local)?;
- Ok(datetime_to_utc(&local_datetime))
+ #[cfg(not(target_arch = "wasm32"))]
+ {
+ let local_datetime = parsed.to_datetime_with_timezone(&Local)?;
+ Ok(datetime_to_utc(&local_datetime))
+ }
+ #[cfg(target_arch = "wasm32")]
+ {
+ let utc_datetime = parsed.to_datetime_with_timezone(&Utc)?;
+ Ok(utc_datetime)
+ }
}
Self::Named(tz) => {
let tz_datetime = parsed.to_datetime_with_timezone(tz)?;
@@ -88,7 +98,16 @@ impl TryFrom<String> for TimeZone {
impl From<TimeZone> for FixedOffset {
fn from(tz: TimeZone) -> Self {
match tz {
- TimeZone::Local => *Utc::now().with_timezone(&Local).offset(),
+ TimeZone::Local => {
+ #[cfg(not(target_arch = "wasm32"))]
+ {
+ *Utc::now().with_timezone(&Local).offset()
+ }
+ #[cfg(target_arch = "wasm32")]
+ {
+ chrono::FixedOffset::east_opt(0).unwrap()
+ }
+ }
TimeZone::Named(tz) => Utc::now().with_timezone(&tz).offset().fix(),
}
}
diff --git a/src/stdlib/get_timezone_name.rs b/src/stdlib/get_timezone_name.rs
index 150edc962..5d9d2cf00 100644
--- a/src/stdlib/get_timezone_name.rs
+++ b/src/stdlib/get_timezone_name.rs
@@ -1,4 +1,5 @@
use crate::compiler::prelude::*;
+#[cfg(not(target_arch = "wasm32"))]
use chrono::Local;
use std::borrow::Cow;
@@ -6,9 +7,18 @@ use std::borrow::Cow;
pub fn get_name_for_timezone(tz: &TimeZone) -> Cow<'_, str> {
match tz {
TimeZone::Named(tz) => tz.name().into(),
- TimeZone::Local => iana_time_zone::get_timezone()
- .unwrap_or_else(|_| Local::now().offset().to_string())
- .into(),
+ TimeZone::Local => {
+ #[cfg(not(target_arch = "wasm32"))]
+ {
+ iana_time_zone::get_timezone()
+ .unwrap_or_else(|_| Local::now().offset().to_string())
+ .into()
+ }
+ #[cfg(target_arch = "wasm32")]
+ {
+ "UTC".into()
+ }
+ }
}
}From a features standpoint, I do think the no system/no env make sense, especially for a pure wasm32 target, but I am wondering if there's a mix of target conditionals + features that would be helpful? Copy-pasting these to a new discussion: I'm happy to contribute PRs and testing here, but I'm trying to gauge if there's any interest/appetite from maintainers first. If this is not of interest for the project, that's fine! Just hoping to get direction one way or another. |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
|
Hi @milas, we already have a WASM VRL build here, we can maybe build on top of that. AFAICT these changes are not necessary to build for a WASM target. Could you provide a set of commands so I can try to build this myself on the latest changes to A WASI build is a nice to have, but this is not something we're actively looking to implement at the moment because there are a quite few higher priority projects pending. However, we absolutely welcome community contributions and do our best to provide guidance and timely reviews for those. This would be a nice addition to the project. |
Beta Was this translation helpful? Give feedback.
Hi @milas,
we already have a WASM VRL build here, we can maybe build on top of that. AFAICT these changes are not necessary to build for a WASM target. Could you provide a set of commands so I can try to build this myself on the latest changes to
main?A WASI build is a nice to have, but this is not something we're actively looking to implement at the moment because there are a quite few higher priority projects pending. However, we absolutely welcome community contributions and do our best to provide guidance and timely reviews for those. This would be a nice addition to the project.