diff --git a/wasm/src/objects.rs b/wasm/src/objects.rs index b4946bf9e..86fd811e8 100644 --- a/wasm/src/objects.rs +++ b/wasm/src/objects.rs @@ -607,25 +607,48 @@ impl Program { Rc::new(DefaultProgramRunner::default()) }; + let clvm_to_modern_err = |_| { + let err: JsValue = JsString::from("error converting result").into(); + err + }; + let run_result = - runner.run_program( + match runner.run_program( &mut allocator, prog_classic, arg_classic, None - ).map_err(|e| { - let err_str: &str = &e.1; - let err: JsValue = JsString::from(err_str).into(); - err - })?; + ) { + Ok(res) => res, + Err(e) => { + let err_str: &str = &e.1; + let err: JsValue = JsString::from(err_str).into(); + let err_atom = + if let Ok(atom) = allocator.new_atom(err_str.as_bytes()) { + atom + } else { + return Err(err); + }; + let err_cons = + if let Ok(cons) = allocator.new_pair(e.0, err_atom) { + cons + } else { + return Err(err); + }; + let modern_err = convert_from_clvm_rs( + &mut allocator, + get_srcloc(), + err_cons + ).map_err(clvm_to_modern_err)?; + return Err(convert_to_program(modern_err)?); + } + }; + let modern_result = convert_from_clvm_rs( &mut allocator, get_srcloc(), run_result.1 - ).map_err(|_| { - let err: JsValue = JsString::from("error converting result").into(); - err - })?; + ).map_err(clvm_to_modern_err)?; let result_object = convert_to_program(modern_result)?; let cost_and_result_array = Array::new(); cost_and_result_array.push(&JsValue::from_f64(run_result.0 as f64)); diff --git a/wasm/tests/clvm-tools-interface/src/lib/tests/index.test.ts b/wasm/tests/clvm-tools-interface/src/lib/tests/index.test.ts index 6e7918609..fc32926d5 100644 --- a/wasm/tests/clvm-tools-interface/src/lib/tests/index.test.ts +++ b/wasm/tests/clvm-tools-interface/src/lib/tests/index.test.ts @@ -174,10 +174,56 @@ it('Has run with operator override', async () => { program.run(args1, options); assert.fail(true); } catch (e) { - assert.equal(e, "path into atom"); + assert.equal(e.toString(), Program.to(t([], "path into atom")).toString()); } }); +it('Can run isolated code and examine the result', async () => { + let program = Program.from_hex('ff02ffff01ff02ff02ffff04ff02ffff04ff05ffff04ff0bff8080808080ffff04ffff01ff9272756e2d776974682d657863657074696f6eff05ff0b80ff018080'); + let use_program = Program.from_hex('ff02ffff01ff02ffff03ff05ffff01ff02ffff01ff02ff02ffff04ff02ff058080ff0180ffff01ff02ffff01ff08ffff018d6e6f206172677320676976656e80ff018080ff0180ffff04ffff01ff02ffff0117ff0180ff018080'); + let options = { + "operators": { + "run-with-exception": (args) => { + let program = args.first(); + let env = args.rest().first(); + try { + let [cost, result] = program.run(env); + return Program.to(t(result, [])); + } catch (e) { + return Program.to(t([], e)); + } + } + } + }; + + let args0 = Program.to([use_program, [[1, 2, 3]]]); + const [cost0, run_result0] = program.run(args0, options); + assert.equal(run_result0.first().as_int(), 3); + assert.ok(run_result0.rest().nullp()); + + let args1 = Program.to([use_program, [[1, 2]]]); + const [cost1, run_result1] = program.run(args1, options); + assert.ok(run_result1.first().nullp()); + console.log(run_result1.first().toString()); + console.log(run_result1.rest().toString()); + assert.equal( + run_result1.rest().toString(), + Program.to(t([], "path into atom")).toString() + ); + + let args2 = Program.to([use_program, [[]]]); + const [cost2, run_result2] = program.run(args2, options); + assert.ok(run_result2.first().nullp()); + assert.equal( + run_result2.rest().first().toString(), + Program.to("no args given").toString() + ); + assert.equal( + run_result2.rest().rest().toString(), + Program.to("clvm raise").toString() + ); +}); + it('Has curry', async () => { let program = Program.from_hex('ff12ffff10ff02ffff010180ffff11ff02ffff01018080'); let program_with_arg = program.curry(Program.to(13));