mirror of
https://github.com/leporello-js/leporello-js
synced 2026-01-13 13:04:30 -08:00
WIP
This commit is contained in:
@@ -276,6 +276,11 @@ export const eval_modules = (
|
|||||||
const codestring =
|
const codestring =
|
||||||
`
|
`
|
||||||
let children, prev_children
|
let children, prev_children
|
||||||
|
|
||||||
|
// TODO refactor, move patch_promise here
|
||||||
|
globalThis.get_children = () => children
|
||||||
|
globalThis.set_children = (_children) => children = _children
|
||||||
|
|
||||||
// TODO use native array for stack for perf?
|
// TODO use native array for stack for perf?
|
||||||
const stack = new Array()
|
const stack = new Array()
|
||||||
|
|
||||||
|
|||||||
@@ -5,11 +5,36 @@ export const patch_promise = window => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class PromiseRecordChildren extends Promise {
|
||||||
|
then(on_resolve, on_reject) {
|
||||||
|
let children = window.get_children()
|
||||||
|
if(children == null) {
|
||||||
|
children = []
|
||||||
|
window.set_children(children)
|
||||||
|
}
|
||||||
|
return super.then(
|
||||||
|
on_resolve == null
|
||||||
|
? null
|
||||||
|
: value => {
|
||||||
|
window.set_children(children)
|
||||||
|
return on_resolve(value)
|
||||||
|
},
|
||||||
|
|
||||||
|
on_reject == null
|
||||||
|
? null
|
||||||
|
: error => {
|
||||||
|
window.set_children(children)
|
||||||
|
return on_reject(error)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class PromiseWithStatus extends window.Promise {
|
class PromiseWithStatus extends window.Promise {
|
||||||
constructor(fn) {
|
constructor(fn) {
|
||||||
let status
|
let status
|
||||||
let is_constructor_finished = false
|
let is_constructor_finished = false
|
||||||
const p = new window.Promise.Original(
|
const p = new PromiseRecordChildren(
|
||||||
(resolve, reject) => {
|
(resolve, reject) => {
|
||||||
fn(
|
fn(
|
||||||
(value) => {
|
(value) => {
|
||||||
|
|||||||
@@ -3,7 +3,9 @@
|
|||||||
export const reserved = [
|
export const reserved = [
|
||||||
'break',
|
'break',
|
||||||
'case',
|
'case',
|
||||||
'catch',
|
// TODO: fix parser to allow catch be an Object key, as other reserved words.
|
||||||
|
// Currently we make exception for promise.catch
|
||||||
|
// 'catch',
|
||||||
'class',
|
'class',
|
||||||
'const',
|
'const',
|
||||||
'continue',
|
'continue',
|
||||||
@@ -14,7 +16,9 @@ export const reserved = [
|
|||||||
'else',
|
'else',
|
||||||
'export',
|
'export',
|
||||||
'extends',
|
'extends',
|
||||||
'finally',
|
// TODO: fix parser to allow finally be an Object key, as other reserved words.
|
||||||
|
// Currently we make exception for promise.finally
|
||||||
|
// 'finally',
|
||||||
'for',
|
'for',
|
||||||
'function',
|
'function',
|
||||||
'if',
|
'if',
|
||||||
|
|||||||
@@ -67,10 +67,8 @@ const dir = load_dir('.')
|
|||||||
console.time('run')
|
console.time('run')
|
||||||
|
|
||||||
const i = test_initial_state(
|
const i = test_initial_state(
|
||||||
`
|
{}, // files
|
||||||
import './test/run.js'
|
{project_dir: dir, entrypoint: 'test/run.js'}
|
||||||
`,
|
|
||||||
{project_dir: dir}
|
|
||||||
)
|
)
|
||||||
assert_equal(i.loading_external_imports_state != null, true)
|
assert_equal(i.loading_external_imports_state != null, true)
|
||||||
|
|
||||||
@@ -81,6 +79,8 @@ assert_equal(loaded.eval_modules_state != null, true)
|
|||||||
const s = loaded.eval_modules_state
|
const s = loaded.eval_modules_state
|
||||||
const result = await s.promise
|
const result = await s.promise
|
||||||
const state = COMMANDS.eval_modules_finished(loaded , result, s.node, s.toplevel)
|
const state = COMMANDS.eval_modules_finished(loaded , result, s.node, s.toplevel)
|
||||||
|
const root = root_calltree_node(state)
|
||||||
|
const run = root.children[0]
|
||||||
|
|
||||||
assert_equal(root_calltree_node(state).ok, true)
|
assert_equal(root_calltree_node(state).ok, true)
|
||||||
|
|
||||||
|
|||||||
34
test/test.js
34
test/test.js
@@ -2779,18 +2779,38 @@ const y = x()`
|
|||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// TODO
|
|
||||||
/*
|
|
||||||
test('async/await Promise.then creates subcall', async () => {
|
test('async/await Promise.then creates subcall', async () => {
|
||||||
const i = await test_initial_state_async(`
|
const i = await test_initial_state_async(`
|
||||||
await Promise.resolve(1).then(x => {
|
const x = () => 1
|
||||||
})
|
await Promise.resolve(1).then(x)
|
||||||
`)
|
`)
|
||||||
console.log('i', root_calltree_node(i))
|
const root = root_calltree_node(i)
|
||||||
|
assert_equal(root.children.at(-1).children[0].fn.name, 'x')
|
||||||
}),
|
}),
|
||||||
|
|
||||||
test('async/await bug', async () => {
|
test('async/await Promise.catch creates subcall', async () => {
|
||||||
|
const i = await test_initial_state_async(`
|
||||||
|
const x = () => 1
|
||||||
|
await Promise.reject(1).catch(x)
|
||||||
|
`)
|
||||||
|
const root = root_calltree_node(i)
|
||||||
|
assert_equal(root.children.at(-1).children[0].fn.name, 'x')
|
||||||
|
}),
|
||||||
|
|
||||||
|
|
||||||
|
test_only('async/await native Promise.then creates subcall', async () => {
|
||||||
|
const i = await test_initial_state_async(`
|
||||||
|
const x = () => 1
|
||||||
|
const async_fn = async () => 1
|
||||||
|
await async_fn().then(x)
|
||||||
|
`)
|
||||||
|
const root = root_calltree_node(i)
|
||||||
|
assert_equal(root.children.at(-1).children[0].fn.name, 'x')
|
||||||
|
}),
|
||||||
|
|
||||||
|
/*
|
||||||
|
// TODO
|
||||||
|
test('async/await move_cursor', async () => {
|
||||||
const code = `
|
const code = `
|
||||||
const f = async () => {
|
const f = async () => {
|
||||||
console.log('f')
|
console.log('f')
|
||||||
|
|||||||
@@ -151,21 +151,20 @@ export const test_only = (message, t) => test(message, t, true)
|
|||||||
// TODO in calltree view, hide fn which has special flag set (see
|
// TODO in calltree view, hide fn which has special flag set (see
|
||||||
// filter_calltree)
|
// filter_calltree)
|
||||||
|
|
||||||
const AsyncFunction = new Function(`return (async () => {}).constructor`)()
|
export const run = Object.defineProperty(new Function('tests', `
|
||||||
|
// Runs test, return failure or null if not failed
|
||||||
export const run = Object.defineProperty(new AsyncFunction('tests', `
|
const run_test = t => {
|
||||||
const run_test = async t => {
|
return Promise.resolve(t.test())
|
||||||
try {
|
.then(() => null)
|
||||||
await t.test()
|
.catch(e => {
|
||||||
} catch(e) {
|
if(globalThis.process != null) {
|
||||||
if(globalThis.process != null) {
|
// In node.js runner, fail fast
|
||||||
// In node.js runner, fail fast
|
console.error('Failed: ' + t.message)
|
||||||
console.error('Failed: ' + t.message)
|
throw e
|
||||||
throw e
|
} else {
|
||||||
} else {
|
return e
|
||||||
return e
|
}
|
||||||
}
|
})
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If not run in node, then dont apply filter
|
// If not run in node, then dont apply filter
|
||||||
@@ -178,32 +177,35 @@ export const run = Object.defineProperty(new AsyncFunction('tests', `
|
|||||||
|
|
||||||
// Exec each test. After all tests are done, we rethrow first error 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
|
// any. So we will mark root calltree node if one of tests failed
|
||||||
const failure = await tests_to_run.reduce(
|
return tests_to_run.reduce(
|
||||||
async (failureP, t) => {
|
(failureP, t) =>
|
||||||
const failure = await failureP
|
Promise.resolve(failureP).then(failure =>
|
||||||
const next_failure = await run_test(t)
|
run_test(t).then(next_failure => failure ?? next_failure)
|
||||||
return failure ?? next_failure
|
)
|
||||||
},
|
,
|
||||||
null
|
null
|
||||||
)
|
).then(failure => {
|
||||||
|
|
||||||
if(failure != null) {
|
if(failure != null) {
|
||||||
throw failure
|
throw failure
|
||||||
} else {
|
} else {
|
||||||
if(globalThis.process != null) {
|
if(globalThis.process != null) {
|
||||||
console.log('Ok')
|
console.log('Ok')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
})
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
const test = tests.find(t => t.message.includes(filter))
|
const test = tests.find(t => t.message.includes(filter))
|
||||||
if(test == null) {
|
if(test == null) {
|
||||||
throw new Error('test not found')
|
throw new Error('test not found')
|
||||||
} else {
|
} else {
|
||||||
await run_test(test)
|
return run_test(test).then(() => {
|
||||||
if(globalThis.process != null) {
|
if(globalThis.process != null) {
|
||||||
console.log('Ok')
|
console.log('Ok')
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`), 'name', {value: 'run'})
|
`), 'name', {value: 'run'})
|
||||||
|
|||||||
Reference in New Issue
Block a user