MIRROR: javascript for 馃悳's, a tiny runtime with big ambitions
1import { test, testDeep, testThrows, summary } from './helpers.js';
2
3console.log('Completion Value Tests\n');
4
5test('empty blocks produce undefined', eval('{}{}{};'), undefined);
6test('label inside block completion', eval("{foo: 'bar'}{};"), 'bar');
7test('block before labelled completion', eval("{}{foo: 'bar'};"), 'bar');
8test('last non-empty block completion', eval("{a: 'b'}{c: 'd'}{};"), 'd');
9
10test('nested label passes expression completion', eval('a: b: c: 1;'), 1);
11test('nested label passes comma expression completion', eval('a: b: c: (1, 2, 3);'), 3);
12
13test('statement-position braces parse as block label', eval('{ a: 1 }'), 1);
14test('multiple labels in block preserve last completion', eval('{ a: 1; b: 2 }'), 2);
15testDeep('parenthesized braces parse as object literal', eval('({ a: 1, b: 2 })'), { a: 1, b: 2 });
16testThrows('comma cannot separate labelled statements', () => eval('{ a: 1, b: 2 }'));
17
18test('declaration empty completion preserves previous value', eval("'a'; var x = 5;"), 'a');
19test('if true carries body completion', eval("if (true) 'a';"), 'a');
20test('if false has empty completion', eval("if (false) 'a';"), undefined);
21test('if false overwrites previous expression with undefined', eval("'a'; if (false) 'b';"), undefined);
22test('if true empty body overwrites previous expression with undefined', eval("'a'; if (true) ;"), undefined);
23test('for loop completion is last body value', eval('for (let i=0;i<3;i++) i;'), 2);
24test('while false overwrites previous expression with undefined', eval("'a'; while (false) 'b';"), undefined);
25test('for false overwrites previous expression with undefined', eval("'a'; for (;false;) 'b';"), undefined);
26test('for empty body overwrites previous expression with undefined', eval("'a'; for (let i=0;i<1;i++);"), undefined);
27test('do while empty body overwrites previous expression with undefined', eval("'a'; do ; while(false);"), undefined);
28test('with empty body overwrites previous expression with undefined', eval("'a'; with ({}) ;"), undefined);
29
30test('empty finally preserves try completion', eval("try { 'a' } finally { }"), 'a');
31test('non-empty finally overrides try completion', eval("try { 'a' } finally { 'b' }"), 'b');
32test('empty try finally overwrites previous expression with undefined', eval("'a'; try { } finally { }"), undefined);
33
34test('break label preserves previous non-empty completion', eval("outer: { 'before'; break outer; 'after'; }"), 'before');
35test('nested block completion flows outward', eval("outer: { { 'inner'; } ; }"), 'inner');
36test('empty block after expression preserves value', eval("'a'; { var x; }"), 'a');
37
38test('switch fallthrough preserves last non-empty case value', eval("switch (1) { case 0: 'zero'; case 1: 'one'; case 2: ; }"), 'one');
39test('switch with no matching case is empty', eval("switch (9) { case 0: 'zero'; }"), undefined);
40test('switch with no matching case overwrites previous expression with undefined', eval("'a'; switch (9) { case 0: 'zero'; }"), undefined);
41test('switch default fallthrough can be overwritten', eval("switch (2) { case 1: 'one'; default: 'default'; case 2: 'two'; }"), 'two');
42
43test('function block body ignores completion value', eval("(function(){ 'block'; })()"), undefined);
44test('arrow block body ignores completion value', eval("(()=>{ 'block'; })()"), undefined);
45test('arrow expression body returns expression value', eval("(()=> 'expr')()"), 'expr');
46
47summary();