fromValue can convert native functions now
This commit is contained in:
parent
676f53c66b
commit
0f39e9401e
|
|
@ -1,4 +1,4 @@
|
|||
import { wrapNative } from "./function"
|
||||
import { wrapNative, getOriginalFunction } from "./function"
|
||||
import { OpCode } from "./opcode"
|
||||
import { Scope } from "./scope"
|
||||
import { VM } from "./vm"
|
||||
|
|
@ -183,7 +183,7 @@ export function fromValue(v: Value, vm?: VM): any {
|
|||
if (!vm || !(vm instanceof VM)) throw new Error('VM is required for function conversion')
|
||||
return fnFromValue(v, vm)
|
||||
case 'native':
|
||||
return '<function>'
|
||||
return getOriginalFunction(v.fn)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -113,3 +113,74 @@ test("toValue - converts wrapped Reef functions back to original Value", async (
|
|||
expect(backToValue).toBe(reefFunction) // Same reference
|
||||
expect(backToValue.type).toBe("function")
|
||||
})
|
||||
|
||||
test("fromValue - converts native function back to original JS function", async () => {
|
||||
const { VM, toBytecode, toValue, fromValue } = await import("#reef")
|
||||
|
||||
const bytecode = toBytecode([["HALT"]])
|
||||
const vm = new VM(bytecode)
|
||||
|
||||
// Create a native JS function
|
||||
const originalFn = (x: number, y: number) => x * y
|
||||
|
||||
// Convert to Value (wraps it as a native function)
|
||||
const nativeValue = toValue(originalFn, vm)
|
||||
expect(nativeValue.type).toBe("native")
|
||||
|
||||
// Convert back to JS - should get the original function
|
||||
const convertedFn = fromValue(nativeValue, vm)
|
||||
expect(typeof convertedFn).toBe("function")
|
||||
|
||||
// Verify it's the same function
|
||||
expect(convertedFn).toBe(originalFn)
|
||||
|
||||
// Verify it works correctly
|
||||
expect(convertedFn(3, 4)).toBe(12)
|
||||
})
|
||||
|
||||
test("fromValue - native function roundtrip preserves functionality", async () => {
|
||||
const { VM, toBytecode, toValue, fromValue } = await import("#reef")
|
||||
|
||||
const bytecode = toBytecode([["HALT"]])
|
||||
const vm = new VM(bytecode)
|
||||
|
||||
// Create a native function with state
|
||||
let callCount = 0
|
||||
const countingFn = (n: number) => {
|
||||
callCount++
|
||||
return n * callCount
|
||||
}
|
||||
|
||||
// Roundtrip through Value
|
||||
const nativeValue = toValue(countingFn, vm)
|
||||
const roundtrippedFn = fromValue(nativeValue, vm)
|
||||
|
||||
// Verify it maintains state across calls
|
||||
expect(roundtrippedFn(10)).toBe(10) // 10 * 1
|
||||
expect(roundtrippedFn(10)).toBe(20) // 10 * 2
|
||||
expect(roundtrippedFn(10)).toBe(30) // 10 * 3
|
||||
expect(callCount).toBe(3)
|
||||
})
|
||||
|
||||
test("fromValue - async native function roundtrip", async () => {
|
||||
const { VM, toBytecode, toValue, fromValue } = await import("#reef")
|
||||
|
||||
const bytecode = toBytecode([["HALT"]])
|
||||
const vm = new VM(bytecode)
|
||||
|
||||
// Create an async native function
|
||||
const asyncFn = async (x: number, y: number) => {
|
||||
await new Promise(resolve => setTimeout(resolve, 1))
|
||||
return x + y
|
||||
}
|
||||
|
||||
// Roundtrip through Value
|
||||
const nativeValue = toValue(asyncFn, vm)
|
||||
expect(nativeValue.type).toBe("native")
|
||||
|
||||
const roundtrippedFn = fromValue(nativeValue, vm)
|
||||
|
||||
// Verify it works
|
||||
const result = await roundtrippedFn(5, 7)
|
||||
expect(result).toBe(12)
|
||||
})
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user