sync works

This commit is contained in:
Dmitry Vasilev
2023-02-04 23:31:20 +08:00
parent 28d5776219
commit 9d4f5e792f
2 changed files with 102 additions and 96 deletions

View File

@@ -273,7 +273,7 @@ ${JSON.stringify(errormessage)}, true)`
.map(i => i.value) .map(i => i.value)
return do_codegen(node.binding) return do_codegen(node.binding)
+ +
`Object.assign(__cxt.modules[cxt.module], {${identifiers.join(',')}});` `Object.assign(__cxt.modules['${cxt.module}'], {${identifiers.join(',')}});`
} else if(node.type == 'function_decl') { } else if(node.type == 'function_decl') {
const expr = node.children[0] const expr = node.children[0]
return `const ${expr.name} = ${codegen_function_expr(expr, cxt)};` return `const ${expr.name} = ${codegen_function_expr(expr, cxt)};`
@@ -326,10 +326,9 @@ export const eval_modules = (
prev_children: null, prev_children: null,
searched_location: location, searched_location: location,
found_call: null, found_call: null,
promise_then: null,
modules: external_imports == null modules: external_imports == null
? null ? {}
: map_object(external_imports, (name, {module}) => module), : map_object(external_imports, (name, {module}) => module),
on_deferred_call: (call, calltree_changed_token, logs) => { on_deferred_call: (call, calltree_changed_token, logs) => {
@@ -362,14 +361,21 @@ export const eval_modules = (
const module_fn = new Function( const module_fn = new Function(
'__cxt', '__cxt',
codegen(node, {module: module_name}) '__trace',
'__trace_call',
'__do_await',
codegen(parse_result.modules[current_module], {module: current_module})
) )
cxt.modules[current_module] =
try { try {
// cxt.modules[current_module] = {} cxt.modules[current_module] = {}
// TODO await // TODO await
module_fn(cxt) module_fn(
cxt,
__trace,
__trace_call,
__do_await,
)
calltree.ok = true calltree.ok = true
} catch(error) { } catch(error) {
calltree.ok = false calltree.ok = false
@@ -388,9 +394,9 @@ export const eval_modules = (
remove_promise_patch(cxt) remove_promise_patch(cxt)
searched_location = null cxt.searched_location = null
const call = found_call const call = cxt.found_call
found_call = null cxt.found_call = null
return { return {
modules: cxt.modules, modules: cxt.modules,
@@ -403,14 +409,14 @@ export const eval_modules = (
const apply_promise_patch = cxt => { const apply_promise_patch = cxt => {
promise_then = Promise.prototype.then cxt.promise_then = Promise.prototype.then
Promise.prototype.then = function then(on_resolve, on_reject) { Promise.prototype.then = function then(on_resolve, on_reject) {
if(children == null) { if(cxt.children == null) {
children = [] cxt.children = []
} }
let children_copy = children let children_copy = cxt.children
const make_callback = (cb, ok) => typeof(cb) != 'function' const make_callback = (cb, ok) => typeof(cb) != 'function'
? cb ? cb
@@ -418,16 +424,16 @@ const apply_promise_patch = cxt => {
if(this.status == null) { if(this.status == null) {
this.status = ok ? {ok, value} : {ok, error: value} this.status = ok ? {ok, value} : {ok, error: value}
} }
const current = children const current = cxt.children
children = children_copy cxt.children = children_copy
try { try {
return cb(value) return cb(value)
} finally { } finally {
children = current cxt.children = current
} }
} }
return promise_then.call( return cxt.promise_then.call(
this, this,
make_callback(on_resolve, true), make_callback(on_resolve, true),
make_callback(on_reject, false), make_callback(on_reject, false),
@@ -436,35 +442,35 @@ const apply_promise_patch = cxt => {
} }
const remove_promise_patch = cxt => { const remove_promise_patch = cxt => {
Promise.prototype.then = promise_then Promise.prototype.then = cxt.promise_then
} }
const set_record_call = () => { const set_record_call = cxt => {
for(let i = 0; i < stack.length; i++) { for(let i = 0; i < cxt.stack.length; i++) {
stack[i] = true cxt.stack[i] = true
} }
} }
const do_expand_calltree_node = node => { const do_expand_calltree_node = (cxt, node) => {
if(node.fn.__location != null) { if(node.fn.__location != null) {
// fn is hosted, it created call, this time with children // fn is hosted, it created call, this time with children
const result = children[0] const result = cxt.children[0]
result.id = node.id result.id = node.id
result.children = prev_children result.children = cxt.prev_children
result.has_more_children = false result.has_more_children = false
return result return result
} else { } else {
// fn is native, it did not created call, only its child did // fn is native, it did not created call, only its child did
return {...node, return {...node,
children, children: cxt.children,
has_more_children: false, has_more_children: false,
} }
} }
} }
export const eval_expand_calltree_node = (parse_result, node) => { export const eval_expand_calltree_node = (cxt, parse_result, node) => {
is_recording_deferred_calls = false cxt.is_recording_deferred_calls = false
children = null cxt.children = null
try { try {
if(node.is_new) { if(node.is_new) {
new node.fn(...node.args) new node.fn(...node.args)
@@ -474,8 +480,8 @@ export const eval_expand_calltree_node = (parse_result, node) => {
} catch(e) { } catch(e) {
// do nothing. Exception was caught and recorded inside '__trace' // do nothing. Exception was caught and recorded inside '__trace'
} }
is_recording_deferred_calls = true cxt.is_recording_deferred_calls = true
return assign_code(parse_result.modules, do_expand_calltree_node(node)) return assign_code(parse_result.modules, do_expand_calltree_node(cxt, node))
} }
@@ -493,7 +499,7 @@ export const eval_expand_calltree_node = (parse_result, node) => {
*/ */
export const eval_find_call = (cxt, parse_result, calltree, location) => { export const eval_find_call = (cxt, parse_result, calltree, location) => {
// TODO remove // TODO remove
if(children != null) { if(cxt.children != null) {
throw new Error('illegal state') throw new Error('illegal state')
} }
@@ -521,13 +527,13 @@ export const eval_find_call = (cxt, parse_result, calltree, location) => {
// do nothing. Exception was caught and recorded inside '__trace' // do nothing. Exception was caught and recorded inside '__trace'
} }
if(found_call != null) { if(cxt.found_call != null) {
return { return {
node: do_expand_calltree_node(node), node: do_expand_calltree_node(cxt, node),
call: found_call, call: cxt.found_call,
} }
} else { } else {
children = null cxt.children = null
} }
} }
@@ -535,15 +541,15 @@ export const eval_find_call = (cxt, parse_result, calltree, location) => {
return null return null
} }
is_recording_deferred_calls = false cxt.is_recording_deferred_calls = false
searched_location = location cxt.searched_location = location
const result = do_find(calltree) const result = do_find(calltree)
children = null cxt.children = null
searched_location = null cxt.searched_location = null
found_call = null cxt.found_call = null
is_recording_deferred_calls = true cxt.is_recording_deferred_calls = true
if(result == null) { if(result == null) {
return null return null
@@ -562,12 +568,12 @@ const __do_await = async (cxt, value) => {
// can be null to save one empty array allocation in case it has no child // can be null to save one empty array allocation in case it has no child
// calls. Allocate array now, so we can have a reference to this array // calls. Allocate array now, so we can have a reference to this array
// which will be used after await // which will be used after await
if(children == null) { if(cxt.children == null) {
children = [] cxt.children = []
} }
const children_copy = children const children_copy = cxt.children
if(value instanceof Promise) { if(value instanceof Promise) {
promise_then.call(value, cxt.promise_then.call(value,
v => { v => {
value.status = {ok: true, value: v} value.status = {ok: true, value: v}
}, },
@@ -579,7 +585,7 @@ const __do_await = async (cxt, value) => {
try { try {
return await value return await value
} finally { } finally {
children = children_copy cxt.children = children_copy
} }
} }
@@ -589,48 +595,48 @@ const __trace = (cxt, fn, name, argscount, __location, get_closure) => {
result.__closure = get_closure() result.__closure = get_closure()
} }
const children_copy = children const children_copy = cxt.children
children = null cxt.children = null
stack.push(false) cxt.stack.push(false)
const is_found_call = const is_found_call =
(searched_location != null && found_call == null) (cxt.searched_location != null && cxt.found_call == null)
&& &&
( (
__location.index == searched_location.index __location.index == cxt.searched_location.index
&& &&
__location.module == searched_location.module __location.module == cxt.searched_location.module
) )
if(is_found_call) { if(is_found_call) {
// Assign temporary value to prevent nested calls from populating // Assign temporary value to prevent nested calls from populating
// found_call // found_call
found_call = {} cxt.found_call = {}
} }
let ok, value, error let ok, value, error
const is_toplevel_call_copy = is_toplevel_call const is_toplevel_call_copy = cxt.is_toplevel_call
is_toplevel_call = false cxt.is_toplevel_call = false
try { try {
value = fn(...args) value = fn(...args)
ok = true ok = true
if(value instanceof Promise) { if(value instanceof Promise) {
set_record_call() set_record_call(cxt)
} }
return value return value
} catch(_error) { } catch(_error) {
ok = false ok = false
error = _error error = _error
set_record_call() set_record_call(cxt)
throw error throw error
} finally { } finally {
prev_children = children cxt.prev_children = cxt.children
const call = { const call = {
id: call_counter++, id: cxt.call_counter++,
ok, ok,
value, value,
error, error,
@@ -642,34 +648,34 @@ const __trace = (cxt, fn, name, argscount, __location, get_closure) => {
} }
if(is_found_call) { if(is_found_call) {
found_call = call cxt.found_call = call
set_record_call() set_record_call(cxt)
} }
const should_record_call = stack.pop() const should_record_call = cxt.stack.pop()
if(should_record_call) { if(should_record_call) {
call.children = children call.children = cxt.children
} else { } else {
call.has_more_children = children != null && children.length != 0 call.has_more_children = cxt.children != null && cxt.children.length != 0
} }
children = children_copy cxt.children = children_copy
if(children == null) { if(cxt.children == null) {
children = [] cxt.children = []
} }
children.push(call) cxt.children.push(call)
is_toplevel_call = is_toplevel_call_copy cxt.is_toplevel_call = is_toplevel_call_copy
if(is_recording_deferred_calls && is_toplevel_call) { if(cxt.is_recording_deferred_calls && cxt.is_toplevel_call) {
if(children.length != 1) { if(cxt.children.length != 1) {
throw new Error('illegal state') throw new Error('illegal state')
} }
const call = children[0] const call = cxt.children[0]
children = null cxt.children = null
const _logs = logs const _logs = cxt.logs
logs = [] cxt.logs = []
on_deferred_call(call, calltree_changed_token, _logs) cxt.on_deferred_call(call, cxt.calltree_changed_token, _logs)
} }
} }
} }
@@ -694,15 +700,15 @@ const __trace_call = (cxt, fn, context, args, errormessage, is_new = false) => {
) )
} }
const children_copy = children const children_copy = cxt.children
children = null cxt.children = null
stack.push(false) cxt.stack.push(false)
// TODO: other console fns // TODO: other console fns
const is_log = fn == console.log || fn == console.error const is_log = fn == console.log || fn == console.error
if(is_log) { if(is_log) {
set_record_call() set_record_call(cxt)
} }
let ok, value, error let ok, value, error
@@ -719,20 +725,20 @@ const __trace_call = (cxt, fn, context, args, errormessage, is_new = false) => {
} }
ok = true ok = true
if(value instanceof Promise) { if(value instanceof Promise) {
set_record_call() set_record_call(cxt)
} }
return value return value
} catch(_error) { } catch(_error) {
ok = false ok = false
error = _error error = _error
set_record_call() set_record_call(cxt)
throw error throw error
} finally { } finally {
prev_children = children cxt.prev_children = cxt.children
const call = { const call = {
id: call_counter++, id: cxt.call_counter++,
ok, ok,
value, value,
error, error,
@@ -745,22 +751,22 @@ const __trace_call = (cxt, fn, context, args, errormessage, is_new = false) => {
if(is_log) { if(is_log) {
// TODO do not collect logs on find_call? // TODO do not collect logs on find_call?
logs.push(call) cxt.logs.push(call)
} }
const should_record_call = stack.pop() const should_record_call = cxt.stack.pop()
if(should_record_call) { if(should_record_call) {
call.children = children call.children = cxt.children
} else { } else {
call.has_more_children = children != null && children.length != 0 call.has_more_children = cxt.children != null && cxt.children.length != 0
} }
children = children_copy cxt.children = children_copy
if(children == null) { if(cxt.children == null) {
children = [] cxt.children = []
} }
children.push(call) cxt.children.push(call)
} }
} }

View File

@@ -2283,11 +2283,11 @@ const y = x()`
assert_equal(s3.current_calltree_node.toplevel, true) assert_equal(s3.current_calltree_node.toplevel, true)
// Go back to fn // Go back to fn
assert_equal(s3.calltree_actions == null, false) assert_equal(s3.eval_cxt == null, false)
const s4 = COMMANDS.move_cursor( const s4 = COMMANDS.move_cursor(
{...s3, {...s3,
// Set calltree_actions to null, ensure it would not be called again // Set eval_cxt to null, ensure eval would not be called again
calltree_actions: null eval_cxt: null
}, },
code.indexOf('1') code.indexOf('1')
) )