A batch of confirmed low-severity correctness edge cases, grouped to limit issue noise. Split out any that warrant a dedicated fix.
1. Extism sends zero bytes instead of {} when input is empty
engines/extism/internal/converters.go:9-11:
if len(inputData) == 0 { return nil, nil }
Eval with no static or context data passes nil to CallWithContext; a guest that would accept {} fails to parse empty input.
Repro (confirmed): Eval with no data → execution failed: unexpected end of JSON input.
Fix: marshal the empty map to {} when the intent is "no data ⇒ empty object"; otherwise document the behavior.
2. Starlark dict → map collides stringified keys and drops unreadable entries
engines/starlark/internal/converters.go:79-97: non-string keys are stringified via k.String(); distinct keys that render identically overwrite each other, and v.Get(k) errors are silently skipped.
Repro (confirmed): _ = {1: "a", "1": "b"} → Interface() == map[1:b] (one entry; 1: "a" lost).
Fix: disambiguate non-string keys (or return an error), and propagate Get errors.
3. Risor uint64 values above MaxInt64 wrap silently
engines/risor/internal/converters.go passes input straight to Risor, whose TypeRegistry.fromGoByKind does NewInt(int64(rv.Uint())).
Repro (confirmed): static data {"big": uint64(math.MaxUint64)}, script ctx["big"] → -1. The wrap is upstream in Risor v2, but go-polyscript feeds the value in unguarded, whereas Starlark's converter rejects uint64. Consider a guard or warning for uint64 values exceeding int64 range, for cross-engine consistency.
4. Starlark eval_data universe entry is dead code
engines/starlark/evaluator/evaluator.go:44 adds eval_data to the runtime universe, but it's never in the compile-time predeclared set (compiler/internal/compile/compile.go), so any script referencing it fails to compile. Remove it or wire it into the predeclared set.
5. Extism execHelper misattributes call failures as cancellation
engines/extism/evaluator/evaluator.go:114-118: when the guest fails for its own reason while ctx is cancelled, the real error is replaced with "execution cancelled: context canceled", discarding the cause. (Root cause that cancellation doesn't actually interrupt execution is #155.) Fix: wrap both errors, or prefer ctx.Err() only for wazero's exit-code-canceled sentinel.
Impact
Low individually — edge cases with clear repros, none covered by existing tests. Worth fixing for robustness and cross-engine consistency.
A batch of confirmed low-severity correctness edge cases, grouped to limit issue noise. Split out any that warrant a dedicated fix.
1. Extism sends zero bytes instead of
{}when input is emptyengines/extism/internal/converters.go:9-11:Evalwith no static or context data passesniltoCallWithContext; a guest that would accept{}fails to parse empty input.Repro (confirmed):
Evalwith no data →execution failed: unexpected end of JSON input.Fix: marshal the empty map to
{}when the intent is "no data ⇒ empty object"; otherwise document the behavior.2. Starlark dict → map collides stringified keys and drops unreadable entries
engines/starlark/internal/converters.go:79-97: non-string keys are stringified viak.String(); distinct keys that render identically overwrite each other, andv.Get(k)errors are silently skipped.Repro (confirmed):
_ = {1: "a", "1": "b"}→Interface() == map[1:b](one entry;1: "a"lost).Fix: disambiguate non-string keys (or return an error), and propagate
Geterrors.3. Risor
uint64values above MaxInt64 wrap silentlyengines/risor/internal/converters.gopasses input straight to Risor, whoseTypeRegistry.fromGoByKinddoesNewInt(int64(rv.Uint())).Repro (confirmed): static data
{"big": uint64(math.MaxUint64)}, scriptctx["big"]→-1. The wrap is upstream in Risor v2, but go-polyscript feeds the value in unguarded, whereas Starlark's converter rejectsuint64. Consider a guard or warning for uint64 values exceeding int64 range, for cross-engine consistency.4. Starlark
eval_datauniverse entry is dead codeengines/starlark/evaluator/evaluator.go:44addseval_datato the runtime universe, but it's never in the compile-time predeclared set (compiler/internal/compile/compile.go), so any script referencing it fails to compile. Remove it or wire it into the predeclared set.5. Extism
execHelpermisattributes call failures as cancellationengines/extism/evaluator/evaluator.go:114-118: when the guest fails for its own reason whilectxis cancelled, the real error is replaced with"execution cancelled: context canceled", discarding the cause. (Root cause that cancellation doesn't actually interrupt execution is #155.) Fix: wrap both errors, or preferctx.Err()only for wazero's exit-code-canceled sentinel.Impact
Low individually — edge cases with clear repros, none covered by existing tests. Worth fixing for robustness and cross-engine consistency.