This commit is contained in:
Dmitry Vasilev
2022-12-07 05:42:33 +08:00
parent 707c34bc66
commit 3ea0bedc31
7 changed files with 84 additions and 36 deletions

View File

@@ -7,6 +7,7 @@ import {eval_frame} from './eval.js'
export const pp_calltree = tree => ({
id: tree.id,
ok: tree.ok,
value: tree.value,
is_log: tree.is_log,
has_more_children: tree.has_more_children,
string: tree.code?.string,

14
src/effects.js vendored
View File

@@ -177,7 +177,11 @@ export const render_common_side_effects = async (prev, next, command, ui) => {
load_external_imports(next)
}
if(prev.eval_modules_state != next.eval_modules_state) {
if(
prev.eval_modules_state != next.eval_modules_state
&&
next.eval_modules_state != null
) {
const s = next.eval_modules_state
s.promise.then(result => {
exec('eval_modules_finished', result, s.node, s.toplevel)
@@ -188,7 +192,13 @@ export const render_common_side_effects = async (prev, next, command, ui) => {
render_parse_result(ui, next)
}
if(!next.parse_result.ok || next.loading_external_imports_state != null) {
if(
!next.parse_result.ok
||
next.loading_external_imports_state != null
||
next.eval_modules_state != null
) {
// TODO if loading external imports, show loading indicator
ui.calltree.clear_calltree()

View File

@@ -260,16 +260,6 @@ 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,
@@ -955,6 +945,7 @@ const do_eval_frame_expr = (node, scope, callsleft) => {
ok = true
value = typeof(expr.result.value)
} else if(node.operator == '-') {
ok = true
value = - expr.result.value
} else if(node.operator == 'await') {
const run_window = globalThis.run_window ?? globalThis

View File

@@ -203,9 +203,20 @@ 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
)
Object.values(modules).some(m => node_has_toplevel_await(m))
const node_has_toplevel_await = node => {
if(node.type == 'unary' && node.operator == 'await') {
return true
}
if(node.type == 'function_expr') {
return false
}
if(node.children == null) {
return false
}
return node.children.find(c => node_has_toplevel_await(c)) != null
}
// TODO not implemented
// TODO detect cycles when loading modules

View File

@@ -13,11 +13,23 @@ export const patch_promise = window => {
(resolve, reject) => {
fn(
(value) => {
status = {ok: true, value}
if(is_constructor_finished) {
this.status = status
if(value instanceof window.Promise.Original) {
value
.then(v => {
this.status = {ok: true, value: v}
resolve(v)
})
.catch(e => {
this.status = {ok: false, error: e}
reject(e)
})
} else {
status = {ok: true, value}
if(is_constructor_finished) {
this.status = status
}
resolve(value)
}
resolve(value)
},
(error) => {
status = {ok: false, error}

View File

@@ -2600,7 +2600,7 @@ const y = x()`
)
}),
test('async/await await Promise', async () => {
test('async/await await resolved Promise', async () => {
await assert_code_evals_to_async(
`
await Promise.resolve(123)
@@ -2609,6 +2609,34 @@ const y = x()`
)
}),
test('async/await await Promise resolved with resolved Promise', async () => {
await assert_code_evals_to_async(
`
await Promise.resolve(Promise.resolve(123))
`,
123
)
}),
test('async/await await Promise resolved with async', async () => {
await assert_code_evals_to_async(
`
const x = async () => 1
await Promise.resolve(x())
`,
1
)
}),
test('async/await await Promise resolved with rejected Promise', async () => {
await assert_code_error_async(
`
await Promise.resolve(Promise.reject('boom'))
`,
'boom',
)
}),
test('async/await await Promise returned from async function', async () => {
await assert_code_evals_to_async(
`
@@ -2640,15 +2668,6 @@ const y = x()`
)
}),
test('async/await await rejected Promise', async () => {
await assert_code_error_async(
`
await Promise.reject('boom')
`,
'boom'
)
}),
test('async/await await rejected Promise returned from async', async () => {
await assert_code_error_async(
`
@@ -2659,10 +2678,14 @@ const y = x()`
)
}),
// TODO
//assert_equal('s', active_frame
//const result = await s.eval_modules_state
//const move = COMMANDS.move_cursor(s, code.indexOf('await x()')).state
//log('m', root_calltree_node(move).children[0].children[0].value)
//log(s.parse_result.modules[''])
test('async/await Promise.all', async () => {
await assert_code_evals_to_async(
`
const x = async i => i
await Promise.all([x(0), x(1), x(2)])
`,
[0,1,2]
)
}),
]

View File

@@ -1,6 +1,6 @@
import {parse, print_debug_node, load_modules} from '../src/parse_js.js'
import {eval_tree, eval_frame} from '../src/eval.js'
import {active_frame} from '../src/calltree.js'
import {active_frame, pp_calltree} from '../src/calltree.js'
import {COMMANDS} from '../src/cmd.js'
Object.assign(globalThis, {log: console.log})