From 747bceda7b17d65d4c153c887a2878f444d5f526 Mon Sep 17 00:00:00 2001 From: Dmitry Vasilev Date: Fri, 2 Dec 2022 08:17:49 +0800 Subject: [PATCH] WIP --- src/effects.js | 4 +++- src/eval.js | 47 ++++++++++++++++++++++++++++------------- src/find_definitions.js | 5 +++++ test/test.js | 2 +- 4 files changed, 41 insertions(+), 17 deletions(-) diff --git a/src/effects.js b/src/effects.js index df25651..2cd99d1 100644 --- a/src/effects.js +++ b/src/effects.js @@ -129,6 +129,7 @@ export const render_initial_state = (ui, state) => { ui.editor.switch_session(state.current_module) } +// TODO remove async export const render_common_side_effects = async (prev, next, command, ui) => { if( prev.project_dir != next.project_dir @@ -188,7 +189,8 @@ export const render_common_side_effects = async (prev, next, command, ui) => { } else { - await unwrap_settled_promises(next.calltree) + // TODO remove + // await unwrap_settled_promises(next.calltree) if( prev.calltree == null diff --git a/src/eval.js b/src/eval.js index bed1b17..3b43f21 100644 --- a/src/eval.js +++ b/src/eval.js @@ -12,6 +12,8 @@ import { map_tree, } from './ast_utils.js' +import {has_toplevel_await} from './find_definitions.js' + // TODO: fix error messages. For example, "__fn is not a function" /* @@ -255,6 +257,16 @@ const codegen = (node, cxt, parent) => { } } +/* TODO remove +const sync_promise = value => { + if(value instanceof run_window.Promise.Original) { + return value + } else { + return {is_sync_promise: true, then: fn => sync_promise(fn(value))} + } +} +*/ + export const eval_modules = ( parse_result, external_imports, @@ -266,6 +278,8 @@ export const eval_modules = ( // TODO bug if module imported twice, once as external and as regular + const is_async = has_toplevel_await(parse_result.modules) + const codestring = ` let children, prev_children @@ -530,7 +544,7 @@ export const eval_modules = ( } } - const run = () => { + const run = ${is_async ? 'async' : ''} () => { is_recording_deferred_calls = false @@ -554,18 +568,17 @@ export const eval_modules = ( module: current_module, id: call_counter++ } - __modules[current_module] = - (() => { - try { - const __exports = {}; - ${codegen(parse_result.modules[m], {module: m})}; - current_call.ok = true - return __exports - } catch(error) { - current_call.ok = false - current_call.error = error - } - })() + __modules[current_module] = ${is_async ? 'await (async' : '('} () => { + try { + const __exports = {}; + ${codegen(parse_result.modules[m], {module: m})}; + current_call.ok = true + return __exports + } catch(error) { + current_call.ok = false + current_call.error = error + } + })() current_call.children = children if(!current_call.ok) { is_recording_deferred_calls = true @@ -639,12 +652,16 @@ export const eval_modules = ( ? actions.run() : calltree_actions.find_call(location) - return { + const make_result = result => ({ modules: result.modules, calltree: assign_code(parse_result.modules, result.calltree), call: result.call, calltree_actions, - } + }) + + return is_async + ? result.then(make_result) + : make_result(result) } // TODO: assign_code: benchmark and use imperative version for perf? diff --git a/src/find_definitions.js b/src/find_definitions.js index 5ce41d1..528f488 100644 --- a/src/find_definitions.js +++ b/src/find_definitions.js @@ -202,6 +202,11 @@ export const topsort_modules = (modules) => { ) } +export const has_toplevel_await = modules => + Object.values(modules).some(m => + m.children.find(c => c.type == 'unary' && c.operator == 'await' ) != null + ) + // TODO not implemented // TODO detect cycles when loading modules export const check_imports = modules => { diff --git a/test/test.js b/test/test.js index afaf7d0..3d16136 100644 --- a/test/test.js +++ b/test/test.js @@ -2593,7 +2593,7 @@ const y = x()` const code = ` const x = async () => 123 const y = async () => await x() - y() + await y() ` const s = test_initial_state(code) const move = COMMANDS.move_cursor(s, code.indexOf('await x()')).state