diff --git a/source/quickjs.c b/source/quickjs.c index 67130d80..6a996f0d 100644 --- a/source/quickjs.c +++ b/source/quickjs.c @@ -5112,21 +5112,23 @@ static int JS_CheckDefineGlobalVar (JSContext *ctx, JSValue prop, int flags) { Currently safe because rec_resize always fails. def_flags is (0, DEFINE_GLOBAL_LEX_VAR) */ static int JS_DefineGlobalVar (JSContext *ctx, JSValue prop, int def_flags) { - JSRecord *rec; + JSValue *pobj; JSValue val; + JSRecord *rec; int slot; 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; } else { - rec = (JSRecord *)JS_VALUE_GET_OBJ (ctx->global_obj); + pobj = &ctx->global_obj; val = JS_NULL; } + rec = (JSRecord *)JS_VALUE_GET_OBJ (*pobj); slot = rec_find_slot (rec, prop); if (slot > 0) return 0; /* already defined */ 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 */ @@ -7512,91 +7514,59 @@ restart: BREAK; CASE (OP_check_var) : { - int ret; - JSValue key; - key = b->cpool[get_u32 (pc)]; + /* Global object is immutable - linker should have resolved or removed this */ pc += 4; - sf->cur_pc = pc; - - ret = JS_CheckGlobalVar (ctx, key); - if (ret < 0) goto exception; - *sp++ = JS_NewBool (ctx, ret); + JS_ThrowInternalError (ctx, "OP_check_var: linker should have resolved this"); + goto exception; } BREAK; CASE (OP_get_var_undef) : CASE (OP_get_var) : { - JSValue val; - JSValue key; - key = b->cpool[get_u32 (pc)]; + /* Global object is immutable - linker should have resolved this */ pc += 4; - sf->cur_pc = pc; - - val = JS_GetGlobalVar (ctx, key, opcode - OP_get_var_undef); - if (unlikely (JS_IsException (val))) goto exception; - *sp++ = val; + JS_ThrowInternalError (ctx, "OP_get_var: linker should have resolved to get_global_slot"); + goto exception; } BREAK; CASE (OP_put_var) : CASE (OP_put_var_init) : { - int ret; - JSValue key; - key = b->cpool[get_u32 (pc)]; + /* Global object is immutable - linker should have resolved this */ pc += 4; - sf->cur_pc = pc; - - ret = JS_SetGlobalVar (ctx, key, sp[-1], opcode - OP_put_var); sp--; - if (unlikely (ret < 0)) goto exception; + JS_ThrowInternalError (ctx, "OP_put_var: global object is immutable, linker should resolve"); + goto exception; } BREAK; CASE (OP_put_var_strict) : { - int ret; - JSValue key; - key = b->cpool[get_u32 (pc)]; + /* Global object is immutable - linker should have resolved this */ 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; - if (unlikely (ret < 0)) goto exception; + JS_ThrowInternalError (ctx, "OP_put_var_strict: global object is immutable, linker should resolve"); + goto exception; } BREAK; CASE (OP_check_define_var) : { - JSValue key; - int flags; - key = b->cpool[get_u32 (pc)]; - flags = pc[4]; + /* Global object is immutable - this opcode should not be emitted */ pc += 5; - sf->cur_pc = pc; - if (JS_CheckDefineGlobalVar (ctx, key, flags)) goto exception; + JS_ThrowInternalError (ctx, "OP_check_define_var: global object is immutable"); + goto exception; } BREAK; CASE (OP_define_var) : { - JSValue key; - int flags; - key = b->cpool[get_u32 (pc)]; - flags = pc[4]; + /* Global object is immutable - this opcode should not be emitted */ pc += 5; - sf->cur_pc = pc; - if (JS_DefineGlobalVar (ctx, key, flags)) goto exception; + JS_ThrowInternalError (ctx, "OP_define_var: global object is immutable"); + goto exception; } BREAK; CASE (OP_define_func) : { - JSValue key; - int flags; - key = b->cpool[get_u32 (pc)]; - flags = pc[4]; + /* Global object is immutable - this opcode should not be emitted */ pc += 5; - sf->cur_pc = pc; - if (JS_DefineGlobalFunction (ctx, key, sp[-1], flags)) goto exception; sp--; + JS_ThrowInternalError (ctx, "OP_define_func: global object is immutable"); + goto exception; } BREAK; @@ -8127,8 +8097,7 @@ restart: } /* Record property set - use JSValue key directly */ - JSRecord *rec = JS_VALUE_GET_RECORD (sp[-2]); - ret = rec_set_own (ctx, rec, key, sp[-1]); + ret = rec_set_own (ctx, &sp[-2], key, sp[-1]); sp -= 2; if (unlikely (ret < 0)) goto exception; } @@ -8153,8 +8122,7 @@ restart: } /* Record property set - use JSValue key directly */ - JSRecord *rec = JS_VALUE_GET_RECORD (sp[-2]); - ret = rec_set_own (ctx, rec, key, sp[-1]); + ret = rec_set_own (ctx, &sp[-2], key, sp[-1]); sp--; if (unlikely (ret < 0)) goto exception; } @@ -8906,16 +8874,10 @@ restart: sp--; BREAK; CASE (OP_delete_var) : { - JSValue key; - int ret; - - key = b->cpool[get_u32 (pc)]; + /* Global object is immutable - cannot delete globals */ pc += 4; - sf->cur_pc = pc; - - ret = JS_DeleteGlobalVar (ctx, key); - if (unlikely (ret < 0)) goto exception; - *sp++ = JS_NewBool (ctx, ret); + JS_ThrowInternalError (ctx, "OP_delete_var: global object is immutable"); + goto exception; } BREAK; @@ -10219,18 +10181,51 @@ static int js_keyword_lookup (JSValue str, BOOL *is_strict_reserved) { } buf[len] = '\0'; 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 { - /* 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; } +#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++) { 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) *is_strict_reserved = js_keywords[i].is_strict_reserved; return js_keywords[i].token; } } +#ifdef PRINT_LEXER + fprintf(stderr, "DEBUG: no keyword match for '%s'\n", cstr); +#endif return -1; } @@ -10239,7 +10234,7 @@ static void update_token_ident (JSParseState *s) { BOOL is_strict_reserved = FALSE; 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) { /* identifiers with escape sequences stay identifiers */ 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 - && 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 { + /* Global object is immutable - always use local variables */ + { JSVarKindEnum var_kind; if (var_def_type == JS_VAR_DEF_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; - 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 */ fd->eval_ret_idx = idx = add_var (s->ctx, fd, JS_KEY__ret_);