feat: builtins.getEnv

This commit is contained in:
2026-01-22 16:46:11 +08:00
parent 15c4159dcc
commit 041d7b7dd2
6 changed files with 29 additions and 21 deletions

View File

@@ -261,5 +261,5 @@ export const builtins: any = {
langVersion: 6, langVersion: 6,
nixPath: [], nixPath: [],
nixVersion: "2.31.2", nixVersion: "2.31.2",
storeDir: "/home/imxyy/.cache/nix-js/fetchers/store", storeDir: "INVALID_PATH",
}; };

View File

@@ -391,6 +391,6 @@ export const findFile =
throw new Error("Not implemented: findFile"); throw new Error("Not implemented: findFile");
}; };
export const getEnv = (s: NixValue): never => { export const getEnv = (s: NixValue): string => {
throw new Error("Not implemented: getEnv"); return Deno.core.ops.op_get_env(forceString(s))
}; };

View File

@@ -79,6 +79,7 @@ declare global {
function op_store_path(path: string): string; function op_store_path(path: string): string;
function op_to_file(name: string, contents: string, references: string[]): string; function op_to_file(name: string, contents: string, references: string[]): string;
function op_copy_path_to_store(path: string): string; function op_copy_path_to_store(path: string): string;
function op_get_env(key: string): string;
} }
} }
} }

View File

@@ -22,8 +22,8 @@ pub(crate) fn compile(expr: &Ir, ctx: &impl CodegenContext) -> String {
let cur_dir = ctx.get_current_dir().display().to_string().escape_quote(); let cur_dir = ctx.get_current_dir().display().to_string().escape_quote();
format!( format!(
"(()=>{{{}const currentDir={};return {}}})()", "(()=>{{{}Nix.builtins.storeDir={};const currentDir={};return {}}})()",
debug_prefix, cur_dir, code debug_prefix, ctx.get_store_dir().escape_quote(), cur_dir, code
) )
} }
@@ -35,6 +35,7 @@ pub(crate) trait CodegenContext {
fn get_ir(&self, id: ExprId) -> &Ir; fn get_ir(&self, id: ExprId) -> &Ir;
fn get_sym(&self, id: SymId) -> &str; fn get_sym(&self, id: SymId) -> &str;
fn get_current_dir(&self) -> &Path; fn get_current_dir(&self) -> &Path;
fn get_store_dir(&self) -> &str;
fn get_current_source_id(&self) -> usize; fn get_current_source_id(&self) -> usize;
} }

View File

@@ -66,21 +66,16 @@ pub(crate) struct SccInfo {
pub struct Context { pub struct Context {
ctx: Ctx, ctx: Ctx,
runtime: Runtime<CtxPtr>, runtime: Runtime<CtxPtr>,
store: Arc<StoreBackend>,
} }
impl Context { impl Context {
pub fn new() -> Result<Self> { pub fn new() -> Result<Self> {
let ctx = Ctx::new(); let ctx = Ctx::new()?;
let runtime = Runtime::new()?; let runtime = Runtime::new()?;
let config = StoreConfig::from_env();
let store = Arc::new(StoreBackend::new(config)?);
Ok(Self { Ok(Self {
ctx, ctx,
runtime, runtime,
store,
}) })
} }
@@ -90,7 +85,7 @@ impl Context {
tracing::debug!("Compiling code"); tracing::debug!("Compiling code");
let code = self.compile_code(source)?; let code = self.compile_code(source)?;
self.runtime.op_state().borrow_mut().put(self.store.clone()); self.runtime.op_state().borrow_mut().put(self.ctx.store.clone());
tracing::debug!("Executing JavaScript"); tracing::debug!("Executing JavaScript");
self.runtime self.runtime
@@ -107,7 +102,7 @@ impl Context {
} }
pub fn get_store_dir(&self) -> &str { pub fn get_store_dir(&self) -> &str {
self.store.as_store().get_store_dir() self.ctx.get_store_dir()
} }
} }
@@ -116,10 +111,11 @@ pub(crate) struct Ctx {
symbols: DefaultStringInterner, symbols: DefaultStringInterner,
global: NonNull<HashMap<SymId, ExprId>>, global: NonNull<HashMap<SymId, ExprId>>,
sources: Vec<Source>, sources: Vec<Source>,
store: Arc<StoreBackend>,
} }
impl Default for Ctx { impl Ctx {
fn default() -> Self { fn new() -> Result<Self> {
use crate::ir::{Builtins, ToIr as _}; use crate::ir::{Builtins, ToIr as _};
let mut symbols = DefaultStringInterner::new(); let mut symbols = DefaultStringInterner::new();
@@ -203,20 +199,20 @@ impl Default for Ctx {
global.insert(name_sym, id); global.insert(name_sym, id);
} }
Self { let config = StoreConfig::from_env();
let store = Arc::new(StoreBackend::new(config)?);
Ok(Self {
symbols, symbols,
irs, irs,
global: unsafe { NonNull::new_unchecked(Box::leak(Box::new(global))) }, global: unsafe { NonNull::new_unchecked(Box::leak(Box::new(global))) },
sources: Vec::new(), sources: Vec::new(),
} store,
})
} }
} }
impl Ctx { impl Ctx {
pub(crate) fn new() -> Self {
Self::default()
}
pub(crate) fn downgrade_ctx<'a>(&'a mut self) -> DowngradeCtx<'a> { pub(crate) fn downgrade_ctx<'a>(&'a mut self) -> DowngradeCtx<'a> {
let global_ref = unsafe { self.global.as_ref() }; let global_ref = unsafe { self.global.as_ref() };
DowngradeCtx::new(self, global_ref) DowngradeCtx::new(self, global_ref)
@@ -281,6 +277,9 @@ impl CodegenContext for Ctx {
.checked_sub(1) .checked_sub(1)
.expect("current_source not set") .expect("current_source not set")
} }
fn get_store_dir(&self) -> &str {
self.store.as_store().get_store_dir()
}
} }
struct DependencyTracker { struct DependencyTracker {

View File

@@ -38,6 +38,7 @@ fn runtime_extension<Ctx: RuntimeContext>() -> Extension {
op_store_path(), op_store_path(),
op_to_file(), op_to_file(),
op_copy_path_to_store(), op_copy_path_to_store(),
op_get_env(),
]; ];
ops.extend(crate::fetcher::register_ops()); ops.extend(crate::fetcher::register_ops());
@@ -390,6 +391,12 @@ fn op_copy_path_to_store(
Ok(store_path) Ok(store_path)
} }
#[deno_core::op2]
#[string]
fn op_get_env(#[string] key: String) -> std::result::Result<String, NixError> {
Ok(std::env::var(key).map_err(|err| format!("Failed to read env var: {err}"))?)
}
pub(crate) struct Runtime<Ctx: RuntimeContext> { pub(crate) struct Runtime<Ctx: RuntimeContext> {
js_runtime: JsRuntime, js_runtime: JsRuntime,
is_thunk_symbol: v8::Global<v8::Symbol>, is_thunk_symbol: v8::Global<v8::Symbol>,