diff --git a/src/value.ts b/src/value.ts index d1f1d3e..212a49e 100644 --- a/src/value.ts +++ b/src/value.ts @@ -68,10 +68,18 @@ export function toValue(v: any, vm?: VM): Value /* throws */ { if (!vm) { const fnName = v.name || '' const fnStr = v.toString().slice(0, 100) + const stack = new Error().stack || '' + const stackLines = stack.split('\n') + .slice(1) + .filter(line => !line.includes('toValue')) + .slice(0, 3) + .map(line => ' ' + line.trim()) + .join('\n') throw new Error( `can't toValue() function without a vm\n` + ` Function: ${fnName}\n` + - ` Source: ${fnStr}${v.toString().length > 100 ? '...' : ''}\n` + ` Source: ${fnStr}${v.toString().length > 100 ? '...' : ''}\n` + + ` Called from:\n${stackLines}` ) } return { type: 'native', fn: wrapNative(vm, v), value: '' } @@ -189,11 +197,18 @@ export function fromValue(v: Value, vm?: VM): any { return v.value case 'function': if (!vm || !(vm instanceof VM)) { + const stack = new Error().stack || '' + const stackLines = stack.split('\n') + .slice(1) + .filter(line => !line.includes('fromValue')) + .slice(0, 3) + .map(line => ' ' + line.trim()) + .join('\n') throw new Error( `VM is required for function conversion\n` + ` Function params: [${v.params.join(', ')}]\n` + ` Function body at instruction: ${v.body}\n` + - ` Tip: Pass a VM instance as the second argument to fromValue()` + ` Called from:\n${stackLines}` ) } return fnFromValue(v, vm) diff --git a/tests/value.test.ts b/tests/value.test.ts index c662de1..4acb35c 100644 --- a/tests/value.test.ts +++ b/tests/value.test.ts @@ -190,7 +190,7 @@ test("toValue - throws helpful error when converting function without VM", () => expect(() => toValue(myFunction)).toThrow(/can't toValue\(\) function without a vm/) expect(() => toValue(myFunction)).toThrow(/Function: myFunction/) expect(() => toValue(myFunction)).toThrow(/Source:/) - expect(() => toValue(myFunction)).toThrow(/Tip: Pass a VM instance/) + expect(() => toValue(myFunction)).toThrow(/Called from:/) }) test("toValue - error message shows function name from binding", () => { @@ -233,5 +233,5 @@ test("fromValue - throws helpful error when converting function without VM", asy expect(() => fromValue(reefFunction)).toThrow(/VM is required for function conversion/) expect(() => fromValue(reefFunction)).toThrow(/Function params: \[x, y\]/) expect(() => fromValue(reefFunction)).toThrow(/Function body at instruction: 10/) - expect(() => fromValue(reefFunction)).toThrow(/Tip: Pass a VM instance/) + expect(() => fromValue(reefFunction)).toThrow(/Called from:/) })