From e1517c338e96ded45fb5721215039ed7edb9b969 Mon Sep 17 00:00:00 2001 From: imxyy_soope_ Date: Fri, 20 Feb 2026 10:25:38 +0800 Subject: [PATCH] chore: tidy --- nix-js/runtime-ts/src/builtins/conversion.ts | 5 +- nix-js/runtime-ts/src/builtins/derivation.ts | 12 +- nix-js/runtime-ts/src/builtins/functional.ts | 2 +- nix-js/runtime-ts/src/builtins/index.ts | 24 ++-- nix-js/runtime-ts/src/builtins/misc.ts | 10 +- nix-js/runtime-ts/src/print.ts | 52 ++++---- nix-js/runtime-ts/src/types.ts | 6 +- nix-js/runtime-ts/src/types/global.d.ts | 7 +- nix-js/src/runtime.rs | 133 +++++++------------ typos.toml | 4 +- 10 files changed, 113 insertions(+), 142 deletions(-) diff --git a/nix-js/runtime-ts/src/builtins/conversion.ts b/nix-js/runtime-ts/src/builtins/conversion.ts index ddbbd9b..7592706 100644 --- a/nix-js/runtime-ts/src/builtins/conversion.ts +++ b/nix-js/runtime-ts/src/builtins/conversion.ts @@ -289,13 +289,14 @@ export const toStringFunc = (value: NixValue): NixString => { return coerceToStringWithContext(value, StringCoercionMode.ToString, false); }; +export type JsonValue = number | boolean | string | null | { [key: string]: JsonValue } | Array; export const nixValueToJson = ( value: NixValue, strict: boolean, outContext: NixStringContext, copyToStore: boolean, seen: Set = new Set(), -): unknown => { +): JsonValue => { const v = strict ? force(value) : value; if (isThunk(v) || typeof v === "function") @@ -358,7 +359,7 @@ export const nixValueToJson = ( return nixValueToJson(v.get("outPath") as NixValue, strict, outContext, copyToStore, seen); } - const result: Record = {}; + const result: { [key: string]: JsonValue } = {}; const keys = Array.from(v.keys()).sort(); for (const key of keys) { result[key] = nixValueToJson(v.get(key) as NixValue, strict, outContext, copyToStore, seen); diff --git a/nix-js/runtime-ts/src/builtins/derivation.ts b/nix-js/runtime-ts/src/builtins/derivation.ts index 245789c..c1c6132 100644 --- a/nix-js/runtime-ts/src/builtins/derivation.ts +++ b/nix-js/runtime-ts/src/builtins/derivation.ts @@ -7,7 +7,7 @@ import { import { force } from "../thunk"; import { forceAttrs, forceList, forceStringNoCtx, forceStringValue } from "../type-assert"; import type { NixAttrs, NixValue } from "../types"; -import { coerceToString, nixValueToJson, StringCoercionMode } from "./conversion"; +import { coerceToString, type JsonValue, nixValueToJson, StringCoercionMode } from "./conversion"; export interface OutputInfo { path: string; @@ -205,9 +205,9 @@ const structuredAttrsExcludedKeys = new Set([ const specialAttrs = new Set(["args", "__ignoreNulls", "__contentAddressed", "__impure"]); -const sortedJsonStringify = (obj: Record): string => { +const sortedJsonStringify = (obj: Record): string => { const sortedKeys = Object.keys(obj).sort(); - const sortedObj: Record = {}; + const sortedObj: Record = {}; for (const key of sortedKeys) { sortedObj[key] = obj[key]; } @@ -224,14 +224,14 @@ const extractEnv = ( const env = new Map(); if (structuredAttrs) { - const jsonAttrs: Record = {}; + const jsonAttrs: Record = {}; for (const [key, value] of attrs) { if (!structuredAttrsExcludedKeys.has(key)) { - const forcedValue = force(value as NixValue); + const forcedValue = force(value); if (ignoreNulls && forcedValue === null) { continue; } - jsonAttrs[key] = nixValueToJson(value as NixValue, true, outContext, true); + jsonAttrs[key] = nixValueToJson(value, true, outContext, true); } if (key === "allowedReferences") { diff --git a/nix-js/runtime-ts/src/builtins/functional.ts b/nix-js/runtime-ts/src/builtins/functional.ts index 6a8b55b..45c18e5 100644 --- a/nix-js/runtime-ts/src/builtins/functional.ts +++ b/nix-js/runtime-ts/src/builtins/functional.ts @@ -27,7 +27,7 @@ export const deepSeq = recurse(val); } } else if (isAttrs(forced)) { - for (const [_, val] of Object.entries(forced)) { + for (const [_, val] of forced.entries()) { recurse(val); } } diff --git a/nix-js/runtime-ts/src/builtins/index.ts b/nix-js/runtime-ts/src/builtins/index.ts index 03ad6f4..42fa65b 100644 --- a/nix-js/runtime-ts/src/builtins/index.ts +++ b/nix-js/runtime-ts/src/builtins/index.ts @@ -1,5 +1,5 @@ import { createThunk, force } from "../thunk"; -import type { NixAttrs, NixValue } from "../types"; +import type { NixAttrs, NixFunction, NixValue } from "../types"; import * as arithmetic from "./arithmetic"; import * as attrs from "./attrs"; import * as conversion from "./conversion"; @@ -24,31 +24,31 @@ export interface PrimopMetadata { } export const mkPrimop = ( - func: (...args: NixValue[]) => NixValue, + func: NixFunction, name: string, arity: number, applied: number = 0, ): ((...args: NixValue[]) => NixValue) => { - (func as unknown as Record)[PRIMOP_METADATA] = { + func[PRIMOP_METADATA] = { name, arity, applied, } satisfies PrimopMetadata; if (applied < arity - 1) { - const wrappedFunc = ((...args: NixValue[]) => { - const result = func(...args); + const wrappedFunc: NixFunction = ((arg: NixValue) => { + const result = func(arg); if (typeof result === "function") { - return mkPrimop(result, name, arity, applied + args.length); + return mkPrimop(result, name, arity, applied + 1); } return result; - }) as (...args: NixValue[]) => NixValue; + }); - (wrappedFunc as unknown as Record)[PRIMOP_METADATA] = { + wrappedFunc[PRIMOP_METADATA] = { name, arity, applied, - } satisfies PrimopMetadata; + }; return wrappedFunc; } @@ -57,8 +57,8 @@ export const mkPrimop = ( }; export const isPrimop = ( - value: unknown, -): value is ((...args: never[]) => unknown) & { [PRIMOP_METADATA]: PrimopMetadata } => { + value: NixValue, +): value is NixFunction & { [PRIMOP_METADATA]: PrimopMetadata } => { return ( typeof value === "function" && PRIMOP_METADATA in value && @@ -67,7 +67,7 @@ export const isPrimop = ( ); }; -export const getPrimopMetadata = (func: unknown): PrimopMetadata | undefined => { +export const getPrimopMetadata = (func: NixValue): PrimopMetadata | undefined => { if (isPrimop(func)) { return func[PRIMOP_METADATA]; } diff --git a/nix-js/runtime-ts/src/builtins/misc.ts b/nix-js/runtime-ts/src/builtins/misc.ts index ebb19d3..fb8884c 100644 --- a/nix-js/runtime-ts/src/builtins/misc.ts +++ b/nix-js/runtime-ts/src/builtins/misc.ts @@ -318,10 +318,12 @@ export const splitVersion = (s: NixValue): NixValue => { return components; }; -export const traceVerbose = (_e1: NixValue, e2: NixValue): NixStrictValue => { - // TODO: implement traceVerbose - return force(e2); -}; +export const traceVerbose = + (_e1: NixValue) => + (e2: NixValue): NixStrictValue => { + // TODO: implement traceVerbose + return force(e2); + }; export const tryEval = (e: NixValue): NixAttrs => { try { diff --git a/nix-js/runtime-ts/src/print.ts b/nix-js/runtime-ts/src/print.ts index 501bb40..477f1a2 100644 --- a/nix-js/runtime-ts/src/print.ts +++ b/nix-js/runtime-ts/src/print.ts @@ -39,36 +39,32 @@ export const printValue = (value: NixValue, seen: WeakSet = new WeakSet( return ""; } - if (typeof value === "object") { - if (IS_CYCLE in value) { - return "«repeated»"; - } - - if (seen.has(value)) { - return "«repeated»"; - } - seen.add(value); - - if (isNixPath(value)) { - return value.value; - } - - if (isStringWithContext(value)) { - return printString(value.value); - } - - if (Array.isArray(value)) { - const items = value.map((v) => printValue(v, seen)).join(" "); - return `[ ${items} ]`; - } - - const entries = Object.entries(value) - .map(([k, v]) => `${printSymbol(k)} = ${printValue(v, seen)};`) - .join(" "); - return `{${entries ? ` ${entries} ` : " "}}`; + if (IS_CYCLE in value) { + return "«repeated»"; } - throw new Error("unreachable"); + if (seen.has(value)) { + return "«repeated»"; + } + seen.add(value); + + if (isNixPath(value)) { + return value.value; + } + + if (isStringWithContext(value)) { + return printString(value.value); + } + + if (Array.isArray(value)) { + const items = value.map((v) => printValue(v, seen)).join(" "); + return `[ ${items} ]`; + } + + const entries = [...value.entries()] + .map(([k, v]) => `${printSymbol(k)} = ${printValue(v, seen)};`) + .join(" "); + return `{${entries ? ` ${entries} ` : " "}}`; }; const printString = (s: string): string => { diff --git a/nix-js/runtime-ts/src/types.ts b/nix-js/runtime-ts/src/types.ts index 372999a..68d0937 100644 --- a/nix-js/runtime-ts/src/types.ts +++ b/nix-js/runtime-ts/src/types.ts @@ -1,3 +1,4 @@ +import { PRIMOP_METADATA, type PrimopMetadata } from "./builtins"; import { HAS_CONTEXT, isStringWithContext, type StringWithContext } from "./string-context"; import { type CYCLE_MARKER, force, type NixThunk } from "./thunk"; import { forceAttrs, forceStringNoCtx } from "./type-assert"; @@ -28,7 +29,10 @@ export type NixNull = null; export const ATTR_POSITIONS = Symbol("attrPositions"); export type NixList = NixValue[]; export type NixAttrs = Map & { [ATTR_POSITIONS]?: Map }; -export type NixFunction = ((arg: NixValue) => NixValue) & { args?: NixArgs }; +export type NixFunction = ((arg: NixValue) => NixValue) & { + args?: NixArgs; + [PRIMOP_METADATA]?: PrimopMetadata; +}; export class NixArgs { required: string[]; optional: string[]; diff --git a/nix-js/runtime-ts/src/types/global.d.ts b/nix-js/runtime-ts/src/types/global.d.ts index efec691..752be8f 100644 --- a/nix-js/runtime-ts/src/types/global.d.ts +++ b/nix-js/runtime-ts/src/types/global.d.ts @@ -1,5 +1,6 @@ import type { NixRuntime } from ".."; import type { builtins } from "../builtins"; +import { JsonValue } from "../builtins/conversion"; import type { FetchGitResult, FetchTarballResult, FetchUrlResult } from "../builtins/io"; import type { assert, @@ -15,7 +16,7 @@ import type { import type { op } from "../operators"; import type { createThunk, force } from "../thunk"; import type { forceBool } from "../type-assert"; -import type { mkAttrs, mkFunction, NixAttrs } from "../types"; +import type { mkAttrs, mkFunction, NixAttrs, NixStrictValue } from "../types"; declare global { var Nix: NixRuntime; @@ -92,8 +93,8 @@ declare global { function op_match(regex: string, text: string): (string | null)[] | null; function op_split(regex: string, text: string): (string | (string | null)[])[]; - function op_from_json(json: string): unknown; - function op_from_toml(toml: string): unknown; + function op_from_json(json: string): NixStrictValue; + function op_from_toml(toml: string): NixStrictValue; function op_to_xml(e: NixValue): [string, string[]]; function op_finalize_derivation( diff --git a/nix-js/src/runtime.rs b/nix-js/src/runtime.rs index 1916695..0c28d29 100644 --- a/nix-js/src/runtime.rs +++ b/nix-js/src/runtime.rs @@ -120,11 +120,7 @@ pub(crate) struct Runtime { rt: tokio::runtime::Runtime, #[cfg(feature = "inspector")] wait_for_inspector: bool, - is_thunk_symbol: v8::Global, - primop_metadata_symbol: v8::Global, - has_context_symbol: v8::Global, - is_path_symbol: v8::Global, - is_cycle_symbol: v8::Global, + symbols: GlobalSymbols, _marker: PhantomData, } @@ -166,13 +162,7 @@ impl Runtime { js_runtime.op_state().borrow_mut().put(RegexCache::new()); js_runtime.op_state().borrow_mut().put(DrvHashCache::new()); - let ( - is_thunk_symbol, - primop_metadata_symbol, - has_context_symbol, - is_path_symbol, - is_cycle_symbol, - ) = { + let symbols = { deno_core::scope!(scope, &mut js_runtime); Self::get_symbols(scope)? }; @@ -186,11 +176,7 @@ impl Runtime { .expect("failed to build tokio runtime"), #[cfg(feature = "inspector")] wait_for_inspector: inspector_options.wait, - is_thunk_symbol, - primop_metadata_symbol, - has_context_symbol, - is_path_symbol, - is_cycle_symbol, + symbols, _marker: PhantomData, }) } @@ -236,34 +222,12 @@ impl Runtime { // Retrieve scope from JsRuntime deno_core::scope!(scope, self.js_runtime); let local_value = v8::Local::new(scope, &global_value); - let is_thunk_symbol = v8::Local::new(scope, &self.is_thunk_symbol); - let primop_metadata_symbol = v8::Local::new(scope, &self.primop_metadata_symbol); - let has_context_symbol = v8::Local::new(scope, &self.has_context_symbol); - let is_path_symbol = v8::Local::new(scope, &self.is_path_symbol); - let is_cycle_symbol = v8::Local::new(scope, &self.is_cycle_symbol); + let symbols = &self.symbols.local(scope); - Ok(to_value( - local_value, - scope, - is_thunk_symbol, - primop_metadata_symbol, - has_context_symbol, - is_path_symbol, - is_cycle_symbol, - )) + Ok(to_value(local_value, scope, symbols)) } - /// get (IS_THUNK, PRIMOP_METADATA, HAS_CONTEXT, IS_PATH, IS_CYCLE) - #[allow(clippy::type_complexity)] - fn get_symbols( - scope: &ScopeRef, - ) -> Result<( - v8::Global, - v8::Global, - v8::Global, - v8::Global, - v8::Global, - )> { + fn get_symbols(scope: &ScopeRef) -> Result { let global = scope.get_current_context().global(scope); let nix_key = v8::String::new(scope, "Nix") .ok_or_else(|| Error::internal("failed to create V8 String".into()))?; @@ -295,18 +259,48 @@ impl Runtime { let is_path = get_symbol("IS_PATH")?; let is_cycle = get_symbol("IS_CYCLE")?; - Ok((is_thunk, primop_metadata, has_context, is_path, is_cycle)) + Ok(GlobalSymbols { + is_thunk, + primop_metadata, + has_context, + is_path, + is_cycle, + }) } } +struct GlobalSymbols { + is_thunk: v8::Global, + primop_metadata: v8::Global, + has_context: v8::Global, + is_path: v8::Global, + is_cycle: v8::Global, +} + +impl GlobalSymbols { + fn local<'a>(&self, scope: &ScopeRef<'a, '_>) -> LocalSymbols<'a> { + LocalSymbols { + is_thunk: v8::Local::new(scope, &self.is_thunk), + primop_metadata: v8::Local::new(scope, &self.primop_metadata), + has_context: v8::Local::new(scope, &self.has_context), + is_path: v8::Local::new(scope, &self.is_path), + is_cycle: v8::Local::new(scope, &self.is_cycle), + } + } +} + +struct LocalSymbols<'a> { + is_thunk: v8::Local<'a, v8::Symbol>, + primop_metadata: v8::Local<'a, v8::Symbol>, + has_context: v8::Local<'a, v8::Symbol>, + is_path: v8::Local<'a, v8::Symbol>, + is_cycle: v8::Local<'a, v8::Symbol>, +} + fn to_value<'a>( val: LocalValue<'a>, scope: &ScopeRef<'a, '_>, - is_thunk_symbol: LocalSymbol<'a>, - primop_metadata_symbol: LocalSymbol<'a>, - has_context_symbol: LocalSymbol<'a>, - is_path_symbol: LocalSymbol<'a>, - is_cycle_symbol: LocalSymbol<'a>, + symbols: &LocalSymbols<'a>, ) -> Value { match () { _ if val.is_big_int() => { @@ -336,21 +330,13 @@ fn to_value<'a>( let list = (0..len) .map(|i| { let val = val.get_index(scope, i).expect("infallible index operation"); - to_value( - val, - scope, - is_thunk_symbol, - primop_metadata_symbol, - has_context_symbol, - is_path_symbol, - is_cycle_symbol, - ) + to_value(val, scope, symbols) }) .collect(); Value::List(List::new(list)) } _ if val.is_function() => { - if let Some(primop) = to_primop(val, scope, primop_metadata_symbol) { + if let Some(primop) = to_primop(val, scope, symbols.primop_metadata) { primop } else { Value::Func @@ -369,34 +355,26 @@ fn to_value<'a>( let val = array .get_index(scope, i * 2 + 1) .expect("infallible index operation"); - let val = to_value( - val, - scope, - is_thunk_symbol, - primop_metadata_symbol, - has_context_symbol, - is_path_symbol, - is_cycle_symbol, - ); + let val = to_value(val, scope, symbols); (Symbol::new(Cow::Owned(key)), val) }) .collect(); Value::AttrSet(AttrSet::new(attrs)) } _ if val.is_object() => { - if is_thunk(val, scope, is_thunk_symbol) { + if is_thunk(val, scope, symbols.is_thunk) { return Value::Thunk; } - if is_cycle(val, scope, is_cycle_symbol) { + if is_cycle(val, scope, symbols.is_cycle) { return Value::Repeated; } - if let Some(path_val) = extract_path(val, scope, is_path_symbol) { + if let Some(path_val) = extract_path(val, scope, symbols.is_path) { return Value::Path(path_val); } - if let Some(string_val) = extract_string_with_context(val, scope, has_context_symbol) { + if let Some(string_val) = extract_string_with_context(val, scope, symbols.has_context) { return Value::String(string_val); } @@ -412,18 +390,7 @@ fn to_value<'a>( .expect("infallible index operation"); let val = val.get(scope, key).expect("infallible operation"); let key = key.to_rust_string_lossy(scope); - ( - Symbol::from(key), - to_value( - val, - scope, - is_thunk_symbol, - primop_metadata_symbol, - has_context_symbol, - is_path_symbol, - is_cycle_symbol, - ), - ) + (Symbol::from(key), to_value(val, scope, symbols)) }) .collect(); Value::AttrSet(AttrSet::new(attrs)) diff --git a/typos.toml b/typos.toml index d2076c7..93588e8 100644 --- a/typos.toml +++ b/typos.toml @@ -1,7 +1,7 @@ [files] extend-exclude = [ - "nix-js/tests/basic/regex.rs", - "nix-js/tests/lang", + "nix-js/tests/tests/regex.rs", + "nix-js/tests/tests/lang", ] [default.extend-words]