From f9d68b29903a6a74180497d1d3bb1b3803415028 Mon Sep 17 00:00:00 2001 From: John Alanbrook Date: Fri, 6 Feb 2026 03:54:25 -0600 Subject: [PATCH] fix if/else, chained assignment --- source/quickjs.c | 31 ++++++++++++++++++++++++++----- vm_test/label_break.txt | 1 - vm_test/op_typeof.txt | 1 - vm_test/switch_basic.txt | 1 - 4 files changed, 26 insertions(+), 8 deletions(-) delete mode 100644 vm_test/label_break.txt delete mode 100644 vm_test/op_typeof.txt delete mode 100644 vm_test/switch_basic.txt diff --git a/source/quickjs.c b/source/quickjs.c index a1419420..2a4b4ac0 100644 --- a/source/quickjs.c +++ b/source/quickjs.c @@ -9434,7 +9434,8 @@ static int js_parse_expect (JSParseState *s, int tok) { static int js_parse_expect_semi (JSParseState *s) { if (s->token.val != ';') { /* automatic insertion of ';' */ - if (s->token.val == TOK_EOF || s->token.val == '}' || s->got_lf) { + if (s->token.val == TOK_EOF || s->token.val == '}' || s->got_lf + || s->token.val == TOK_ELSE) { return 0; } return js_parse_error (s, "expecting '%c'", ';'); @@ -29500,7 +29501,8 @@ static cJSON *ast_parse_arrow_function (ASTParseState *s) { static void ast_expect_semi (ASTParseState *s) { if (s->token_val == ';') { ast_next_token (s); return; } - if (s->token_val == TOK_EOF || s->token_val == '}' || s->got_lf) return; + if (s->token_val == TOK_EOF || s->token_val == '}' || s->got_lf + || s->token_val == TOK_ELSE) return; ast_error (s, s->token_ptr, "expecting ';'"); } @@ -29551,7 +29553,9 @@ static cJSON *ast_parse_statement (ASTParseState *s) { return NULL; } - /* Can have multiple declarations */ + /* Can have multiple declarations: var x = 1, y = 2 */ + cJSON *decls = cJSON_CreateArray (); + int decl_count = 0; while (s->token_val == TOK_IDENT) { const uint8_t *var_ptr = s->token_ptr; node = ast_node (s, kind_name, start); @@ -29564,7 +29568,7 @@ static cJSON *ast_parse_statement (ASTParseState *s) { if (s->token_val == '=') { ast_next_token (s); - cJSON *right = ast_parse_expr (s); + cJSON *right = ast_parse_assign_expr (s); cJSON_AddItemToObject (node, "right", right); const char *right_kind = cJSON_GetStringValue (cJSON_GetObjectItem (right, "kind")); if (right_kind && strcmp (right_kind, "[") == 0 && !cJSON_GetObjectItem (right, "right")) @@ -29575,15 +29579,24 @@ static cJSON *ast_parse_statement (ASTParseState *s) { } JS_FreeCString (s->ctx, str); ast_node_end (s, node, s->buf_ptr); + cJSON_AddItemToArray (decls, node); + decl_count++; if (s->token_val == ',') { ast_next_token (s); - /* For multiple vars, we'd need to return an array - simplified here */ } else { break; } } ast_expect_semi (s); + if (decl_count == 1) { + node = cJSON_DetachItemFromArray (decls, 0); + cJSON_Delete (decls); + } else { + node = ast_node (s, "var_list", start); + cJSON_AddItemToObject (node, "list", decls); + ast_node_end (s, node, s->buf_ptr); + } } break; case TOK_IF: { @@ -30223,6 +30236,14 @@ static void ast_sem_check_stmt (ASTSemState *st, ASTSemScope *scope, cJSON *stmt const char *kind = cJSON_GetStringValue (cJSON_GetObjectItem (stmt, "kind")); if (!kind) return; + if (strcmp (kind, "var_list") == 0) { + cJSON *item; + cJSON_ArrayForEach (item, cJSON_GetObjectItem (stmt, "list")) { + ast_sem_check_stmt (st, scope, item); + } + return; + } + if (strcmp (kind, "var") == 0) { /* Register variable */ cJSON *left = cJSON_GetObjectItem (stmt, "left"); diff --git a/vm_test/label_break.txt b/vm_test/label_break.txt deleted file mode 100644 index cddbae9b..00000000 --- a/vm_test/label_break.txt +++ /dev/null @@ -1 +0,0 @@ -var x = 0; outer: { x = 1; break outer; x = 2 }; x diff --git a/vm_test/op_typeof.txt b/vm_test/op_typeof.txt deleted file mode 100644 index 6eea91be..00000000 --- a/vm_test/op_typeof.txt +++ /dev/null @@ -1 +0,0 @@ -typeof 5 diff --git a/vm_test/switch_basic.txt b/vm_test/switch_basic.txt deleted file mode 100644 index 172b8c91..00000000 --- a/vm_test/switch_basic.txt +++ /dev/null @@ -1 +0,0 @@ -var r; switch(2) { case 1: r = 1; break; case 2: r = 2; break }; r