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
5 changes: 3 additions & 2 deletions 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 Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ serde_path_to_error = "0.1.16"
simd-json = "0.17.0"
thiserror = "1.0"
tokio = { version = "1.47.1" }
tokio-fs-ext = "0.7.3"
tokio-fs-ext = "0.7.7"
toml = "0.8"
tracing = "0.1.41"
tracing-subscriber = { version = "0.3.19", features = ["env-filter", "fmt"] }
Expand Down
1 change: 1 addition & 0 deletions crates/utoo-wasm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ wasm-bindgen-futures = "0.4.58"
pack-api = { workspace = true, optional = true }
pack-core = { workspace = true, optional = true }
parking_lot = { workspace = true, features = ["nightly"] }
swc_core = { workspace = true, features = ["base", "ecma_ast"] }
turbo-rcstr = { workspace = true, optional = true }
turbo-tasks = { workspace = true, optional = true }
turbo-tasks-backend = { workspace = true, optional = true }
Expand Down
49 changes: 48 additions & 1 deletion crates/utoo-wasm/src/errors.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,55 @@
use std::io;
use wasm_bindgen::prelude::*;

// Helper macro to define constants and their JS getters (exported as functions)
macro_rules! define_error_consts {
($($name:ident, $fn_name:ident = $val:expr),* $(,)?) => {
$(
// Internal Rust constant
pub const $name: &str = $val;

// Exported JS function returning the string
#[wasm_bindgen(js_name = $name)]
pub fn $fn_name() -> String {
$name.to_string()
}
)*
};
}

define_error_consts! {
ERR_NOT_FOUND, err_not_found = "NotFoundError",
ERR_KEY_ALREADY_EXISTS, err_key_already_exists = "NoModificationAllowedError",
ERR_NOT_ALLOWED, err_not_allowed = "NotAllowedError",
ERR_NO_MODIFICATION_ALLOWED, err_no_modification_allowed = "NoModificationAllowedError",
ERR_TYPE_MISMATCH, err_type_mismatch = "TypeMismatchError",
ERR_QUOTA_EXCEEDED, err_quota_exceeded = "QuotaExceededError",
ERR_INVALID_STATE, err_invalid_state = "InvalidStateError",
ERR_ABORT, err_abort = "AbortError",
}

pub fn to_js_error<E>(e: E) -> JsError
where
E: Into<anyhow::Error>,
{
JsError::new(&format!("{:#?}", e.into()))
let err = e.into();

if let Some(io_err) = err.downcast_ref::<io::Error>() {
let prefix = match io_err.kind() {
io::ErrorKind::NotFound => ERR_NOT_FOUND,
io::ErrorKind::PermissionDenied => ERR_NOT_ALLOWED,
io::ErrorKind::WouldBlock => ERR_NO_MODIFICATION_ALLOWED,
io::ErrorKind::InvalidData => ERR_TYPE_MISMATCH,
io::ErrorKind::StorageFull => ERR_QUOTA_EXCEEDED,
io::ErrorKind::InvalidInput => ERR_INVALID_STATE,
io::ErrorKind::Interrupted => ERR_ABORT,
_ => "",
Comment thread
xusd320 marked this conversation as resolved.
Resolved
};

if !prefix.is_empty() {
return JsError::new(&format!("{}: {}", prefix, io_err));
}
}

JsError::new(&format!("{:#?}", err))
}
22 changes: 5 additions & 17 deletions crates/utoo-wasm/src/pack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -350,22 +350,7 @@ pub async fn build() -> std::result::Result<JsValue, wasm_bindgen::JsError> {
})
.await?;

tracing::info!("all project entrypoints wrote to disk.");

tracing::info!(
"pack tasks with {} apps {} libraries finished in {:?}",
entrypoints
.apps
.as_ref()
.map(|apps| apps.0.len())
.unwrap_or_default(),
entrypoints
.libraries
.as_ref()
.map(|libraries| libraries.0.len())
.unwrap_or_default(),
start.elapsed()
);
tracing::info!("build finished in {:?}", start.elapsed());

let result = TurbopackResult {
issues: issues.iter().map(|i| Issue::from(&**i)).collect(),
Expand Down Expand Up @@ -417,7 +402,8 @@ pub async fn project_entrypoints_subscribe(
turbo_tasks_clone.spawn_root_task(move || {
let tx = tx.clone();
async move {
tracing::debug!("entrypointsSubscribe root task executing");
let start = Instant::now();
tracing::info!("dev build started...");

let entrypoints_with_issues_op =
get_all_written_entrypoints_with_issues_operation(container);
Expand All @@ -431,6 +417,8 @@ pub async fn project_entrypoints_subscribe(
.await?;
effects.apply().await?;

tracing::info!("dev build finished in {:?}", start.elapsed());

let turbopack_result = TurbopackResult {
issues: issues.iter().map(|i| Issue::from(&**i)).collect(),
diagnostics: diagnostics.iter().map(|d| Diagnostic::from(d)).collect(),
Expand Down
50 changes: 42 additions & 8 deletions crates/utoo-wasm/src/tokio_runtime.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
use std::{
cell::OnceCell,
cell::{OnceCell, RefCell},
sync::{
atomic::{AtomicUsize, Ordering},
OnceLock,
},
time::Duration,
};

use tokio::runtime::{self, Runtime};
use tokio::{
runtime::{self, Runtime},
time::Instant,
};

#[cfg(feature = "utoopack")]
thread_local! {
static LAST_SWC_ATOM_GC_TIME: RefCell<Option<Instant>> = const { RefCell::new(None) };
}

pub static TOKIO_RUNTIME: OnceLock<Runtime> = OnceLock::new();

Expand All @@ -20,14 +28,40 @@ pub fn runtime() -> &'static Runtime {

pub fn init_tokio_runtime(worker_url: String) {
TOKIO_RUNTIME.get_or_init(|| {
runtime::Builder::new_multi_thread()
let concurrency = (|| {
let global = js_sys::global();
let navigator =
js_sys::Reflect::get(&global, &wasm_bindgen::JsValue::from_str("navigator"))
.ok()?;
let concurrency = js_sys::Reflect::get(
&navigator,
&wasm_bindgen::JsValue::from_str("hardwareConcurrency"),
)
.ok()?;
concurrency.as_f64().map(|v| (v as usize).max(1))
})()
.unwrap_or(1);

let mut builder = runtime::Builder::new_multi_thread();
builder
.disable_lifo_slot()
.thread_name_fn(|| {
static ATOMIC_ID: AtomicUsize = AtomicUsize::new(1);
let id = ATOMIC_ID.fetch_add(1, Ordering::SeqCst);
format!("tokio-runtime-worker-{id}")
.max_blocking_threads(concurrency);

#[cfg(feature = "utoopack")]
builder
.on_thread_stop(|| {
turbo_tasks_malloc::TurboMalloc::thread_stop();
})
.max_blocking_threads(1)
.on_thread_park(|| {
LAST_SWC_ATOM_GC_TIME.with_borrow_mut(|cell| {
if cell.is_none_or(|t| t.elapsed() > Duration::from_secs(2)) {
swc_core::ecma::atoms::hstr::global_atom_store_gc();
*cell = Some(Instant::now());
}
});
});

builder
.wasm_bindgen_shim_url(worker_url.clone())
.build()
.expect("Failed to build tokio runtime")
Expand Down
2 changes: 1 addition & 1 deletion next.js
54 changes: 39 additions & 15 deletions packages/utoo-web/src/utoo/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,22 @@ export class DirEntry {
type: DirEntryType;
}

export function ERR_ABORT(): string;

export function ERR_INVALID_STATE(): string;

export function ERR_KEY_ALREADY_EXISTS(): string;

export function ERR_NOT_ALLOWED(): string;

export function ERR_NOT_FOUND(): string;

export function ERR_NO_MODIFICATION_ALLOWED(): string;

export function ERR_QUOTA_EXCEEDED(): string;

export function ERR_TYPE_MISMATCH(): string;

export class Fs {
private constructor();
free(): void;
Expand Down Expand Up @@ -183,8 +199,29 @@ export interface InitOutput {
readonly workerCreated: (a: number) => void;
readonly getWasmMemory: () => any;
readonly getWasmModule: () => any;
readonly ERR_ABORT: () => [number, number];
readonly ERR_INVALID_STATE: () => [number, number];
readonly ERR_KEY_ALREADY_EXISTS: () => [number, number];
readonly ERR_NOT_ALLOWED: () => [number, number];
readonly ERR_NOT_FOUND: () => [number, number];
readonly ERR_NO_MODIFICATION_ALLOWED: () => [number, number];
readonly ERR_QUOTA_EXCEEDED: () => [number, number];
readonly ERR_TYPE_MISMATCH: () => [number, number];
readonly initLogFilter: (a: number, b: number) => void;
readonly init_pack: () => void;
readonly __wbg_project_free: (a: number, b: number) => void;
readonly project_build: () => any;
readonly project_cwd: () => [number, number];
readonly project_deps: (a: number, b: number, c: number) => any;
readonly project_entrypointsSubscribe: (a: any) => any;
readonly project_gzip: (a: any) => any;
readonly project_hmrEvents: (a: number, b: number, c: any) => any;
readonly project_init: (a: number, b: number) => void;
readonly project_install: (a: number, b: number, c: number) => any;
readonly project_setCwd: (a: number, b: number) => void;
readonly project_sigMd5: (a: any) => any;
readonly project_updateInfoSubscribe: (a: number, b: any) => void;
readonly project_writeAllToDisk: (a: any) => void;
readonly __wbg_direntry_free: (a: number, b: number) => void;
readonly __wbg_fs_free: (a: number, b: number) => void;
readonly __wbg_get_direntry_name: (a: number) => [number, number];
Expand Down Expand Up @@ -216,19 +253,6 @@ export interface InitOutput {
readonly fs_write: (a: number, b: number, c: any) => any;
readonly fs_writeString: (a: number, b: number, c: number, d: number) => any;
readonly fs_writeSync: (a: number, b: number, c: any) => [number, number];
readonly __wbg_project_free: (a: number, b: number) => void;
readonly project_build: () => any;
readonly project_cwd: () => [number, number];
readonly project_deps: (a: number, b: number, c: number) => any;
readonly project_entrypointsSubscribe: (a: any) => any;
readonly project_gzip: (a: any) => any;
readonly project_hmrEvents: (a: number, b: number, c: any) => any;
readonly project_init: (a: number, b: number) => void;
readonly project_install: (a: number, b: number, c: number) => any;
readonly project_setCwd: (a: number, b: number) => void;
readonly project_sigMd5: (a: any) => any;
readonly project_updateInfoSubscribe: (a: number, b: any) => void;
readonly project_writeAllToDisk: (a: any) => void;
readonly rust_mi_get_default_heap: () => number;
readonly rust_mi_get_thread_id: () => number;
readonly rust_mi_set_default_heap: (a: number) => void;
Expand All @@ -254,16 +278,16 @@ export interface InitOutput {
readonly __wbg_createsyncaccesshandleoptions_free: (a: number, b: number) => void;
readonly wasm_thread_entry_point: (a: number) => void;
readonly wasm_bindgen_4243f1f505d3e2fc___closure__destroy___dyn_core_97b1fb32719f2dc8___ops__function__FnMut_____Output_______: (a: number, b: number) => void;
readonly wasm_bindgen_4243f1f505d3e2fc___closure__destroy___dyn_core_97b1fb32719f2dc8___ops__function__Fn__js_sys_8afca1662fec7f75___Array____Output_______: (a: number, b: number) => void;
readonly wasm_bindgen_4243f1f505d3e2fc___closure__destroy___dyn_core_97b1fb32719f2dc8___ops__function__FnMut__wasm_bindgen_4243f1f505d3e2fc___JsValue____Output_______: (a: number, b: number) => void;
readonly wasm_bindgen_4243f1f505d3e2fc___closure__destroy___dyn_core_97b1fb32719f2dc8___ops__function__FnMut__web_sys_95f4c484d1daab41___features__gen_MessageEvent__MessageEvent____Output_______: (a: number, b: number) => void;
readonly wasm_bindgen_4243f1f505d3e2fc___closure__destroy___dyn_core_97b1fb32719f2dc8___ops__function__FnMut_____Output________1_: (a: number, b: number) => void;
readonly wasm_bindgen_4243f1f505d3e2fc___closure__destroy___dyn_for__a__core_97b1fb32719f2dc8___ops__function__FnMut____a_web_sys_95f4c484d1daab41___features__gen_MessageEvent__MessageEvent____Output_______: (a: number, b: number) => void;
readonly wasm_bindgen_4243f1f505d3e2fc___closure__destroy___dyn_core_97b1fb32719f2dc8___ops__function__Fn__js_sys_8afca1662fec7f75___Array____Output_______: (a: number, b: number) => void;
readonly wasm_bindgen_4243f1f505d3e2fc___convert__closures_____invoke___js_sys_8afca1662fec7f75___Function__js_sys_8afca1662fec7f75___Function_____: (a: number, b: number, c: any, d: any) => void;
readonly wasm_bindgen_4243f1f505d3e2fc___convert__closures_____invoke___js_sys_8afca1662fec7f75___Array_____: (a: number, b: number, c: any) => void;
readonly wasm_bindgen_4243f1f505d3e2fc___convert__closures_____invoke___wasm_bindgen_4243f1f505d3e2fc___JsValue_____: (a: number, b: number, c: any) => void;
readonly wasm_bindgen_4243f1f505d3e2fc___convert__closures_____invoke___web_sys_95f4c484d1daab41___features__gen_MessageEvent__MessageEvent_____: (a: number, b: number, c: any) => void;
readonly wasm_bindgen_4243f1f505d3e2fc___convert__closures________invoke___web_sys_95f4c484d1daab41___features__gen_MessageEvent__MessageEvent_____: (a: number, b: number, c: any) => void;
readonly wasm_bindgen_4243f1f505d3e2fc___convert__closures_____invoke___js_sys_8afca1662fec7f75___Array_____: (a: number, b: number, c: any) => void;
readonly wasm_bindgen_4243f1f505d3e2fc___convert__closures_____invoke______: (a: number, b: number) => void;
readonly wasm_bindgen_4243f1f505d3e2fc___convert__closures_____invoke_______1_: (a: number, b: number) => void;
readonly memory: WebAssembly.Memory;
Expand Down
Loading
Loading