feat: builtins

This commit is contained in:
2026-01-02 16:29:17 +08:00
parent bd77cde867
commit d2ed3935ca
9 changed files with 757 additions and 52 deletions

View File

@@ -31,7 +31,9 @@ fn run_impl(script: &str, isolate: &mut v8::Isolate) -> Result<Value> {
let runtime_script = v8::Script::compile(scope, runtime_source, None).unwrap();
if runtime_script.run(scope).is_none() {
return Err(Error::eval_error("Failed to initialize runtime".to_string()));
return Err(Error::eval_error(
"Failed to initialize runtime".to_string(),
));
}
let source = v8::String::new(scope, script).unwrap();
@@ -47,7 +49,10 @@ fn run_impl(script: &str, isolate: &mut v8::Isolate) -> Result<Value> {
.to_string(try_catch)
.unwrap()
.to_rust_string_lossy(try_catch);
return Err(Error::eval_error(format!("Compilation error: {}", exception_string)));
return Err(Error::eval_error(format!(
"Compilation error: {}",
exception_string
)));
} else {
return Err(Error::eval_error("Unknown compilation error".to_string()));
}
@@ -62,7 +67,10 @@ fn run_impl(script: &str, isolate: &mut v8::Isolate) -> Result<Value> {
.to_string(try_catch)
.unwrap()
.to_rust_string_lossy(try_catch);
Err(Error::eval_error(format!("Runtime error: {}", exception_string)))
Err(Error::eval_error(format!(
"Runtime error: {}",
exception_string
)))
} else {
Err(Error::eval_error("Unknown runtime error".to_string()))
}
@@ -91,7 +99,7 @@ fn to_value<'a>(
}
_ if val.is_true() => Value::Const(Const::Bool(true)),
_ if val.is_false() => Value::Const(Const::Bool(false)),
_ if val.is_null() => Value::Const(Const::Bool(true)),
_ if val.is_null() => Value::Const(Const::Null),
_ if val.is_string() => {
let val = val.to_string(scope).unwrap();
Value::String(val.to_rust_string_lossy(scope))
@@ -107,7 +115,12 @@ fn to_value<'a>(
.collect();
Value::List(List::new(list))
}
_ if val.is_function() => Value::Func,
_ if val.is_object() => {
if is_thunk(val, scope) {
return Value::Thunk;
}
let val = val.to_object(scope).unwrap();
let keys = val
.get_own_property_names(scope, v8::GetPropertyNamesArgsBuilder::new().build())
@@ -123,18 +136,42 @@ fn to_value<'a>(
.collect();
Value::AttrSet(AttrSet::new(attrs))
}
_ if val.is_function_template() => Value::PrimOp,
_ if val.is_function() => Value::Func,
_ => todo!("{}", val.type_repr()),
}
}
fn is_thunk<'a>(
val: v8::Local<'a, v8::Value>,
scope: &v8::PinnedRef<'a, v8::HandleScope>,
) -> bool {
if !val.is_object() {
return false;
}
let global = scope.get_current_context().global(scope);
let nix_key = v8::String::new(scope, "Nix").unwrap();
let nix_obj = match global.get(scope, nix_key.into()) {
Some(obj) if obj.is_object() => obj.to_object(scope).unwrap(),
_ => return false,
};
let is_thunk_sym_key = v8::String::new(scope, "IS_THUNK").unwrap();
let is_thunk_sym = match nix_obj.get(scope, is_thunk_sym_key.into()) {
Some(sym) if sym.is_symbol() => sym,
_ => return false,
};
let obj = val.to_object(scope).unwrap();
matches!(obj.get(scope, is_thunk_sym), Some(v) if v.is_true())
}
#[test]
fn to_value_working() {
assert_eq!(
run("({
test: [1, 9223372036854775807n, true, false, 'hello world!']
})").unwrap(),
})")
.unwrap(),
Value::AttrSet(AttrSet::new(std::collections::BTreeMap::from([(
Symbol::from("test"),
Value::List(List::new(vec![