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;
};
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 => {
switch (elem.type) {
case "opaque":

View File

@@ -39,6 +39,8 @@ impl<Ctx: CodegenContext> Compile<Ctx> for Ir {
match self {
Ir::Int(int) => format!("{int}n"), // Generate BigInt literal
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::Path(p) => {
// 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),
Con => format!("Nix.op.concat({},{})", lhs, rhs),
Upd => format!("Nix.op.update({},{})", lhs, rhs),
PipeL => format!("Nix.force({})({})", rhs, lhs),
PipeR => format!("Nix.force({})({})", lhs, rhs),
PipeL => format!("Nix.call({}, {})", rhs, lhs),
PipeR => format!("Nix.call({}, {})", lhs, rhs),
}
}
}

View File

@@ -81,7 +81,7 @@ impl Context {
let ctx = guard.as_ctx();
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> {
@@ -116,9 +116,6 @@ impl Default for Ctx {
global.insert(builtins_sym, builtins_expr);
let free_globals = [
"true",
"false",
"null",
"abort",
"baseNameOf",
"break",
@@ -139,6 +136,11 @@ impl Default for Ctx {
"throw",
"toString",
];
let consts = [
("true", Ir::Bool(true)),
("false", Ir::Bool(false)),
("null", Ir::Null(())),
];
for name in free_globals {
let name_sym = symbols.get_or_intern(name);
@@ -146,6 +148,12 @@ impl Default for Ctx {
irs.push(Builtin(name_sym).to_ir());
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 {
symbols,
@@ -195,7 +203,7 @@ impl Ctx {
} else {
""
};
let code = format!("({}Nix.force({}))", debug_prefix, code);
let code = format!("({}{})", debug_prefix, code);
#[cfg(debug_assertions)]
eprintln!("[DEBUG] generated code: {}", &code);
Ok(code)

View File

@@ -122,7 +122,7 @@ pub fn op_fetch_tarball(
.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()))?;
let nar_hash =

View File

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

View File

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