Skip to content

Commit 14b9bd3

Browse files
authored
chore/bump deps and improve fs (#2580)
* feat(utoo-web): improve fs error translation, support cjs extension, and standardize resolution * chore: bump tokio-fs-ext to 0.7.4 and update next.js submodule * fix(wasm): export error constants from rust to ensure consistency with js polyfill * chore(wasm): add duration logging for build tasks * chore(wasm): remove AlreadyExists error mapping and dedupe cjs extensions * feat(utoo-wasm): optimize tokio runtime usage * chore(utoo-web): simplify cjs loader logic * chore: update tokio-fs-ext to 0.7.7
1 parent 82fc7f7 commit 14b9bd3

File tree

10 files changed

+341
-184
lines changed

10 files changed

+341
-184
lines changed

Cargo.lock

Lines changed: 3 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ serde_path_to_error = "0.1.16"
4444
simd-json = "0.17.0"
4545
thiserror = "1.0"
4646
tokio = { version = "1.47.1" }
47-
tokio-fs-ext = "0.7.3"
47+
tokio-fs-ext = "0.7.7"
4848
toml = "0.8"
4949
tracing = "0.1.41"
5050
tracing-subscriber = { version = "0.3.19", features = ["env-filter", "fmt"] }

crates/utoo-wasm/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ wasm-bindgen-futures = "0.4.58"
5050
pack-api = { workspace = true, optional = true }
5151
pack-core = { workspace = true, optional = true }
5252
parking_lot = { workspace = true, features = ["nightly"] }
53+
swc_core = { workspace = true, features = ["base", "ecma_ast"] }
5354
turbo-rcstr = { workspace = true, optional = true }
5455
turbo-tasks = { workspace = true, optional = true }
5556
turbo-tasks-backend = { workspace = true, optional = true }

crates/utoo-wasm/src/errors.rs

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,55 @@
1+
use std::io;
12
use wasm_bindgen::prelude::*;
23

4+
// Helper macro to define constants and their JS getters (exported as functions)
5+
macro_rules! define_error_consts {
6+
($($name:ident, $fn_name:ident = $val:expr),* $(,)?) => {
7+
$(
8+
// Internal Rust constant
9+
pub const $name: &str = $val;
10+
11+
// Exported JS function returning the string
12+
#[wasm_bindgen(js_name = $name)]
13+
pub fn $fn_name() -> String {
14+
$name.to_string()
15+
}
16+
)*
17+
};
18+
}
19+
20+
define_error_consts! {
21+
ERR_NOT_FOUND, err_not_found = "NotFoundError",
22+
ERR_KEY_ALREADY_EXISTS, err_key_already_exists = "NoModificationAllowedError",
23+
ERR_NOT_ALLOWED, err_not_allowed = "NotAllowedError",
24+
ERR_NO_MODIFICATION_ALLOWED, err_no_modification_allowed = "NoModificationAllowedError",
25+
ERR_TYPE_MISMATCH, err_type_mismatch = "TypeMismatchError",
26+
ERR_QUOTA_EXCEEDED, err_quota_exceeded = "QuotaExceededError",
27+
ERR_INVALID_STATE, err_invalid_state = "InvalidStateError",
28+
ERR_ABORT, err_abort = "AbortError",
29+
}
30+
331
pub fn to_js_error<E>(e: E) -> JsError
432
where
533
E: Into<anyhow::Error>,
634
{
7-
JsError::new(&format!("{:#?}", e.into()))
35+
let err = e.into();
36+
37+
if let Some(io_err) = err.downcast_ref::<io::Error>() {
38+
let prefix = match io_err.kind() {
39+
io::ErrorKind::NotFound => ERR_NOT_FOUND,
40+
io::ErrorKind::PermissionDenied => ERR_NOT_ALLOWED,
41+
io::ErrorKind::WouldBlock => ERR_NO_MODIFICATION_ALLOWED,
42+
io::ErrorKind::InvalidData => ERR_TYPE_MISMATCH,
43+
io::ErrorKind::StorageFull => ERR_QUOTA_EXCEEDED,
44+
io::ErrorKind::InvalidInput => ERR_INVALID_STATE,
45+
io::ErrorKind::Interrupted => ERR_ABORT,
46+
_ => "",
47+
};
48+
49+
if !prefix.is_empty() {
50+
return JsError::new(&format!("{}: {}", prefix, io_err));
51+
}
52+
}
53+
54+
JsError::new(&format!("{:#?}", err))
855
}

crates/utoo-wasm/src/pack.rs

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -350,22 +350,7 @@ pub async fn build() -> std::result::Result<JsValue, wasm_bindgen::JsError> {
350350
})
351351
.await?;
352352

353-
tracing::info!("all project entrypoints wrote to disk.");
354-
355-
tracing::info!(
356-
"pack tasks with {} apps {} libraries finished in {:?}",
357-
entrypoints
358-
.apps
359-
.as_ref()
360-
.map(|apps| apps.0.len())
361-
.unwrap_or_default(),
362-
entrypoints
363-
.libraries
364-
.as_ref()
365-
.map(|libraries| libraries.0.len())
366-
.unwrap_or_default(),
367-
start.elapsed()
368-
);
353+
tracing::info!("build finished in {:?}", start.elapsed());
369354

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

422408
let entrypoints_with_issues_op =
423409
get_all_written_entrypoints_with_issues_operation(container);
@@ -431,6 +417,8 @@ pub async fn project_entrypoints_subscribe(
431417
.await?;
432418
effects.apply().await?;
433419

420+
tracing::info!("dev build finished in {:?}", start.elapsed());
421+
434422
let turbopack_result = TurbopackResult {
435423
issues: issues.iter().map(|i| Issue::from(&**i)).collect(),
436424
diagnostics: diagnostics.iter().map(|d| Diagnostic::from(d)).collect(),

crates/utoo-wasm/src/tokio_runtime.rs

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,21 @@
11
use std::{
2-
cell::OnceCell,
2+
cell::{OnceCell, RefCell},
33
sync::{
44
atomic::{AtomicUsize, Ordering},
55
OnceLock,
66
},
77
time::Duration,
88
};
99

10-
use tokio::runtime::{self, Runtime};
10+
use tokio::{
11+
runtime::{self, Runtime},
12+
time::Instant,
13+
};
14+
15+
#[cfg(feature = "utoopack")]
16+
thread_local! {
17+
static LAST_SWC_ATOM_GC_TIME: RefCell<Option<Instant>> = const { RefCell::new(None) };
18+
}
1119

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

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

2129
pub fn init_tokio_runtime(worker_url: String) {
2230
TOKIO_RUNTIME.get_or_init(|| {
23-
runtime::Builder::new_multi_thread()
31+
let concurrency = (|| {
32+
let global = js_sys::global();
33+
let navigator =
34+
js_sys::Reflect::get(&global, &wasm_bindgen::JsValue::from_str("navigator"))
35+
.ok()?;
36+
let concurrency = js_sys::Reflect::get(
37+
&navigator,
38+
&wasm_bindgen::JsValue::from_str("hardwareConcurrency"),
39+
)
40+
.ok()?;
41+
concurrency.as_f64().map(|v| (v as usize).max(1))
42+
})()
43+
.unwrap_or(1);
44+
45+
let mut builder = runtime::Builder::new_multi_thread();
46+
builder
2447
.disable_lifo_slot()
25-
.thread_name_fn(|| {
26-
static ATOMIC_ID: AtomicUsize = AtomicUsize::new(1);
27-
let id = ATOMIC_ID.fetch_add(1, Ordering::SeqCst);
28-
format!("tokio-runtime-worker-{id}")
48+
.max_blocking_threads(concurrency);
49+
50+
#[cfg(feature = "utoopack")]
51+
builder
52+
.on_thread_stop(|| {
53+
turbo_tasks_malloc::TurboMalloc::thread_stop();
2954
})
30-
.max_blocking_threads(1)
55+
.on_thread_park(|| {
56+
LAST_SWC_ATOM_GC_TIME.with_borrow_mut(|cell| {
57+
if cell.is_none_or(|t| t.elapsed() > Duration::from_secs(2)) {
58+
swc_core::ecma::atoms::hstr::global_atom_store_gc();
59+
*cell = Some(Instant::now());
60+
}
61+
});
62+
});
63+
64+
builder
3165
.wasm_bindgen_shim_url(worker_url.clone())
3266
.build()
3367
.expect("Failed to build tokio runtime")

next.js

packages/utoo-web/src/utoo/index.d.ts

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,22 @@ export class DirEntry {
2525
type: DirEntryType;
2626
}
2727

28+
export function ERR_ABORT(): string;
29+
30+
export function ERR_INVALID_STATE(): string;
31+
32+
export function ERR_KEY_ALREADY_EXISTS(): string;
33+
34+
export function ERR_NOT_ALLOWED(): string;
35+
36+
export function ERR_NOT_FOUND(): string;
37+
38+
export function ERR_NO_MODIFICATION_ALLOWED(): string;
39+
40+
export function ERR_QUOTA_EXCEEDED(): string;
41+
42+
export function ERR_TYPE_MISMATCH(): string;
43+
2844
export class Fs {
2945
private constructor();
3046
free(): void;
@@ -183,8 +199,29 @@ export interface InitOutput {
183199
readonly workerCreated: (a: number) => void;
184200
readonly getWasmMemory: () => any;
185201
readonly getWasmModule: () => any;
202+
readonly ERR_ABORT: () => [number, number];
203+
readonly ERR_INVALID_STATE: () => [number, number];
204+
readonly ERR_KEY_ALREADY_EXISTS: () => [number, number];
205+
readonly ERR_NOT_ALLOWED: () => [number, number];
206+
readonly ERR_NOT_FOUND: () => [number, number];
207+
readonly ERR_NO_MODIFICATION_ALLOWED: () => [number, number];
208+
readonly ERR_QUOTA_EXCEEDED: () => [number, number];
209+
readonly ERR_TYPE_MISMATCH: () => [number, number];
186210
readonly initLogFilter: (a: number, b: number) => void;
187211
readonly init_pack: () => void;
212+
readonly __wbg_project_free: (a: number, b: number) => void;
213+
readonly project_build: () => any;
214+
readonly project_cwd: () => [number, number];
215+
readonly project_deps: (a: number, b: number, c: number) => any;
216+
readonly project_entrypointsSubscribe: (a: any) => any;
217+
readonly project_gzip: (a: any) => any;
218+
readonly project_hmrEvents: (a: number, b: number, c: any) => any;
219+
readonly project_init: (a: number, b: number) => void;
220+
readonly project_install: (a: number, b: number, c: number) => any;
221+
readonly project_setCwd: (a: number, b: number) => void;
222+
readonly project_sigMd5: (a: any) => any;
223+
readonly project_updateInfoSubscribe: (a: number, b: any) => void;
224+
readonly project_writeAllToDisk: (a: any) => void;
188225
readonly __wbg_direntry_free: (a: number, b: number) => void;
189226
readonly __wbg_fs_free: (a: number, b: number) => void;
190227
readonly __wbg_get_direntry_name: (a: number) => [number, number];
@@ -216,19 +253,6 @@ export interface InitOutput {
216253
readonly fs_write: (a: number, b: number, c: any) => any;
217254
readonly fs_writeString: (a: number, b: number, c: number, d: number) => any;
218255
readonly fs_writeSync: (a: number, b: number, c: any) => [number, number];
219-
readonly __wbg_project_free: (a: number, b: number) => void;
220-
readonly project_build: () => any;
221-
readonly project_cwd: () => [number, number];
222-
readonly project_deps: (a: number, b: number, c: number) => any;
223-
readonly project_entrypointsSubscribe: (a: any) => any;
224-
readonly project_gzip: (a: any) => any;
225-
readonly project_hmrEvents: (a: number, b: number, c: any) => any;
226-
readonly project_init: (a: number, b: number) => void;
227-
readonly project_install: (a: number, b: number, c: number) => any;
228-
readonly project_setCwd: (a: number, b: number) => void;
229-
readonly project_sigMd5: (a: any) => any;
230-
readonly project_updateInfoSubscribe: (a: number, b: any) => void;
231-
readonly project_writeAllToDisk: (a: any) => void;
232256
readonly rust_mi_get_default_heap: () => number;
233257
readonly rust_mi_get_thread_id: () => number;
234258
readonly rust_mi_set_default_heap: (a: number) => void;
@@ -254,16 +278,16 @@ export interface InitOutput {
254278
readonly __wbg_createsyncaccesshandleoptions_free: (a: number, b: number) => void;
255279
readonly wasm_thread_entry_point: (a: number) => void;
256280
readonly wasm_bindgen_4243f1f505d3e2fc___closure__destroy___dyn_core_97b1fb32719f2dc8___ops__function__FnMut_____Output_______: (a: number, b: number) => void;
281+
readonly wasm_bindgen_4243f1f505d3e2fc___closure__destroy___dyn_core_97b1fb32719f2dc8___ops__function__Fn__js_sys_8afca1662fec7f75___Array____Output_______: (a: number, b: number) => void;
257282
readonly wasm_bindgen_4243f1f505d3e2fc___closure__destroy___dyn_core_97b1fb32719f2dc8___ops__function__FnMut__wasm_bindgen_4243f1f505d3e2fc___JsValue____Output_______: (a: number, b: number) => void;
258283
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;
259284
readonly wasm_bindgen_4243f1f505d3e2fc___closure__destroy___dyn_core_97b1fb32719f2dc8___ops__function__FnMut_____Output________1_: (a: number, b: number) => void;
260285
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;
261-
readonly wasm_bindgen_4243f1f505d3e2fc___closure__destroy___dyn_core_97b1fb32719f2dc8___ops__function__Fn__js_sys_8afca1662fec7f75___Array____Output_______: (a: number, b: number) => void;
262286
readonly wasm_bindgen_4243f1f505d3e2fc___convert__closures_____invoke___js_sys_8afca1662fec7f75___Function__js_sys_8afca1662fec7f75___Function_____: (a: number, b: number, c: any, d: any) => void;
287+
readonly wasm_bindgen_4243f1f505d3e2fc___convert__closures_____invoke___js_sys_8afca1662fec7f75___Array_____: (a: number, b: number, c: any) => void;
263288
readonly wasm_bindgen_4243f1f505d3e2fc___convert__closures_____invoke___wasm_bindgen_4243f1f505d3e2fc___JsValue_____: (a: number, b: number, c: any) => void;
264289
readonly wasm_bindgen_4243f1f505d3e2fc___convert__closures_____invoke___web_sys_95f4c484d1daab41___features__gen_MessageEvent__MessageEvent_____: (a: number, b: number, c: any) => void;
265290
readonly wasm_bindgen_4243f1f505d3e2fc___convert__closures________invoke___web_sys_95f4c484d1daab41___features__gen_MessageEvent__MessageEvent_____: (a: number, b: number, c: any) => void;
266-
readonly wasm_bindgen_4243f1f505d3e2fc___convert__closures_____invoke___js_sys_8afca1662fec7f75___Array_____: (a: number, b: number, c: any) => void;
267291
readonly wasm_bindgen_4243f1f505d3e2fc___convert__closures_____invoke______: (a: number, b: number) => void;
268292
readonly wasm_bindgen_4243f1f505d3e2fc___convert__closures_____invoke_______1_: (a: number, b: number) => void;
269293
readonly memory: WebAssembly.Memory;

0 commit comments

Comments
 (0)