fix parser
This commit is contained in:
153
source/quickjs.c
153
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_);
|
||||
|
||||
Reference in New Issue
Block a user