From 6ea107d0576997cbb3cda7686ef9378076e55f20 Mon Sep 17 00:00:00 2001 From: Dmitry Vasilev Date: Tue, 29 Nov 2022 04:22:56 +0800 Subject: [PATCH] discard async calls from prev code run --- src/cmd.js | 7 +++- src/eval.js | 14 ++++++-- test/test.js | 94 +++++++++++++++++---------------------------------- test/utils.js | 23 +++++++++++++ 4 files changed, 72 insertions(+), 66 deletions(-) diff --git a/src/cmd.js b/src/cmd.js index 41f5666..b240ac3 100644 --- a/src/cmd.js +++ b/src/cmd.js @@ -180,6 +180,7 @@ const do_external_imports_loaded = ( state.parse_result, external_imports, state.on_async_call, + state.calltree_changed_token, ) const next = apply_eval_result(state, result) @@ -202,6 +203,7 @@ const do_external_imports_loaded = ( state.parse_result, external_imports, state.on_async_call, + state.calltree_changed_token, {index: node.index, module: state.current_module}, ) @@ -744,7 +746,10 @@ const move_cursor = (s, index) => { return do_move_cursor(state, index) } -const on_async_call = (state, call) => { +const on_async_call = (state, call, calltree_changed_token) => { + if(state.calltree_changed_token != calltree_changed_token) { + return state + } return {...state, calltree: make_calltree( root_calltree_node(state), diff --git a/src/eval.js b/src/eval.js index 7bb82c7..907fe75 100644 --- a/src/eval.js +++ b/src/eval.js @@ -257,6 +257,7 @@ export const eval_modules = ( parse_result, external_imports, on_async_call, + calltree_changed_token, location ) => { // TODO gensym __modules, __exports @@ -429,7 +430,7 @@ export const eval_modules = ( } const call = children[0] children = null - on_async_call(call) + on_async_call(call, calltree_changed_token) } } } @@ -567,6 +568,7 @@ export const eval_modules = ( const actions = make_function( 'external_imports', 'on_async_call', + 'calltree_changed_token', codestring )( /* external_imports */ @@ -575,7 +577,15 @@ export const eval_modules = ( : map_object(external_imports, (name, {module}) => module), /* on_async_call */ - call => on_async_call(assign_code(parse_result.modules, call)) + (call, calltree_changed_token) => { + return on_async_call( + assign_code(parse_result.modules, call), + calltree_changed_token, + ) + }, + + /* calltree_changed_token */ + calltree_changed_token ) const calltree_actions = { diff --git a/test/test.js b/test/test.js index d836a0f..b1bf08b 100644 --- a/test/test.js +++ b/test/test.js @@ -14,6 +14,7 @@ import { assert_code_error, parse_modules, test_initial_state, + test_async_calls_state, print_debug_ct_node, } from './utils.js' @@ -2324,31 +2325,18 @@ const y = x()` } ` - const {get_async_call, on_async_call} = (new Function(` - let call - return { - get_async_call() { - return call - }, - on_async_call(_call) { - call = _call - } - } - `))() - - const i = test_initial_state(code, { on_async_call }) + const {state: i, on_async_call} = test_async_calls_state(code) // Make async call i.modules[''].fn(10) - const call = get_async_call() + const state = on_async_call(i) + assert_equal(state.logs.logs.length, 1) + + const call = get_async_calls(state)[0] assert_equal(call.fn.name, 'fn') assert_equal(call.code.index, code.indexOf('() => {')) assert_equal(call.args, [10]) - const state = COMMANDS.on_async_call(i, call) - assert_equal(get_async_calls(state), [call]) - - assert_equal(state.logs.logs.length, 1) // Expand call const {state: expanded} = COMMANDS.calltree.click(state, call.id) @@ -2373,26 +2361,13 @@ const y = x()` } ` - const {get_async_call, on_async_call} = (new Function(` - let call - return { - get_async_call() { - return call - }, - on_async_call(_call) { - call = _call - } - } - `))() - - const i = test_initial_state(code, { on_async_call }) + const {state: i, on_async_call} = test_async_calls_state(code) const after_async_calls = [1, 2, 3].reduce( (s, a) => { // Make async calls i.modules[''].async_call(a) - const call = get_async_call() - return COMMANDS.on_async_call(s, call) + return on_async_call(s) }, i ) @@ -2458,25 +2433,12 @@ const y = x()` } ` - const {get_async_call, on_async_call} = (new Function(` - let call - return { - get_async_call() { - return call - }, - on_async_call(_call) { - call = _call - } - } - `))() - - const i = test_initial_state(code, { on_async_call }) + const {state: i, on_async_call} = test_async_calls_state(code) // Make async call i.modules[''].fn() - const call = get_async_call() - const state = COMMANDS.on_async_call(i, call) + const state = on_async_call(i) const {state: moved} = COMMANDS.move_cursor(state, code.indexOf('fn2')) assert_equal(moved.active_calltree_node.fn.name, 'fn') @@ -2495,24 +2457,12 @@ const y = x()` export const fn = () => { /* label */ } ` - const {get_async_call, on_async_call} = (new Function(` - let call - return { - get_async_call() { - return call - }, - on_async_call(_call) { - call = _call - } - } - `))() - - const i = test_initial_state(code, { on_async_call }) + const {state: i, on_async_call} = test_async_calls_state(code) // Make async call i.modules[''].fn(1) - const state = COMMANDS.on_async_call(i, get_async_call()) + const state = on_async_call(i) // find call const {state: moved} = COMMANDS.move_cursor(state, code.indexOf('label')) @@ -2520,9 +2470,27 @@ const y = x()` // Make async call i.modules[''].fn(2) - const result = COMMANDS.on_async_call(moved, get_async_call()) + const result = on_async_call(moved) // there was a bug throwing error when added second async call assert_equal(get_async_calls(result).map(c => c.args), [[1], [2]]) }), + + test('async_calls discard on code rerun', () => { + const code = ` + export const fn = () => { /* label */ } + ` + const {state: i, on_async_call} = test_async_calls_state(code) + + const input = COMMANDS.input(i, code, 0).state + + // Make async call, calling fn from previous code + i.modules[''].fn(1) + + const result = on_async_call(input) + + // Async calls must be null, because async calls from previous executions + // must be discarded + assert_equal(get_async_calls(result), null) + }), ] diff --git a/test/utils.js b/test/utils.js index 30339f4..769d30d 100644 --- a/test/utils.js +++ b/test/utils.js @@ -40,6 +40,29 @@ export const test_initial_state = (code, state) => { ) } +export const test_async_calls_state = code => { + const {get_async_call, on_async_call} = (new Function(` + let call, calltree_changed_token + return { + get_async_call() { + return [call, calltree_changed_token] + }, + on_async_call(_call, _calltree_changed_token) { + call = _call + calltree_changed_token = _calltree_changed_token + } + } + `))() + + const state = test_initial_state(code, { on_async_call }) + + return { + state, + get_async_call, + on_async_call: state => COMMANDS.on_async_call(state, ...get_async_call()) + } +} + export const stringify = val => JSON.stringify(val, (key, value) => { // TODO do not use instanceof because currently not implemented in parser