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: 2 additions & 2 deletions Cargo.lock

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

7 changes: 3 additions & 4 deletions Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ PWD := replace(justfile_dir(), "\\", "/")
# * include the stubs required by hyperlight-js-runtime
# * define __wasi__ as this disables threading support in quickjs
export HYPERLIGHT_CFLAGS := \
"-I" + PWD + "/src/hyperlight-js-runtime/stubs/include " + \
"-I" + PWD + "/src/hyperlight-js-runtime/include " + \
"-D__wasi__=1 "

# On Windows, use Ninja generator for CMake to avoid aws-lc-sys build issues with Visual Studio generator
export CMAKE_GENERATOR := if os() == "windows" { "Ninja" } else { "" }

ensure-tools:
cargo install cargo-hyperlight --locked --version 0.1.3
cargo install cargo-hyperlight --locked

# Check if npm is installed, install automatically if missing (Linux)
[private]
Expand All @@ -39,8 +39,7 @@ check-license-headers:
./dev/check-license-headers.sh

clippy target=default-target features="": (ensure-tools)
cd src/hyperlight-js-runtime && \
cargo hyperlight clippy \
cargo hyperlight clippy -p hyperlight-js-runtime \
--profile={{ if target == "debug" {"dev"} else { target } }} \
-- -D warnings
cargo clippy --all-targets \
Expand Down
4 changes: 2 additions & 2 deletions src/hyperlight-js-runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,17 @@ tracing = { version = "0.1.44", default-features = false, features = ["log","att
hyperlight-common = { workspace = true, default-features = false }
hyperlight-guest = { workspace = true }
hyperlight-guest-bin = { workspace = true }
chrono = { version = "0.4", default-features = false }

[target.'cfg(not(hyperlight))'.dependencies]
clap = { version = "4.5", features = ["derive"] }
libc = "0.2"

[target.'cfg(not(hyperlight))'.dev-dependencies]
escargot = "0.5"
tempfile = "3.26"

[build-dependencies]
cc = "1.2"
bindgen = "0.72"

[features]
default = []
Expand Down
40 changes: 31 additions & 9 deletions src/hyperlight-js-runtime/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,38 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
fn main() {
if std::env::var_os("CARGO_CFG_HYPERLIGHT").is_none() {
return;
}

let files = ["stubs/clock.c", "stubs/localtime.c"];
use std::env;
use std::path::PathBuf;

for file in files {
println!("cargo:rerun-if-changed={}", file);
}
use bindgen::RustEdition::Edition2024;

cc::Build::new().files(files).compile("stubs");
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut bindings = bindgen::builder()
.use_core()
.wrap_unsafe_ops(true)
.rust_edition(Edition2024)
.clang_arg("-D_POSIX_MONOTONIC_CLOCK=1")
.clang_arg("-D_POSIX_C_SOURCE=200809L");

bindings = bindings.header_contents(
"libc.h",
"
#pragma once
#include <errno.h>
#include <stdio.h>
#include <time.h>
",
);

println!("cargo:rerun-if-changed=include");
println!("cargo:rerun-if-changed=include/stdio.h");
println!("cargo:rerun-if-changed=include/time.h");
println!("cargo:rerun-if-changed=include/unistd.h");

// Write the generated bindings to an output file.
let out_path = PathBuf::from(env::var("OUT_DIR")?).join("libc.rs");
bindings.generate()?.write_to_file(out_path)?;

Ok(())
}
29 changes: 29 additions & 0 deletions src/hyperlight-js-runtime/include/stdio.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
Copyright 2026 The Hyperlight Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once

#include "printf.h"
#include_next "stdio.h"

#define stdout NULL

int putchar(int c);

#define vfprintf(f, ...) vprintf(__VA_ARGS__)
#define fprintf(f, ...) printf(__VA_ARGS__)
#define fputc(c, f) putc((char)(c), f)

int fflush(FILE *f);
28 changes: 28 additions & 0 deletions src/hyperlight-js-runtime/include/time.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
Copyright 2026 The Hyperlight Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once

#include_next "time.h"

#include <sys/time.h>
#include <sys/types.h>
#include <errno.h>

#define CLOCK_REALTIME 0
#define CLOCK_MONOTONIC 1

int clock_gettime(clockid_t clk_id, struct timespec *tp);
struct tm *localtime_r(const time_t *timer, struct tm *tm);
15 changes: 15 additions & 0 deletions src/hyperlight-js-runtime/include/unistd.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
Copyright 2026 The Hyperlight Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
1 change: 1 addition & 0 deletions src/hyperlight-js-runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ extern crate alloc;
mod globals;
pub mod host;
mod host_fn;
mod libc;
mod modules;
pub(crate) mod utils;

Expand Down
31 changes: 31 additions & 0 deletions src/hyperlight-js-runtime/src/libc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
Copyright 2026 The Hyperlight Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
mod bindings {
#![allow(
non_camel_case_types,
non_snake_case,
non_upper_case_globals,
dead_code,
unnecessary_transmutes,
clippy::upper_case_acronyms,
clippy::ptr_offset_with_cast
)]
include!(concat!(env!("OUT_DIR"), "/libc.rs"));
}

pub(crate) use core::ffi::*;

pub(crate) use bindings::*;
3 changes: 3 additions & 0 deletions src/hyperlight-js-runtime/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ limitations under the License.
#![cfg_attr(hyperlight, no_std)]
#![cfg_attr(hyperlight, no_main)]

#[cfg(hyperlight)]
mod libc;

#[cfg(hyperlight)]
include!("main/hyperlight.rs");

Expand Down
49 changes: 2 additions & 47 deletions src/hyperlight-js-runtime/src/main/hyperlight.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,6 @@ limitations under the License.
*/
extern crate alloc;

use core::ffi::*;
use core::time::Duration;

use alloc::format;
use alloc::string::String;
use alloc::vec::Vec;
Expand All @@ -32,6 +29,8 @@ use hyperlight_guest_bin::{guest_function, host_function};
use spin::Mutex;
use tracing::instrument;

mod stubs;

struct Host;

pub trait CatchGuestErrorExt {
Expand Down Expand Up @@ -126,11 +125,6 @@ fn register_host_modules(host_modules_json: String) -> Result<()> {
Ok(())
}

#[unsafe(no_mangle)]
pub extern "C" fn srand(_seed: u32) {
// No-op
}

#[unsafe(no_mangle)]
pub fn guest_dispatch_function(function_call: FunctionCall) -> Result<Vec<u8>> {
let params = function_call.parameters.unwrap_or_default();
Expand All @@ -139,42 +133,3 @@ pub fn guest_dispatch_function(function_call: FunctionCall) -> Result<Vec<u8>> {
let result = RUNTIME.lock().run_handler(function_name, event, run_gc)?;
Ok(get_flatbuffer_result(result.as_str()))
}

/// # Safety
/// This function is used by the C code to get the current time in seconds and nanoseconds.
/// `ts` must be a valid pointer to an array of two `u64` values.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn _current_time(ts: *mut u64) -> c_int {
#[host_function("CurrentTimeMicros")]
fn current_time_micros() -> Result<u64>;

let dur = current_time_micros().unwrap_or(1609459200u64 * 1_000_000u64);
let dur = Duration::from_micros(dur);

let ts = unsafe { core::slice::from_raw_parts_mut(ts, 2) };
ts[0] = dur.as_secs();
ts[1] = dur.subsec_nanos() as u64;

0
}

#[unsafe(no_mangle)]
pub extern "C" fn putchar(c: c_int) -> c_int {
unsafe { hyperlight_guest_bin::host_comm::_putchar(c as c_char) };
if c == '\n' as c_int {
// force a flush of the internal buffer in the hyperlight putchar implementation
unsafe { hyperlight_guest_bin::host_comm::_putchar(0) };
}
(c as c_char) as c_int
}

#[unsafe(no_mangle)]
pub extern "C" fn fflush(f: *mut c_void) -> c_int {
if !f.is_null() {
// we only support flushing all streams, and stdout is our only stream
return -1;
}
// flush stdout
putchar('\0' as _);
0
}
57 changes: 57 additions & 0 deletions src/hyperlight-js-runtime/src/main/stubs/clock.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
Copyright 2026 The Hyperlight Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
use hyperlight_guest::error::Result;
use hyperlight_guest_bin::host_function;

use crate::libc;

fn micros_since_epoch() -> u64 {
#[host_function("CurrentTimeMicros")]
fn current_time_micros() -> Result<u64>;

current_time_micros().unwrap_or(1609459200u64 * 1_000_000u64)
}

#[unsafe(no_mangle)]
extern "C" fn clock_gettime(clk_id: libc::clockid_t, ts: *mut libc::timespec) -> libc::c_int {
const CLOCK_REALTIME: libc::clockid_t = libc::CLOCK_REALTIME as libc::clockid_t;
const CLOCK_MONOTONIC: libc::clockid_t = libc::CLOCK_MONOTONIC as libc::clockid_t;

if clk_id != CLOCK_REALTIME && clk_id != CLOCK_MONOTONIC {
unsafe { libc::__errno_location().write(libc::EINVAL as _) };
return -1;
}
let micros = micros_since_epoch();
unsafe {
ts.write(libc::timespec {
tv_sec: (micros / 1_000_000) as _,
tv_nsec: ((micros % 1_000_000) * 1000) as _,
})
};
0
}

#[unsafe(no_mangle)]
extern "C" fn gettimeofday(tp: *mut libc::timeval, _tz: *mut libc::c_void) -> libc::c_int {
let micros = micros_since_epoch();
unsafe {
tp.write(libc::timeval {
tv_sec: (micros / 1_000_000) as _,
tv_usec: (micros % 1_000_000) as _,
});
}
0
}
Loading