MIRROR: javascript for 馃悳's, a tiny runtime with big ambitions
1function assertEq(actual, expected, message) {
2 if (actual !== expected) {
3 throw new Error(`${message}: expected ${expected}, got ${actual}`);
4 }
5}
6
7async function main() {
8 const trace = [];
9
10 async function leaf(label) {
11 const local = `leaf-${label}`;
12 trace.push(`leaf-before:${local}`);
13 const resumed = await new Promise((resolve) => setTimeout(() => resolve(label.toUpperCase()), 0));
14 trace.push(`leaf-after:${local}:${resumed}`);
15 return `${local}:${resumed}`;
16 }
17
18 async function middle(label) {
19 const local = `middle-${label}`;
20 trace.push(`middle-enter:${local}`);
21 try {
22 const value = await leaf(label);
23 trace.push(`middle-after:${local}:${value}`);
24 return `${local}:${value}`;
25 } finally {
26 trace.push(`middle-finally:${local}`);
27 }
28 }
29
30 async function top(label) {
31 const local = `top-${label}`;
32 trace.push(`top-enter:${local}`);
33 try {
34 const value = await middle(label);
35 trace.push(`top-after:${local}:${value}`);
36 return `${local}:${value}`;
37 } finally {
38 trace.push(`top-finally:${local}`);
39 await Promise.resolve(local);
40 trace.push(`top-finally-after-await:${local}`);
41 }
42 }
43
44 const result = await top('x');
45
46 assertEq(
47 result,
48 'top-x:middle-x:leaf-x:X',
49 'nested async result should preserve caller stack state'
50 );
51
52 assertEq(
53 trace.join(','),
54 [
55 'top-enter:top-x',
56 'middle-enter:middle-x',
57 'leaf-before:leaf-x',
58 'leaf-after:leaf-x:X',
59 'middle-after:middle-x:leaf-x:X',
60 'middle-finally:middle-x',
61 'top-after:top-x:middle-x:leaf-x:X',
62 'top-finally:top-x',
63 'top-finally-after-await:top-x',
64 ].join(','),
65 'materialized slice should preserve frames, handlers, and locals above the await'
66 );
67
68 console.log('nested async stack slice resumes with handlers and locals intact');
69}
70
71main().catch((err) => {
72 console.error(err && err.stack ? err.stack : String(err));
73 throw err;
74});