fix parser

This commit is contained in:
2026-02-03 18:24:06 -06:00
parent dc3c474b3a
commit 04c569eab1

View File

@@ -5112,21 +5112,23 @@ static int JS_CheckDefineGlobalVar (JSContext *ctx, JSValue prop, int flags) {
Currently safe because rec_resize always fails. Currently safe because rec_resize always fails.
def_flags is (0, DEFINE_GLOBAL_LEX_VAR) */ def_flags is (0, DEFINE_GLOBAL_LEX_VAR) */
static int JS_DefineGlobalVar (JSContext *ctx, JSValue prop, int def_flags) { static int JS_DefineGlobalVar (JSContext *ctx, JSValue prop, int def_flags) {
JSRecord *rec; JSValue *pobj;
JSValue val; JSValue val;
JSRecord *rec;
int slot; int slot;
if (def_flags & DEFINE_GLOBAL_LEX_VAR) { if (def_flags & DEFINE_GLOBAL_LEX_VAR) {
rec = (JSRecord *)JS_VALUE_GET_OBJ (ctx->global_var_obj); pobj = &ctx->global_var_obj;
val = JS_UNINITIALIZED; val = JS_UNINITIALIZED;
} else { } else {
rec = (JSRecord *)JS_VALUE_GET_OBJ (ctx->global_obj); pobj = &ctx->global_obj;
val = JS_NULL; val = JS_NULL;
} }
rec = (JSRecord *)JS_VALUE_GET_OBJ (*pobj);
slot = rec_find_slot (rec, prop); slot = rec_find_slot (rec, prop);
if (slot > 0) return 0; /* already defined */ if (slot > 0) return 0; /* already defined */
if (obj_is_stone (rec)) return 0; if (obj_is_stone (rec)) return 0;
return rec_set_own (ctx, rec, prop, val); return rec_set_own (ctx, pobj, prop, val);
} }
/* Simplified global function definition */ /* Simplified global function definition */
@@ -7512,91 +7514,59 @@ restart:
BREAK; BREAK;
CASE (OP_check_var) : { CASE (OP_check_var) : {
int ret; /* Global object is immutable - linker should have resolved or removed this */
JSValue key;
key = b->cpool[get_u32 (pc)];
pc += 4; pc += 4;
sf->cur_pc = pc; JS_ThrowInternalError (ctx, "OP_check_var: linker should have resolved this");
goto exception;
ret = JS_CheckGlobalVar (ctx, key);
if (ret < 0) goto exception;
*sp++ = JS_NewBool (ctx, ret);
} }
BREAK; BREAK;
CASE (OP_get_var_undef) : CASE (OP_get_var) : { CASE (OP_get_var_undef) : CASE (OP_get_var) : {
JSValue val; /* Global object is immutable - linker should have resolved this */
JSValue key;
key = b->cpool[get_u32 (pc)];
pc += 4; pc += 4;
sf->cur_pc = pc; JS_ThrowInternalError (ctx, "OP_get_var: linker should have resolved to get_global_slot");
goto exception;
val = JS_GetGlobalVar (ctx, key, opcode - OP_get_var_undef);
if (unlikely (JS_IsException (val))) goto exception;
*sp++ = val;
} }
BREAK; BREAK;
CASE (OP_put_var) : CASE (OP_put_var_init) : { CASE (OP_put_var) : CASE (OP_put_var_init) : {
int ret; /* Global object is immutable - linker should have resolved this */
JSValue key;
key = b->cpool[get_u32 (pc)];
pc += 4; pc += 4;
sf->cur_pc = pc;
ret = JS_SetGlobalVar (ctx, key, sp[-1], opcode - OP_put_var);
sp--; sp--;
if (unlikely (ret < 0)) goto exception; JS_ThrowInternalError (ctx, "OP_put_var: global object is immutable, linker should resolve");
goto exception;
} }
BREAK; BREAK;
CASE (OP_put_var_strict) : { CASE (OP_put_var_strict) : {
int ret; /* Global object is immutable - linker should have resolved this */
JSValue key;
key = b->cpool[get_u32 (pc)];
pc += 4; pc += 4;
sf->cur_pc = pc;
/* sp[-2] is JS_TRUE or JS_FALSE */
if (unlikely (!JS_VALUE_GET_INT (sp[-2]))) {
JS_ThrowReferenceErrorNotDefined (ctx, key);
goto exception;
}
ret = JS_SetGlobalVar (ctx, key, sp[-1], 2);
sp -= 2; sp -= 2;
if (unlikely (ret < 0)) goto exception; JS_ThrowInternalError (ctx, "OP_put_var_strict: global object is immutable, linker should resolve");
goto exception;
} }
BREAK; BREAK;
CASE (OP_check_define_var) : { CASE (OP_check_define_var) : {
JSValue key; /* Global object is immutable - this opcode should not be emitted */
int flags;
key = b->cpool[get_u32 (pc)];
flags = pc[4];
pc += 5; pc += 5;
sf->cur_pc = pc; JS_ThrowInternalError (ctx, "OP_check_define_var: global object is immutable");
if (JS_CheckDefineGlobalVar (ctx, key, flags)) goto exception; goto exception;
} }
BREAK; BREAK;
CASE (OP_define_var) : { CASE (OP_define_var) : {
JSValue key; /* Global object is immutable - this opcode should not be emitted */
int flags;
key = b->cpool[get_u32 (pc)];
flags = pc[4];
pc += 5; pc += 5;
sf->cur_pc = pc; JS_ThrowInternalError (ctx, "OP_define_var: global object is immutable");
if (JS_DefineGlobalVar (ctx, key, flags)) goto exception; goto exception;
} }
BREAK; BREAK;
CASE (OP_define_func) : { CASE (OP_define_func) : {
JSValue key; /* Global object is immutable - this opcode should not be emitted */
int flags;
key = b->cpool[get_u32 (pc)];
flags = pc[4];
pc += 5; pc += 5;
sf->cur_pc = pc;
if (JS_DefineGlobalFunction (ctx, key, sp[-1], flags)) goto exception;
sp--; sp--;
JS_ThrowInternalError (ctx, "OP_define_func: global object is immutable");
goto exception;
} }
BREAK; BREAK;
@@ -8127,8 +8097,7 @@ restart:
} }
/* Record property set - use JSValue key directly */ /* Record property set - use JSValue key directly */
JSRecord *rec = JS_VALUE_GET_RECORD (sp[-2]); ret = rec_set_own (ctx, &sp[-2], key, sp[-1]);
ret = rec_set_own (ctx, rec, key, sp[-1]);
sp -= 2; sp -= 2;
if (unlikely (ret < 0)) goto exception; if (unlikely (ret < 0)) goto exception;
} }
@@ -8153,8 +8122,7 @@ restart:
} }
/* Record property set - use JSValue key directly */ /* Record property set - use JSValue key directly */
JSRecord *rec = JS_VALUE_GET_RECORD (sp[-2]); ret = rec_set_own (ctx, &sp[-2], key, sp[-1]);
ret = rec_set_own (ctx, rec, key, sp[-1]);
sp--; sp--;
if (unlikely (ret < 0)) goto exception; if (unlikely (ret < 0)) goto exception;
} }
@@ -8906,16 +8874,10 @@ restart:
sp--; sp--;
BREAK; BREAK;
CASE (OP_delete_var) : { CASE (OP_delete_var) : {
JSValue key; /* Global object is immutable - cannot delete globals */
int ret;
key = b->cpool[get_u32 (pc)];
pc += 4; pc += 4;
sf->cur_pc = pc; JS_ThrowInternalError (ctx, "OP_delete_var: global object is immutable");
goto exception;
ret = JS_DeleteGlobalVar (ctx, key);
if (unlikely (ret < 0)) goto exception;
*sp++ = JS_NewBool (ctx, ret);
} }
BREAK; BREAK;
@@ -10219,18 +10181,51 @@ static int js_keyword_lookup (JSValue str, BOOL *is_strict_reserved) {
} }
buf[len] = '\0'; buf[len] = '\0';
cstr = buf; cstr = buf;
} else if (JS_IsPtr (str)) {
/* Handle heap strings (JSText) - keywords like "function" are 8 chars */
JSText *text = (JSText *)JS_VALUE_GET_PTR (str);
#ifdef PRINT_LEXER
fprintf(stderr, "DEBUG: JS_IsPtr branch, ptr=%p, hdr_type=%d\n", (void*)text, objhdr_type(text->hdr));
#endif
if (objhdr_type (text->hdr) != OBJ_TEXT) return -1;
len = JSText_len (text);
#ifdef PRINT_LEXER
fprintf(stderr, "DEBUG: text len=%zu\n", len);
#endif
if (len >= sizeof (buf)) return -1;
for (size_t i = 0; i < len; i++) {
uint32_t c = string_get (text, i);
if (c >= 128) return -1; /* Keywords are ASCII only */
buf[i] = (char)c;
}
buf[len] = '\0';
cstr = buf;
#ifdef PRINT_LEXER
fprintf(stderr, "DEBUG: extracted string='%s' len=%zu\n", cstr, len);
#endif
} else { } else {
/* heap strings longer than immediate can't be keywords */ #ifdef PRINT_LEXER
fprintf(stderr, "DEBUG: unknown str type, tag=%llx\n", (unsigned long long)(str & 0xFF));
#endif
return -1; return -1;
} }
#ifdef PRINT_LEXER
fprintf(stderr, "DEBUG: looking up '%s' in %zu keywords\n", cstr, (size_t)JS_KEYWORD_COUNT);
#endif
for (size_t i = 0; i < JS_KEYWORD_COUNT; i++) { for (size_t i = 0; i < JS_KEYWORD_COUNT; i++) {
if (strcmp (cstr, js_keywords[i].name) == 0) { if (strcmp (cstr, js_keywords[i].name) == 0) {
#ifdef PRINT_LEXER
fprintf(stderr, "DEBUG: matched keyword '%s' -> token %d\n", js_keywords[i].name, js_keywords[i].token);
#endif
if (is_strict_reserved) if (is_strict_reserved)
*is_strict_reserved = js_keywords[i].is_strict_reserved; *is_strict_reserved = js_keywords[i].is_strict_reserved;
return js_keywords[i].token; return js_keywords[i].token;
} }
} }
#ifdef PRINT_LEXER
fprintf(stderr, "DEBUG: no keyword match for '%s'\n", cstr);
#endif
return -1; return -1;
} }
@@ -10239,7 +10234,7 @@ static void update_token_ident (JSParseState *s) {
BOOL is_strict_reserved = FALSE; BOOL is_strict_reserved = FALSE;
int token = js_keyword_lookup (s->token.u.ident.str, &is_strict_reserved); int token = js_keyword_lookup (s->token.u.ident.str, &is_strict_reserved);
if (token >= 0) { if (token != -1) {
if (s->token.u.ident.has_escape) { if (s->token.u.ident.has_escape) {
/* identifiers with escape sequences stay identifiers */ /* identifiers with escape sequences stay identifiers */
s->token.u.ident.is_reserved = TRUE; s->token.u.ident.is_reserved = TRUE;
@@ -11672,15 +11667,8 @@ static int define_var (JSParseState *s, JSFunctionDef *fd, JSValue name, JSVarDe
} }
} }
if (fd->is_eval && fd->eval_type == JS_EVAL_TYPE_GLOBAL /* Global object is immutable - always use local variables */
&& fd->scope_level == fd->body_scope) { {
JSGlobalVar *hf;
hf = add_global_var (s->ctx, fd, name);
if (!hf) return -1;
hf->is_lexical = TRUE;
hf->is_const = (var_def_type == JS_VAR_DEF_CONST);
idx = GLOBAL_VAR_OFFSET;
} else {
JSVarKindEnum var_kind; JSVarKindEnum var_kind;
if (var_def_type == JS_VAR_DEF_FUNCTION_DECL) if (var_def_type == JS_VAR_DEF_FUNCTION_DECL)
var_kind = JS_VAR_FUNCTION_DECL; var_kind = JS_VAR_FUNCTION_DECL;
@@ -18132,7 +18120,8 @@ static __exception int js_parse_program (JSParseState *s) {
if (js_parse_directives (s)) return -1; if (js_parse_directives (s)) return -1;
fd->is_global_var = fd->eval_type == JS_EVAL_TYPE_GLOBAL; /* Global object is immutable - all variables are locals of the eval function */
fd->is_global_var = FALSE;
/* hidden variable for the return value */ /* hidden variable for the return value */
fd->eval_ret_idx = idx = add_var (s->ctx, fd, JS_KEY__ret_); fd->eval_ret_idx = idx = add_var (s->ctx, fd, JS_KEY__ret_);