diff --git a/src/eval.js b/src/eval.js index 044ebde..e0a5031 100644 --- a/src/eval.js +++ b/src/eval.js @@ -159,7 +159,7 @@ const codegen = (node, cxt, parent) => { return el.value } else if(el.type == 'key_value_pair') { return '[' + do_codegen(el.key.type == 'computed_property' ? el.key.expr : el.key) + ']' - + ': (' + do_codegen(el.value) + ')' + + ': (' + do_codegen(el.value, el) + ')' } else { throw new Error('unknown node type ' + el.type) } @@ -169,12 +169,18 @@ const codegen = (node, cxt, parent) => { } else if(node.type == 'function_call'){ return codegen_function_call(node, cxt) } else if(node.type == 'function_expr'){ - const name = parent != null && parent.type == 'const' - // TODO here we deduce fn name from left-side of assignment - // TODO name inference is much more sophisticated, for example - // `{foo: () => {...}}` infers name `foo` - ? parent.name - : 'anonymous' + let name + // TODO here we deduce fn name from left-side of assignment + // TODO name inference is much more sophisticated, for example + // `{foo: () => {...}}` infers name `foo` + if(parent?.type == 'const') { + name = parent.name + } else if(parent?.type == 'key_value_pair') { + // unwrap quotes with JSON.parse + name = JSON.parse(parent.key.value) + } else { + name = 'anonymous' + } return codegen_function_expr(node, cxt, name) } else if(node.type == 'ternary'){ return '' diff --git a/test/test.js b/test/test.js index 7383e19..b15c1bf 100644 --- a/test/test.js +++ b/test/test.js @@ -459,6 +459,14 @@ export const tests = [ ) }), + test('function name from object literal', () => { + const i = test_initial_state(` + const fns = {x: () => 1} + fns.x() + `) + assert_equal(root_calltree_node(i).children[0].fn.name, 'x') + }), + test('function name', () => { // TODO /*