Bug: @gorules/zen-engine-wasm truncates all decimal results to integers
Description
evaluateExpression in @gorules/zen-engine-wasm truncates all decimal (non-integer) results to integers. The same expressions evaluated via @gorules/zen-engine (Node.js native) return correct decimal values.
Minimal reproduction
<script type="module">
import init, { evaluateExpression } from '@gorules/zen-engine-wasm';
await init();
// All decimals are truncated to integers
console.log(evaluateExpression('3.7', {})); // Returns 3, expected 3.7
console.log(evaluateExpression('1.5 + 0.1', {})); // Returns 1, expected 1.6
console.log(evaluateExpression('2 * 0.3', {})); // Returns 0, expected 0.6
console.log(evaluateExpression('10 / 3', {})); // Returns 3, expected 3.333...
// Integer results work correctly
console.log(evaluateExpression('1 + 2', {})); // Returns 3, correct
console.log(evaluateExpression('4 * 5', {})); // Returns 20, correct
</script>
Expected behavior
evaluateExpression('3.7', {}) should return 3.7.
Actual behavior
evaluateExpression('3.7', {}) returns 3.
Every expression that produces a non-integer Decimal value has its fractional part silently dropped.
Environment
@gorules/zen-engine-wasm: 0.23.1
- Browser: Chrome 134, Firefox 136 (same behavior)
- OS: Linux x86_64
Root cause analysis
The WASM package in gorules/jdm-editor (packages/zen-engine-wasm/src/expression/evaluate.rs) returns results via:
Ok(JsValue::from_serde(&result)?)
The Variable serializer (in gorules/zen at core/types/src/variable/ser.rs) without the arbitrary_precision feature tries:
if let Some(u) = v.to_u64() { return serializer.serialize_u64(u); }
rust_decimal::Decimal::to_u64() calls self.trunc() first, so Decimal(1.6).to_u64() returns Some(1) — the fractional part is silently dropped.
The Node.js native package (@gorules/zen-engine) enables arbitrary_precision in its Cargo.toml, which uses a string-based serialization path that preserves decimal precision. The WASM package does not enable this feature.
Suggested fix
In gorules/jdm-editor, file packages/zen-engine-wasm/Cargo.toml, add the arbitrary_precision feature:
# Current:
zen-expression = { version = "0.55.0", default-features = false, features = ["regex-lite"] }
# Fix:
zen-expression = { version = "0.55.0", default-features = false, features = ["regex-lite", "arbitrary_precision"] }
And add arbitrary_precision to serde_json:
serde_json = { version = "1", features = ["arbitrary_precision"] }
This aligns the WASM package with the Node.js, Python, C, and UniFFI bindings which all enable arbitrary_precision (as done in PR #433 for the other bindings).
Validated locally
I cloned gorules/jdm-editor, applied the above change to packages/zen-engine-wasm/Cargo.toml, and rebuilt with wasm-pack build --target web --release. After replacing the .wasm and .js files in node_modules/@gorules/zen-engine-wasm/dist/, all tests pass:
OK | 3.7 → 3.7 (expected 3.7)
OK | 1.5 + 0.1 → 1.6 (expected 1.6)
OK | 2 * 0.3 → 0.6 (expected 0.6)
OK | 1 + 2 → 3 (expected 3)
OK | 1 + (x ? 0.5 : 0) + y * 0.3 → 1.6 (expected 1.6) // x=false, y=2
OK | 1 + (x ? 0.5 : 0) + y * 0.3 → 2.1 (expected 2.1) // x=true, y=2
Bug:
@gorules/zen-engine-wasmtruncates all decimal results to integersDescription
evaluateExpressionin@gorules/zen-engine-wasmtruncates all decimal (non-integer) results to integers. The same expressions evaluated via@gorules/zen-engine(Node.js native) return correct decimal values.Minimal reproduction
Expected behavior
evaluateExpression('3.7', {})should return3.7.Actual behavior
evaluateExpression('3.7', {})returns3.Every expression that produces a non-integer
Decimalvalue has its fractional part silently dropped.Environment
@gorules/zen-engine-wasm: 0.23.1Root cause analysis
The WASM package in
gorules/jdm-editor(packages/zen-engine-wasm/src/expression/evaluate.rs) returns results via:The
Variableserializer (ingorules/zenatcore/types/src/variable/ser.rs) without thearbitrary_precisionfeature tries:rust_decimal::Decimal::to_u64()callsself.trunc()first, soDecimal(1.6).to_u64()returnsSome(1)— the fractional part is silently dropped.The Node.js native package (
@gorules/zen-engine) enablesarbitrary_precisionin itsCargo.toml, which uses a string-based serialization path that preserves decimal precision. The WASM package does not enable this feature.Suggested fix
In
gorules/jdm-editor, filepackages/zen-engine-wasm/Cargo.toml, add thearbitrary_precisionfeature:And add
arbitrary_precisiontoserde_json:This aligns the WASM package with the Node.js, Python, C, and UniFFI bindings which all enable
arbitrary_precision(as done in PR #433 for the other bindings).Validated locally
I cloned
gorules/jdm-editor, applied the above change topackages/zen-engine-wasm/Cargo.toml, and rebuilt withwasm-pack build --target web --release. After replacing the.wasmand.jsfiles innode_modules/@gorules/zen-engine-wasm/dist/, all tests pass: