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.

var scope hoist

+172 -2
+1 -1
meson.build
··· 74 74 build_date = run_command('date', '+%Y-%m-%d', check: true).stdout().strip() 75 75 76 76 version_conf = configuration_data() 77 - version_conf.set('ANT_VERSION', '0.0.8.11') 77 + version_conf.set('ANT_VERSION', '0.0.8.12') 78 78 version_conf.set('ANT_GIT_HASH', git_hash) 79 79 version_conf.set('ANT_BUILD_DATE', build_date) 80 80
+66 -1
src/ant.c
··· 319 319 static jsval_t js_while(struct js *js); 320 320 static jsval_t js_do_while(struct js *js); 321 321 static jsval_t js_block_or_stmt(struct js *js); 322 + static jsval_t js_var_decl(struct js *js); 322 323 static bool parse_func_params(struct js *js, uint8_t *flags); 323 324 static jsval_t js_regex_literal(struct js *js); 324 325 static jsval_t js_try(struct js *js); ··· 5401 5402 bool is_for_of = false; 5402 5403 jsoff_t var_name_off = 0, var_name_len = 0; 5403 5404 bool is_const_var = false; 5405 + bool is_var_decl = false; 5404 5406 5405 5407 if (next(js) == TOK_LET || next(js) == TOK_CONST || next(js) == TOK_VAR) { 5406 5408 if (js->tok == TOK_VAR) { 5409 + is_var_decl = true; 5407 5410 if ((js->flags & F_STRICT) && !js->var_warning_shown) { 5408 5411 fprintf(stderr, "Warning: 'var' is deprecated, use 'let' or 'const' instead\n"); 5409 5412 js->var_warning_shown = true; ··· 5426 5429 js->consumed = 1; 5427 5430 if (is_const_var) { 5428 5431 v = js_const(js); 5432 + } else if (is_var_decl) { 5433 + v = js_var_decl(js); 5429 5434 } else { 5430 5435 v = js_let(js); 5431 5436 } ··· 6804 6809 } 6805 6810 } 6806 6811 6812 + static jsval_t find_var_scope(struct js *js) { 6813 + if ((js->flags & F_CALL) && global_scope_stack && utarray_len(global_scope_stack) > 0) { 6814 + jsoff_t *scope_off = (jsoff_t *)utarray_eltptr(global_scope_stack, 0); 6815 + if (scope_off && *scope_off != 0) return mkval(T_OBJ, *scope_off); 6816 + } 6817 + 6818 + jsval_t scope = js->scope; 6819 + while (vdata(upper(js, scope)) != 0) { 6820 + scope = upper(js, scope); 6821 + } 6822 + return scope; 6823 + } 6824 + 6825 + static jsval_t js_var_decl(struct js *js) { 6826 + uint8_t exe = !(js->flags & F_NOEXEC); 6827 + jsval_t var_scope = find_var_scope(js); 6828 + 6829 + js->consumed = 1; 6830 + for (;;) { 6831 + EXPECT(TOK_IDENTIFIER, ); 6832 + js->consumed = 0; 6833 + jsoff_t noff = js->toff, nlen = js->tlen; 6834 + char *name = (char *) &js->code[noff]; 6835 + 6836 + if (exe && (js->flags & F_STRICT) && is_strict_restricted(name, nlen)) { 6837 + return js_mkerr(js, "cannot use '%.*s' as variable name in strict mode", (int) nlen, name); 6838 + } 6839 + 6840 + if (exe && (js->flags & F_STRICT) && is_strict_reserved(name, nlen)) { 6841 + return js_mkerr(js, "'%.*s' is reserved in strict mode", (int) nlen, name); 6842 + } 6843 + 6844 + jsval_t v = js_mkundef(); 6845 + js->consumed = 1; 6846 + if (next(js) == TOK_ASSIGN) { 6847 + js->consumed = 1; 6848 + v = js_expr(js); 6849 + if (is_err(v)) return v; 6850 + } 6851 + 6852 + if (exe) { 6853 + jsoff_t existing_off = lkp(js, var_scope, name, nlen); 6854 + if (existing_off > 0) { 6855 + jsval_t key_val = js_mkstr(js, name, nlen); 6856 + if (!is_err(v) && vtype(v) != T_UNDEF) { 6857 + setprop(js, var_scope, key_val, resolveprop(js, v)); 6858 + } 6859 + } else { 6860 + jsval_t x = mkprop(js, var_scope, js_mkstr(js, name, nlen), resolveprop(js, v), false); 6861 + if (is_err(x)) return x; 6862 + } 6863 + } 6864 + 6865 + if (next(js) == TOK_SEMICOLON || next(js) == TOK_EOF) break; 6866 + EXPECT(TOK_COMMA, ); 6867 + } 6868 + return js_mkundef(); 6869 + } 6870 + 6807 6871 static void js_var(struct js *js, jsval_t *res) { 6808 6872 if ((js->flags & F_STRICT) && !js->var_warning_shown) { 6809 6873 fprintf(stderr, "Warning: 'var' is deprecated, use 'let' or 'const' instead\n"); 6810 6874 js->var_warning_shown = true; 6811 6875 } 6812 - *res = js_let(js); 6876 + 6877 + *res = js_var_decl(js); 6813 6878 } 6814 6879 6815 6880 static void js_async(struct js *js, jsval_t *res) {
stupid.js tests/with.js
+8
tests/ack.js
··· 1 + function ack(i, j) { 2 + console.log('ack(' + i + ', ' + j + ')'); 3 + if (i == 0) return j + 1; 4 + if (j == 0) return ack(i - 1, 1); 5 + return ack(i - 1, ack(i, j - 1)); 6 + } 7 + 8 + console.log(ack(3, 3));
+97
tests/test_var_hoisting.cjs
··· 1 + // Test var hoisting behavior 2 + // In JavaScript, 'var' declarations are hoisted to the function scope (or global scope) 3 + // regardless of where they are declared within blocks 4 + 5 + console.log("=== Test 1: Basic var hoisting in blocks ==="); 6 + { 7 + var x = 10; 8 + } 9 + console.log("x should be 10:", x); 10 + 11 + console.log("\n=== Test 2: var in nested blocks ==="); 12 + { 13 + { 14 + { 15 + var y = 20; 16 + } 17 + } 18 + } 19 + console.log("y should be 20:", y); 20 + 21 + console.log("\n=== Test 3: var in if blocks ==="); 22 + if (true) { 23 + var z = 30; 24 + } 25 + console.log("z should be 30:", z); 26 + 27 + console.log("\n=== Test 4: var in function scope ==="); 28 + function testFunc() { 29 + { 30 + var a = 40; 31 + } 32 + return a; 33 + } 34 + console.log("a inside function should be 40:", testFunc()); 35 + 36 + console.log("\n=== Test 5: var in for loop ==="); 37 + for (var i = 0; i < 3; i++) { 38 + // loop body 39 + } 40 + console.log("i should be 3:", i); 41 + 42 + console.log("\n=== Test 6: var in with statement ==="); 43 + var obj = { prop: 100 }; 44 + with (obj) { 45 + var w = 50; 46 + } 47 + console.log("w should be 50:", w); 48 + 49 + console.log("\n=== Test 7: Multiple var declarations in different blocks ==="); 50 + { 51 + var m = 1; 52 + } 53 + { 54 + var n = 2; 55 + } 56 + console.log("m should be 1, n should be 2:", m, n); 57 + 58 + console.log("\n=== Test 8: var reassignment across blocks ==="); 59 + { 60 + var p = 100; 61 + } 62 + { 63 + p = 200; 64 + } 65 + console.log("p should be 200:", p); 66 + 67 + console.log("\n=== Test 9: var in while loop ==="); 68 + var count = 0; 69 + while (count < 2) { 70 + var q = count; 71 + count++; 72 + } 73 + console.log("q should be 1:", q); 74 + 75 + console.log("\n=== Test 10: Function scope isolation ==="); 76 + function outer() { 77 + { 78 + var funcVar = 77; 79 + } 80 + return funcVar; 81 + } 82 + console.log("funcVar inside function should be 77:", outer()); 83 + // funcVar should not be accessible here (would be undefined in global scope) 84 + 85 + console.log("\n=== Test 11: var vs let comparison ==="); 86 + { 87 + var varTest = "var-value"; 88 + let letTest = "let-value"; 89 + } 90 + console.log("varTest should be 'var-value':", varTest); 91 + try { 92 + console.log("letTest should cause error:", letTest); 93 + } catch (e) { 94 + console.log("letTest correctly not accessible (block-scoped)"); 95 + } 96 + 97 + console.log("\n=== All var hoisting tests completed ===");