This commit is contained in:
Dmitry Vasilev
2022-12-07 05:06:15 +08:00
parent 9e9400ab24
commit 707c34bc66
8 changed files with 178 additions and 49 deletions

View File

@@ -15,10 +15,10 @@ import {
test_only,
assert_equal,
stringify,
assert_code_evals_to,
assert_code_error,
assert_code_evals_to, assert_code_evals_to_async,
assert_code_error, assert_code_error_async,
parse_modules,
test_initial_state,
test_initial_state, test_initial_state_async,
test_deferred_calls_state,
print_debug_ct_node,
} from './utils.js'
@@ -2589,15 +2589,80 @@ const y = x()`
assert_equal(get_deferred_calls(result), null)
}),
test('async/await', () => {
const code = `
const x = async () => 123
const y = async () => await x()
await y()
`
const s = test_initial_state(code)
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 return from async function', async () => {
await assert_code_evals_to_async(
`
const x = async () => 123
const y = async () => await x()
await y()
`,
123
)
}),
test('async/await await Promise', async () => {
await assert_code_evals_to_async(
`
await Promise.resolve(123)
`,
123
)
}),
test('async/await await Promise returned from async function', async () => {
await assert_code_evals_to_async(
`
const x = async () => {
return Promise.resolve(123)
}
await x()
`,
123
)
}),
test('async/await throw from async function', async () => {
await assert_code_error_async(
`
const x = async () => { throw 'boom' }
await x()
`,
'boom'
)
}),
test('async/await await rejected Promise', async () => {
await assert_code_error_async(
`
await Promise.reject('boom')
`,
'boom'
)
}),
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(
`
const x = async () => Promise.reject('boom')
await x()
`,
'boom'
)
}),
// 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[''])
]

View File

@@ -1,12 +1,8 @@
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 {COMMANDS} from '../src/cmd.js'
// external
import {patch_promise} from '../src/patch_promise.js'
patch_promise(globalThis)
Object.assign(globalThis, {log: console.log})
export const parse_modules = (entry, modules) =>
@@ -32,6 +28,22 @@ export const assert_code_error = (codestring, error) => {
assert_equal(result.error, error)
}
export const assert_code_evals_to_async = async (codestring, expected) => {
const s = await test_initial_state_async(codestring)
const frame = active_frame(s)
const result = frame.children[frame.children.length - 1].result
assert_equal(result.ok, true)
assert_equal(result.value, expected)
}
export const assert_code_error_async = async (codestring, error) => {
const s = await test_initial_state_async(codestring)
const frame = active_frame(s)
const result = frame.children[frame.children.length - 1].result
assert_equal(result.ok, false)
assert_equal(result.error, error)
}
export const test_initial_state = (code, state) => {
return COMMANDS.open_run_window(
COMMANDS.get_initial_state(
@@ -45,6 +57,18 @@ export const test_initial_state = (code, state) => {
)
}
export const test_initial_state_async = async code => {
const s = test_initial_state(code)
assert_equal(s.eval_modules_state != null, true)
const result = await s.eval_modules_state.promise
return COMMANDS.eval_modules_finished(
s,
result,
s.eval_modules_state.node,
s.eval_modules_state.toplevel
)
}
export const test_deferred_calls_state = code => {
const {get_deferred_call, on_deferred_call} = (new Function(`
let call, calltree_changed_token
@@ -119,10 +143,13 @@ export const test_only = (message, t) => test(message, t, true)
// Wrap to Function constructor to hide from calltree view
// TODO in calltree view, hide fn which has special flag set (see
// filter_calltree)
export const run = Object.defineProperty(new Function('tests', `
const run_test = t => {
const AsyncFunction = new Function(`return (async () => {}).constructor`)()
export const run = Object.defineProperty(new AsyncFunction('tests', `
const run_test = async t => {
try {
t.test()
await t.test()
} catch(e) {
if(globalThis.process != null) {
// In node.js runner, fail fast
@@ -142,12 +169,13 @@ export const run = Object.defineProperty(new Function('tests', `
const only = tests.find(t => t.only)
const tests_to_run = only == null ? tests : [only]
// Exec each test. After all tests are done, we rethrow first failer if
// Exec each test. After all tests are done, we rethrow first error if
// any. So we will mark root calltree node if one of tests failed
const failure = tests_to_run.reduce(
(failure, t) => {
const next_failure = run_test(t)
return failure ?? next_failure
const failure = await tests_to_run.reduce(
async (failureP, t) => {
const failure = await failureP
const next_failure = await run_test(t)
return (await failure) ?? next_failure
},
null
)
@@ -165,7 +193,7 @@ export const run = Object.defineProperty(new Function('tests', `
if(test == null) {
throw new Error('test not found')
} else {
run_test(test)
await run_test(test)
if(globalThis.process != null) {
console.log('Ok')
}