MIRROR: javascript for ๐Ÿœ's, a tiny runtime with big ambitions
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

add body end token check for arrow functions

+141 -17
+125
examples/spec/arrow.js
··· 1 + import { test, summary } from './helpers.js'; 2 + 3 + console.log('Arrow Function Tests\n'); 4 + 5 + const basic = (a, b) => a + b; 6 + test('basic arrow function', basic(2, 3), 5); 7 + 8 + const single = x => x * 2; 9 + test('arrow single param no parens', single(5), 10); 10 + 11 + const singleParen = x => x * 3; 12 + test('arrow single param with parens', singleParen(4), 12); 13 + 14 + const noParams = () => 42; 15 + test('arrow no params', noParams(), 42); 16 + 17 + const implicit = (a, b) => a - b; 18 + test('arrow implicit return', implicit(10, 3), 7); 19 + 20 + const block = (a, b) => { 21 + const sum = a + b; 22 + return sum * 2; 23 + }; 24 + test('arrow block body', block(2, 3), 10); 25 + 26 + const withDefault = (a, b = 10) => a + b; 27 + test('arrow default param used', withDefault(5), 15); 28 + test('arrow default param overridden', withDefault(5, 3), 8); 29 + 30 + const defaultExpr = (x = 5 * 2) => x + 1; 31 + test('arrow default param expression', defaultExpr(), 11); 32 + test('arrow default param override expr', defaultExpr(7), 8); 33 + 34 + const multiDefault = (a = 1, b = 2, c = 3) => a + b + c; 35 + test('arrow multiple defaults all used', multiDefault(), 6); 36 + test('arrow multiple defaults partial', multiDefault(10), 15); 37 + test('arrow multiple defaults override all', multiDefault(10, 20, 30), 60); 38 + 39 + const defaultCall = (x = Math.random()) => x >= 0 && x <= 1; 40 + test('arrow default with call', defaultCall(), true); 41 + 42 + const assignmentDefault = (u = 42) => u * 2; 43 + test('arrow assignment in default', assignmentDefault(), 84); 44 + 45 + const parenDefault = (x = 5) => x + 1; 46 + test('arrow parenthesized default', parenDefault(), 6); 47 + 48 + const complexDefault = (x = (2 + 3) * 4) => x; 49 + test('arrow complex expression default', complexDefault(), 20); 50 + 51 + const rest = (first, ...others) => first + others.length; 52 + test('arrow rest params', rest(1, 2, 3, 4), 4); 53 + 54 + const restWithDefault = (a = 10, ...rest) => a + rest.length; 55 + test('arrow rest with default', restWithDefault(5, 1, 2), 7); 56 + 57 + const objReturn = (a, b) => ({ x: a, y: b }); 58 + test('arrow object return x', objReturn(1, 2).x, 1); 59 + test('arrow object return y', objReturn(1, 2).y, 2); 60 + 61 + const add = x => y => x + y; 62 + test('arrow currying', add(5)(3), 8); 63 + 64 + const fns = [x => x, x => x * 2, x => x * 3]; 65 + test('arrow in array [0]', fns[0](5), 5); 66 + test('arrow in array [1]', fns[1](5), 10); 67 + test('arrow in array [2]', fns[2](5), 15); 68 + 69 + const obj = { 70 + double: x => x * 2, 71 + triple: x => x * 3 72 + }; 73 + test('arrow in object double', obj.double(5), 10); 74 + test('arrow in object triple', obj.triple(5), 15); 75 + 76 + const context = { 77 + value: 100, 78 + getValue: function () { 79 + return (() => this.value)(); 80 + } 81 + }; 82 + test('arrow this binding', context.getValue(), 100); 83 + 84 + const mapped = [1, 2, 3].map(x => x * 2); 85 + test('arrow in map [0]', mapped[0], 2); 86 + test('arrow in map [1]', mapped[1], 4); 87 + test('arrow in map [2]', mapped[2], 6); 88 + 89 + const filtered = [1, 2, 3, 4, 5].filter(x => x > 2); 90 + test('arrow in filter length', filtered.length, 3); 91 + test('arrow in filter [0]', filtered[0], 3); 92 + 93 + const sum = [1, 2, 3, 4].reduce((acc, x) => acc + x, 0); 94 + test('arrow in reduce', sum, 10); 95 + 96 + const iife = (x => x * 2)(5); 97 + test('arrow iife', iife, 10); 98 + 99 + const iifeTwoLevel = ((u = 10) => u * 2)(); 100 + test('arrow iife with default', iifeTwoLevel, 20); 101 + 102 + const nested = a => b => c => a + b + c; 103 + test('arrow nested 1', nested(1)(2)(3), 6); 104 + 105 + const conditional = x => (x > 0 ? x : -x); 106 + test('arrow conditional positive', conditional(5), 5); 107 + test('arrow conditional negative', conditional(-5), 5); 108 + 109 + const logical = (a, b) => (a && b ? a + b : 0); 110 + test('arrow logical true', logical(3, 4), 7); 111 + test('arrow logical false', logical(0, 4), 0); 112 + 113 + const template = name => `Hello, ${name}!`; 114 + test('arrow template literal', template('World'), 'Hello, World!'); 115 + 116 + const makeMultiplier = n => x => x * n; 117 + const double = makeMultiplier(2); 118 + const triple = makeMultiplier(3); 119 + test('arrow returning arrow double', double(5), 10); 120 + test('arrow returning arrow triple', triple(5), 15); 121 + 122 + const spreadArrow = (a, b, c) => a + b + c; 123 + test('arrow with spread call', spreadArrow(...[1, 2, 3]), 6); 124 + 125 + summary();
+1 -1
meson.build
··· 96 96 build_date = run_command('date', '+%Y-%m-%d', check: true).stdout().strip() 97 97 98 98 version_conf = configuration_data() 99 - version_conf.set('ANT_VERSION', '0.3.2.34') 99 + version_conf.set('ANT_VERSION', '0.3.2.36') 100 100 version_conf.set('ANT_GIT_HASH', git_hash) 101 101 version_conf.set('ANT_BUILD_DATE', build_date) 102 102
+15 -16
src/ant.c
··· 667 667 return tok >= TOK_IDENTIFIER && tok < TOK_IDENT_LIKE_END; 668 668 } 669 669 670 + static inline int is_body_end_tok(int tok) { 671 + return tok == TOK_RPAREN || tok == TOK_RBRACE || tok == TOK_SEMICOLON || tok == TOK_COMMA || tok == TOK_EOF; 672 + } 673 + 670 674 static bool is_keyword_propname(uint8_t tok) { 671 675 return (tok >= TOK_ASYNC && tok <= TOK_GLOBAL_THIS) || tok == TOK_TYPEOF; 672 676 } ··· 680 684 681 685 static bool is_valid_arrow_param_tok(uint8_t tok) { 682 686 static const uint64_t bits[4] = { 683 - 0x0004000000000F0Cull, 684 - 0x001CC01003C00000ull, 687 + 0x0004000000000FCCull, 688 + 0x041CC01003C00000ull, 685 689 0x0000000000800100ull, 686 690 0x0000000000000000ull 687 691 }; ··· 7989 7993 return body_result; 7990 7994 } 7991 7995 uint8_t tok = next(js); 7992 - if (tok == TOK_RPAREN || tok == TOK_RBRACE || tok == TOK_SEMICOLON || 7993 - tok == TOK_COMMA || tok == TOK_EOF) { 7994 - body_end_actual = js->toff; 7995 - } else { 7996 - body_end_actual = js->pos; 7997 - } 7996 + body_end_actual = is_body_end_tok(tok) ? js->toff : js->pos; 7998 7997 } else { 7999 7998 body_start = js->toff; 8000 7999 js->flags |= F_NOEXEC; ··· 8096 8095 8097 8096 if (is_arrow) { 8098 8097 js->flags |= F_NOEXEC; 8099 - while (next(js) != TOK_RPAREN && next(js) != TOK_EOF) js->consumed = 1; 8098 + int skip_paren_depth = 1; 8099 + while (skip_paren_depth > 0 && next(js) != TOK_EOF) { 8100 + if (js->tok == TOK_LPAREN) skip_paren_depth++; 8101 + else if (js->tok == TOK_RPAREN) skip_paren_depth--; 8102 + if (skip_paren_depth > 0) js->consumed = 1; 8103 + } 8100 8104 8101 8105 if (next(js) != TOK_RPAREN) { 8102 8106 js->parse_depth--; ··· 8805 8809 jsoff_t body_end; 8806 8810 if (is_expr) { 8807 8811 uint8_t tok = next(js); 8808 - if (tok == TOK_RPAREN || tok == TOK_RBRACE || tok == TOK_SEMICOLON || 8809 - tok == TOK_COMMA || tok == TOK_EOF) { 8810 - body_end = js->toff; 8811 - } else body_end = js->pos; 8812 - } else { 8813 - body_end = js->pos; 8814 - } 8812 + body_end = is_body_end_tok(tok) ? js->toff : js->pos; 8813 + } else body_end = js->pos; 8815 8814 8816 8815 size_t fn_size = param_len + (body_end - body_start) + 64; 8817 8816 char *fn_str = (char *) malloc(fn_size);