feat: mkAttrs
This commit is contained in:
@@ -23,7 +23,7 @@ import { op } from "./operators";
|
||||
import { builtins, PRIMOP_METADATA } from "./builtins";
|
||||
import { coerceToString, StringCoercionMode } from "./builtins/conversion";
|
||||
import { HAS_CONTEXT } from "./string-context";
|
||||
import { IS_PATH, mkFunction } from "./types";
|
||||
import { IS_PATH, mkAttrs, mkFunction } from "./types";
|
||||
import { forceBool } from "./type-assert";
|
||||
|
||||
export type NixRuntime = typeof Nix;
|
||||
@@ -52,6 +52,7 @@ export const Nix = {
|
||||
coerceToString,
|
||||
concatStringsWithContext,
|
||||
StringCoercionMode,
|
||||
mkAttrs,
|
||||
mkFunction,
|
||||
|
||||
pushContext,
|
||||
|
||||
@@ -2,10 +2,11 @@
|
||||
* Core TypeScript type definitions for nix-js runtime
|
||||
*/
|
||||
|
||||
import { IS_THUNK } from "./thunk";
|
||||
import { type StringWithContext, HAS_CONTEXT, isStringWithContext } from "./string-context";
|
||||
import { force, IS_THUNK } from "./thunk";
|
||||
import { type StringWithContext, HAS_CONTEXT, isStringWithContext, getStringContext } from "./string-context";
|
||||
import { op } from "./operators";
|
||||
import { forceAttrs } from "./type-assert";
|
||||
import { isString, typeOf } from "./builtins/type-check";
|
||||
export { HAS_CONTEXT, isStringWithContext };
|
||||
export type { StringWithContext };
|
||||
|
||||
@@ -73,6 +74,24 @@ export const mkFunction = (
|
||||
return func;
|
||||
};
|
||||
|
||||
export const mkAttrs = (attrs: NixAttrs, keys: NixValue[], values: NixValue[]): NixAttrs => {
|
||||
const len = keys.length;
|
||||
for (let i = 0; i < len; i++) {
|
||||
const key = force(keys[i]);
|
||||
if (key === null) {
|
||||
continue;
|
||||
}
|
||||
if (!isString(key)) {
|
||||
throw `Expected string, got ${typeOf(key)}`
|
||||
}
|
||||
if (isStringWithContext(key)) {
|
||||
throw new TypeError(`the string '${key.value}' is not allowed to refer to a store path`)
|
||||
}
|
||||
attrs[key] = values[i];
|
||||
}
|
||||
return attrs;
|
||||
};
|
||||
|
||||
/**
|
||||
* Interface for lazy thunk values
|
||||
* Thunks delay evaluation until forced
|
||||
|
||||
@@ -353,24 +353,28 @@ impl<Ctx: CodegenContext> Compile<Ctx> for AttrSet {
|
||||
attrs.push(format!("{}:{}", key.escape_quote(), value));
|
||||
}
|
||||
|
||||
// FIXME: duplicated key
|
||||
for (key_expr, value_expr) in &self.dyns {
|
||||
let key = ctx.get_ir(*key_expr).compile(ctx);
|
||||
let value_code = ctx.get_ir(*value_expr).compile(ctx);
|
||||
|
||||
let value = if stack_trace_enabled {
|
||||
let value_span = encode_span(ctx.get_ir(*value_expr).span(), ctx);
|
||||
format!(
|
||||
"Nix.withContext(\"while evaluating a dynamic attribute\",{},()=>({}))",
|
||||
value_span, value_code
|
||||
)
|
||||
} else {
|
||||
value_code
|
||||
};
|
||||
attrs.push(format!("[{}]:{}", key, value));
|
||||
if !self.dyns.is_empty() {
|
||||
let (keys, vals) = self.dyns.iter().map(|&(key, val)| {
|
||||
let key = ctx.get_ir(key).compile(ctx);
|
||||
let val_expr = ctx.get_ir(val);
|
||||
let val = val_expr.compile(ctx);
|
||||
let span = val_expr.span();
|
||||
let val = if stack_trace_enabled {
|
||||
let span = encode_span(span, ctx);
|
||||
format!(
|
||||
"Nix.withContext(\"while evaluating a dynamic attribute\",{},()=>({}))",
|
||||
span, val
|
||||
)
|
||||
} else {
|
||||
val
|
||||
};
|
||||
(key, val)
|
||||
}).collect::<(Vec<_>, Vec<_>)>();
|
||||
format!("Nix.mkAttrs({{{}}},[{}],[{}])", attrs.join(","), keys.join(","), vals.join(","))
|
||||
} else {
|
||||
format!("{{{}}}", attrs.join(","))
|
||||
}
|
||||
|
||||
format!("{{{}}}", attrs.join(","))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user