From 7eb3acf26fdb05927c3f0b2761823d962ff3bd4c Mon Sep 17 00:00:00 2001 From: imxyy_soope_ Date: Thu, 19 Feb 2026 18:22:40 +0800 Subject: [PATCH] optimize: use v8::Script::compile to run script directly in op_import --- nix-js/runtime-ts/src/types/global.d.ts | 2 +- nix-js/src/runtime.rs | 18 +------ nix-js/src/runtime/ops.rs | 64 ++++++++++++++++++++++--- 3 files changed, 60 insertions(+), 24 deletions(-) diff --git a/nix-js/runtime-ts/src/types/global.d.ts b/nix-js/runtime-ts/src/types/global.d.ts index 3933e82..efec691 100644 --- a/nix-js/runtime-ts/src/types/global.d.ts +++ b/nix-js/runtime-ts/src/types/global.d.ts @@ -48,7 +48,7 @@ declare global { namespace Deno { namespace core { namespace ops { - function op_import(path: string): string; + function op_import(path: string): NixValue; function op_scoped_import(path: string, scopeKeys: string[]): string; function op_resolve_path(currentDir: string, path: string): string; diff --git a/nix-js/src/runtime.rs b/nix-js/src/runtime.rs index 419375e..1916695 100644 --- a/nix-js/src/runtime.rs +++ b/nix-js/src/runtime.rs @@ -116,6 +116,7 @@ pub(crate) use private::NixRuntimeError; pub(crate) struct Runtime { js_runtime: JsRuntime, + #[cfg(feature = "inspector")] rt: tokio::runtime::Runtime, #[cfg(feature = "inspector")] wait_for_inspector: bool, @@ -178,6 +179,7 @@ impl Runtime { Ok(Self { js_runtime, + #[cfg(feature = "inspector")] rt: tokio::runtime::Builder::new_current_thread() .enable_all() .build() @@ -230,22 +232,6 @@ impl Runtime { crate::error::parse_js_error(error, ctx) })?; - let global_value = self - .rt - .block_on(self.js_runtime.resolve(global_value)) - .map_err(|error| { - let op_state = self.js_runtime.op_state(); - let op_state_borrow = op_state.borrow(); - let ctx: &Ctx = op_state_borrow.get_ctx(); - - crate::error::parse_js_error(error, ctx) - })?; - #[cfg(feature = "inspector")] - { - let _ = self - .rt - .block_on(self.js_runtime.run_event_loop(Default::default())); - } // Retrieve scope from JsRuntime deno_core::scope!(scope, self.js_runtime); diff --git a/nix-js/src/runtime/ops.rs b/nix-js/src/runtime/ops.rs index 9303550..59849b3 100644 --- a/nix-js/src/runtime/ops.rs +++ b/nix-js/src/runtime/ops.rs @@ -3,9 +3,9 @@ use std::convert::Infallible; use std::path::{Component, Path, PathBuf}; use std::str::FromStr; -use hashbrown::{HashMap, HashSet, hash_map::Entry}; - +use deno_core::error::JsError; use deno_core::{FromV8, OpState, ToV8, v8}; +use hashbrown::{HashMap, HashSet, hash_map::Entry}; use regex::Regex; use rust_embed::Embed; @@ -62,12 +62,60 @@ where #[folder = "src/runtime/corepkgs"] pub(crate) struct CorePkgs; -#[deno_core::op2] -#[string] +fn new_simple_jserror(msg: String) -> Box { + JsError { + message: Some(msg.clone()), + + name: None, + stack: None, + cause: None, + exception_message: msg, + frames: Vec::new(), + source_line: None, + source_line_frame_index: None, + aggregated: None, + additional_properties: Vec::new(), + } + .into() +} + +struct Compiled(String); +impl<'a> ToV8<'a> for Compiled { + type Error = Box; + fn to_v8<'i>( + self, + scope: &mut v8::PinScope<'a, 'i>, + ) -> std::result::Result, Self::Error> { + let Ok(script) = self.0.to_v8(scope); + let Some(source) = script.to_string(scope) else { + unsafe { std::hint::unreachable_unchecked() } + }; + let tc = std::pin::pin!(v8::TryCatch::new(scope)); + let mut scope = tc.init(); + let Some(compiled) = v8::Script::compile(&scope, source, None) else { + let msg = scope + .exception() + .map(|e| e.to_rust_string_lossy(&scope)) + .unwrap_or_else(|| "failed to compile code".into()); + return Err(new_simple_jserror(msg)); + }; + match compiled.run(&scope) { + Some(val) => Ok(val), + None => Err(scope + .exception() + .map(|e| JsError::from_v8_exception(&mut scope, e)) + .unwrap_or_else(|| { + new_simple_jserror("script execution failed unexpectedly".into()) + })), + } + } +} + +#[deno_core::op2(reentrant)] pub(super) fn op_import( state: &mut OpState, #[string] path: String, -) -> Result { +) -> Result { let _span = tracing::info_span!("op_import", path = %path).entered(); let ctx: &mut Ctx = state.get_ctx_mut(); @@ -83,7 +131,8 @@ pub(super) fn op_import( .into(), ); ctx.add_source(source.clone()); - return Ok(ctx.compile(source).map_err(|err| err.to_string())?); + let code = ctx.compile(source).map_err(|err| err.to_string())?; + return Ok(Compiled(code)); } else { return Err(format!("Corepkg not found: {}", corepkg_name).into()); } @@ -107,7 +156,8 @@ pub(super) fn op_import( tracing::debug!("Compiling file"); ctx.add_source(source.clone()); - Ok(ctx.compile(source).map_err(|err| err.to_string())?) + let code = ctx.compile(source).map_err(|err| err.to_string())?; + Ok(Compiled(code)) } #[deno_core::op2]