chore: directly map nix boolean/null to javascript boolean/null

This commit is contained in:
2026-01-14 17:50:55 +08:00
parent b4e0b53cde
commit 55825788b8
6 changed files with 21 additions and 30 deletions

View File

@@ -62,28 +62,6 @@ export const mergeContexts = (...contexts: NixStringContext[]): NixStringContext
return result; return result;
}; };
export const concatStringsWithContext = (
strings: (string | StringWithContext)[],
): string | StringWithContext => {
const parts: string[] = [];
const contexts: NixStringContext[] = [];
for (const s of strings) {
parts.push(getStringValue(s));
const ctx = getStringContext(s);
if (ctx.size > 0) {
contexts.push(ctx);
}
}
const value = parts.join("");
if (contexts.length === 0) {
return value;
}
return mkStringWithContext(value, mergeContexts(...contexts));
};
export const encodeContextElem = (elem: StringContextElem): string => { export const encodeContextElem = (elem: StringContextElem): string => {
switch (elem.type) { switch (elem.type) {
case "opaque": case "opaque":

View File

@@ -39,6 +39,8 @@ impl<Ctx: CodegenContext> Compile<Ctx> for Ir {
match self { match self {
Ir::Int(int) => format!("{int}n"), // Generate BigInt literal Ir::Int(int) => format!("{int}n"), // Generate BigInt literal
Ir::Float(float) => float.to_string(), Ir::Float(float) => float.to_string(),
Ir::Bool(bool) => bool.to_string(),
Ir::Null(_) => "null".to_string(),
Ir::Str(s) => s.val.escape_quote(), Ir::Str(s) => s.val.escape_quote(),
Ir::Path(p) => { Ir::Path(p) => {
// Path needs runtime resolution for interpolated paths // Path needs runtime resolution for interpolated paths
@@ -104,8 +106,8 @@ impl<Ctx: CodegenContext> Compile<Ctx> for BinOp {
Impl => format!("(!Nix.force({}) || Nix.force({}))", lhs, rhs), Impl => format!("(!Nix.force({}) || Nix.force({}))", lhs, rhs),
Con => format!("Nix.op.concat({},{})", lhs, rhs), Con => format!("Nix.op.concat({},{})", lhs, rhs),
Upd => format!("Nix.op.update({},{})", lhs, rhs), Upd => format!("Nix.op.update({},{})", lhs, rhs),
PipeL => format!("Nix.force({})({})", rhs, lhs), PipeL => format!("Nix.call({}, {})", rhs, lhs),
PipeR => format!("Nix.force({})({})", lhs, rhs), PipeR => format!("Nix.call({}, {})", lhs, rhs),
} }
} }
} }

View File

@@ -81,7 +81,7 @@ impl Context {
let ctx = guard.as_ctx(); let ctx = guard.as_ctx();
let code = ctx.compile_code(expr)?; let code = ctx.compile_code(expr)?;
self.runtime.eval(code, CtxPtr::new(&mut self.ctx)) self.runtime.eval(format!("Nix.force({code})"), CtxPtr::new(&mut self.ctx))
} }
pub fn compile_code(&mut self, expr: &str) -> Result<String> { pub fn compile_code(&mut self, expr: &str) -> Result<String> {
@@ -116,9 +116,6 @@ impl Default for Ctx {
global.insert(builtins_sym, builtins_expr); global.insert(builtins_sym, builtins_expr);
let free_globals = [ let free_globals = [
"true",
"false",
"null",
"abort", "abort",
"baseNameOf", "baseNameOf",
"break", "break",
@@ -139,6 +136,11 @@ impl Default for Ctx {
"throw", "throw",
"toString", "toString",
]; ];
let consts = [
("true", Ir::Bool(true)),
("false", Ir::Bool(false)),
("null", Ir::Null(())),
];
for name in free_globals { for name in free_globals {
let name_sym = symbols.get_or_intern(name); let name_sym = symbols.get_or_intern(name);
@@ -146,6 +148,12 @@ impl Default for Ctx {
irs.push(Builtin(name_sym).to_ir()); irs.push(Builtin(name_sym).to_ir());
global.insert(name_sym, id); global.insert(name_sym, id);
} }
for (name, value) in consts {
let name_sym = symbols.get_or_intern(name);
let id = ExprId(irs.len());
irs.push(value);
global.insert(name_sym, id);
}
Self { Self {
symbols, symbols,
@@ -195,7 +203,7 @@ impl Ctx {
} else { } else {
"" ""
}; };
let code = format!("({}Nix.force({}))", debug_prefix, code); let code = format!("({}{})", debug_prefix, code);
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
eprintln!("[DEBUG] generated code: {}", &code); eprintln!("[DEBUG] generated code: {}", &code);
Ok(code) Ok(code)

View File

@@ -122,7 +122,7 @@ pub fn op_fetch_tarball(
.map_err(|e| NixError::from(e.to_string()))?; .map_err(|e| NixError::from(e.to_string()))?;
let temp_dir = tempfile::tempdir().map_err(|e| NixError::from(e.to_string()))?; let temp_dir = tempfile::tempdir().map_err(|e| NixError::from(e.to_string()))?;
let extracted_path = archive::extract_archive(&data, &temp_dir.path().to_path_buf()) let extracted_path = archive::extract_archive(&data, temp_dir.path())
.map_err(|e| NixError::from(e.to_string()))?; .map_err(|e| NixError::from(e.to_string()))?;
let nar_hash = let nar_hash =

View File

@@ -98,6 +98,7 @@ fn write_contents<W: Write>(sink: &mut W, contents: &[u8]) -> io::Result<()> {
} }
#[cfg(test)] #[cfg(test)]
#[allow(clippy::unwrap_used)]
mod tests { mod tests {
use super::*; use super::*;
use tempfile::TempDir; use tempfile::TempDir;

View File

@@ -52,6 +52,8 @@ ir! {
Int(i64), Int(i64),
Float(f64), Float(f64),
Bool(bool),
Null(()),
Str, Str,
AttrSet, AttrSet,
List, List,