Replace js_mode with is_strict_mode bit field (#590)

Shrinks some structures by one or more bytes and is easier to read.
This commit is contained in:
Ben Noordhuis 2024-10-10 19:31:47 +02:00 committed by GitHub
parent 681568353c
commit e145244999
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

123
quickjs.c
View file

@ -311,8 +311,6 @@ struct JSClass {
const JSClassExoticMethods *exotic; const JSClassExoticMethods *exotic;
}; };
#define JS_MODE_STRICT (1 << 0)
typedef struct JSStackFrame { typedef struct JSStackFrame {
struct JSStackFrame *prev_frame; /* NULL if first stack frame */ struct JSStackFrame *prev_frame; /* NULL if first stack frame */
JSValue cur_func; /* current function, JS_UNDEFINED if the frame is detached */ JSValue cur_func; /* current function, JS_UNDEFINED if the frame is detached */
@ -321,8 +319,8 @@ typedef struct JSStackFrame {
struct list_head var_ref_list; /* list of JSVarRef.link */ struct list_head var_ref_list; /* list of JSVarRef.link */
uint8_t *cur_pc; /* only used in bytecode functions : PC of the uint8_t *cur_pc; /* only used in bytecode functions : PC of the
instruction after the call */ instruction after the call */
int arg_count; uint32_t arg_count : 31;
int js_mode; uint32_t is_strict_mode : 1;
/* only used in generators. Current stack pointer value. NULL if /* only used in generators. Current stack pointer value. NULL if
the function is running. */ the function is running. */
JSValue *cur_sp; JSValue *cur_sp;
@ -648,7 +646,7 @@ static force_inline JSAtom get_ic_atom(JSInlineCache *ic, uint32_t cache_offset)
typedef struct JSFunctionBytecode { typedef struct JSFunctionBytecode {
JSGCObjectHeader header; /* must come first */ JSGCObjectHeader header; /* must come first */
uint8_t js_mode; uint8_t is_strict_mode : 1;
uint8_t has_prototype : 1; /* true if a prototype field is necessary */ uint8_t has_prototype : 1; /* true if a prototype field is necessary */
uint8_t has_simple_parameter_list : 1; uint8_t has_simple_parameter_list : 1;
uint8_t is_derived_class_constructor : 1; uint8_t is_derived_class_constructor : 1;
@ -2492,7 +2490,7 @@ void JS_UpdateStackTop(JSRuntime *rt)
static inline BOOL is_strict_mode(JSContext *ctx) static inline BOOL is_strict_mode(JSContext *ctx)
{ {
JSStackFrame *sf = ctx->rt->current_stack_frame; JSStackFrame *sf = ctx->rt->current_stack_frame;
return (sf && (sf->js_mode & JS_MODE_STRICT)); return sf && sf->is_strict_mode;
} }
/* JSAtom support */ /* JSAtom support */
@ -13438,7 +13436,7 @@ static JSValue js_function_proto_caller(JSContext *ctx, JSValue this_val,
int argc, JSValue *argv) int argc, JSValue *argv)
{ {
JSFunctionBytecode *b = JS_GetFunctionBytecode(this_val); JSFunctionBytecode *b = JS_GetFunctionBytecode(this_val);
if (!b || (b->js_mode & JS_MODE_STRICT) || !b->has_prototype) { if (!b || b->is_strict_mode || !b->has_prototype) {
return js_throw_type_error(ctx, this_val, 0, NULL); return js_throw_type_error(ctx, this_val, 0, NULL);
} }
return JS_UNDEFINED; return JS_UNDEFINED;
@ -14588,7 +14586,7 @@ static JSValue js_call_c_function(JSContext *ctx, JSValue func_obj,
rt->current_stack_frame = sf; rt->current_stack_frame = sf;
ctx = p->u.cfunc.realm; /* change the current realm */ ctx = p->u.cfunc.realm; /* change the current realm */
sf->js_mode = 0; sf->is_strict_mode = FALSE;
sf->cur_func = func_obj; sf->cur_func = func_obj;
sf->arg_count = argc; sf->arg_count = argc;
arg_buf = argv; arg_buf = argv;
@ -14850,7 +14848,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValue func_obj,
if (js_check_stack_overflow(rt, alloca_size)) if (js_check_stack_overflow(rt, alloca_size))
return JS_ThrowStackOverflow(caller_ctx); return JS_ThrowStackOverflow(caller_ctx);
sf->js_mode = b->js_mode; sf->is_strict_mode = b->is_strict_mode;
arg_buf = argv; arg_buf = argv;
sf->arg_count = argc; sf->arg_count = argc;
sf->cur_func = func_obj; sf->cur_func = func_obj;
@ -14959,7 +14957,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValue func_obj,
/* OP_push_this is only called at the start of a function */ /* OP_push_this is only called at the start of a function */
{ {
JSValue val; JSValue val;
if (!(b->js_mode & JS_MODE_STRICT)) { if (!b->is_strict_mode) {
uint32_t tag = JS_VALUE_GET_TAG(this_obj); uint32_t tag = JS_VALUE_GET_TAG(this_obj);
if (likely(tag == JS_TAG_OBJECT)) if (likely(tag == JS_TAG_OBJECT))
goto normal_this; goto normal_this;
@ -17532,7 +17530,7 @@ static __exception int async_func_init(JSContext *ctx, JSAsyncFunctionState *s,
init_list_head(&sf->var_ref_list); init_list_head(&sf->var_ref_list);
p = JS_VALUE_GET_OBJ(func_obj); p = JS_VALUE_GET_OBJ(func_obj);
b = p->u.func.function_bytecode; b = p->u.func.function_bytecode;
sf->js_mode = b->js_mode; sf->is_strict_mode = b->is_strict_mode;
sf->cur_pc = b->byte_code_buf; sf->cur_pc = b->byte_code_buf;
arg_buf_len = max_int(b->arg_count, argc); arg_buf_len = max_int(b->arg_count, argc);
local_count = arg_buf_len + b->var_count + b->stack_size; local_count = arg_buf_len + b->var_count + b->stack_size;
@ -18622,8 +18620,8 @@ typedef struct JSFunctionDef {
BOOL in_function_body; BOOL in_function_body;
BOOL backtrace_barrier; BOOL backtrace_barrier;
JSFunctionKindEnum func_kind : 8; JSFunctionKindEnum func_kind : 8;
JSParseFunctionEnum func_type : 8; JSParseFunctionEnum func_type : 7;
uint8_t js_mode; /* bitmap of JS_MODE_x */ uint8_t is_strict_mode : 1;
JSAtom func_name; /* JS_ATOM_NULL if no name */ JSAtom func_name; /* JS_ATOM_NULL if no name */
JSVarDef *vars; JSVarDef *vars;
@ -19081,7 +19079,7 @@ static __exception int js_parse_string(JSParseState *s, int sep,
c = '\0'; c = '\0';
} else } else
if ((c >= '0' && c <= '9') if ((c >= '0' && c <= '9')
&& ((s->cur_func->js_mode & JS_MODE_STRICT) || sep == '`')) { && (s->cur_func->is_strict_mode || sep == '`')) {
if (do_throw) { if (do_throw) {
js_parse_error(s, "%s are not allowed in %s", js_parse_error(s, "%s are not allowed in %s",
(c >= '8') ? "\\8 and \\9" : "Octal escape sequences", (c >= '8') ? "\\8 and \\9" : "Octal escape sequences",
@ -19268,7 +19266,7 @@ static void update_token_ident(JSParseState *s)
{ {
if (s->token.u.ident.atom <= JS_ATOM_LAST_KEYWORD || if (s->token.u.ident.atom <= JS_ATOM_LAST_KEYWORD ||
(s->token.u.ident.atom <= JS_ATOM_LAST_STRICT_KEYWORD && (s->token.u.ident.atom <= JS_ATOM_LAST_STRICT_KEYWORD &&
(s->cur_func->js_mode & JS_MODE_STRICT)) || s->cur_func->is_strict_mode) ||
(s->token.u.ident.atom == JS_ATOM_yield && (s->token.u.ident.atom == JS_ATOM_yield &&
((s->cur_func->func_kind & JS_FUNC_GENERATOR) || ((s->cur_func->func_kind & JS_FUNC_GENERATOR) ||
(s->cur_func->func_type == JS_PARSE_FUNC_ARROW && (s->cur_func->func_type == JS_PARSE_FUNC_ARROW &&
@ -19560,7 +19558,7 @@ static __exception int next_token(JSParseState *s)
goto def_token; goto def_token;
case '0': case '0':
if (is_digit(p[1])) { /* handle legacy octal */ if (is_digit(p[1])) { /* handle legacy octal */
if (s->cur_func->js_mode & JS_MODE_STRICT) { if (s->cur_func->is_strict_mode) {
js_parse_error(s, "Octal literals are not allowed in strict mode"); js_parse_error(s, "Octal literals are not allowed in strict mode");
goto fail; goto fail;
} }
@ -20696,7 +20694,7 @@ static int add_func_var(JSContext *ctx, JSFunctionDef *fd, JSAtom name)
if (idx < 0 && (idx = add_var(ctx, fd, name)) >= 0) { if (idx < 0 && (idx = add_var(ctx, fd, name)) >= 0) {
fd->func_var_idx = idx; fd->func_var_idx = idx;
fd->vars[idx].var_kind = JS_VAR_FUNCTION_NAME; fd->vars[idx].var_kind = JS_VAR_FUNCTION_NAME;
if (fd->js_mode & JS_MODE_STRICT) if (fd->is_strict_mode)
fd->vars[idx].is_const = TRUE; fd->vars[idx].is_const = TRUE;
} }
return idx; return idx;
@ -20809,7 +20807,7 @@ static int define_var(JSParseState *s, JSFunctionDef *fd, JSAtom name,
if (fd->vars[idx].scope_level == fd->scope_level) { if (fd->vars[idx].scope_level == fd->scope_level) {
/* same scope: in non strict mode, functions /* same scope: in non strict mode, functions
can be redefined (annex B.3.3.4). */ can be redefined (annex B.3.3.4). */
if (!(!(fd->js_mode & JS_MODE_STRICT) && if (!(!fd->is_strict_mode &&
var_def_type == JS_VAR_DEF_FUNCTION_DECL && var_def_type == JS_VAR_DEF_FUNCTION_DECL &&
fd->vars[idx].var_kind == JS_VAR_FUNCTION_DECL)) { fd->vars[idx].var_kind == JS_VAR_FUNCTION_DECL)) {
goto redef_lex_error; goto redef_lex_error;
@ -21802,16 +21800,16 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr,
JSAtom name = JS_ATOM_NULL, class_name = JS_ATOM_NULL, class_name1; JSAtom name = JS_ATOM_NULL, class_name = JS_ATOM_NULL, class_name1;
JSAtom class_var_name = JS_ATOM_NULL; JSAtom class_var_name = JS_ATOM_NULL;
JSFunctionDef *method_fd, *ctor_fd; JSFunctionDef *method_fd, *ctor_fd;
int saved_js_mode, class_name_var_idx, prop_type, ctor_cpool_offset; int class_name_var_idx, prop_type, ctor_cpool_offset;
int class_flags = 0, i, define_class_offset; int class_flags = 0, i, define_class_offset;
BOOL is_static, is_private; BOOL is_static, is_private, is_strict_mode;
const uint8_t *class_start_ptr = s->token.ptr; const uint8_t *class_start_ptr = s->token.ptr;
const uint8_t *start_ptr; const uint8_t *start_ptr;
ClassFieldsDef class_fields[2]; ClassFieldsDef class_fields[2];
/* classes are parsed and executed in strict mode */ /* classes are parsed and executed in strict mode */
saved_js_mode = fd->js_mode; is_strict_mode = fd->is_strict_mode;
fd->js_mode |= JS_MODE_STRICT; fd->is_strict_mode = TRUE;
if (next_token(s)) if (next_token(s))
goto fail; goto fail;
if (s->token.val == TOK_IDENT) { if (s->token.val == TOK_IDENT) {
@ -22311,13 +22309,13 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr,
JS_FreeAtom(ctx, class_name); JS_FreeAtom(ctx, class_name);
JS_FreeAtom(ctx, class_var_name); JS_FreeAtom(ctx, class_var_name);
fd->js_mode = saved_js_mode; fd->is_strict_mode = is_strict_mode;
return 0; return 0;
fail: fail:
JS_FreeAtom(ctx, name); JS_FreeAtom(ctx, name);
JS_FreeAtom(ctx, class_name); JS_FreeAtom(ctx, class_name);
JS_FreeAtom(ctx, class_var_name); JS_FreeAtom(ctx, class_var_name);
fd->js_mode = saved_js_mode; fd->is_strict_mode = is_strict_mode;
return -1; return -1;
} }
@ -22462,7 +22460,7 @@ static __exception int get_lvalue(JSParseState *s, int *popcode, int *pscope,
name = get_u32(fd->byte_code.buf + fd->last_opcode_pos + 1); name = get_u32(fd->byte_code.buf + fd->last_opcode_pos + 1);
scope = get_u16(fd->byte_code.buf + fd->last_opcode_pos + 5); scope = get_u16(fd->byte_code.buf + fd->last_opcode_pos + 5);
if ((name == JS_ATOM_arguments || name == JS_ATOM_eval) && if ((name == JS_ATOM_arguments || name == JS_ATOM_eval) &&
(fd->js_mode & JS_MODE_STRICT)) { fd->is_strict_mode) {
return js_parse_error(s, "invalid lvalue in strict mode"); return js_parse_error(s, "invalid lvalue in strict mode");
} }
if (name == JS_ATOM_this || name == JS_ATOM_new_target) if (name == JS_ATOM_this || name == JS_ATOM_new_target)
@ -22712,7 +22710,7 @@ static __exception int js_define_var(JSParseState *s, JSAtom name, int tok)
return js_parse_error(s, "yield is a reserved identifier"); return js_parse_error(s, "yield is a reserved identifier");
} }
if ((name == JS_ATOM_arguments || name == JS_ATOM_eval) if ((name == JS_ATOM_arguments || name == JS_ATOM_eval)
&& (fd->js_mode & JS_MODE_STRICT)) { && fd->is_strict_mode) {
return js_parse_error(s, "invalid variable name in strict mode"); return js_parse_error(s, "invalid variable name in strict mode");
} }
if ((name == JS_ATOM_let || name == JS_ATOM_undefined) if ((name == JS_ATOM_let || name == JS_ATOM_undefined)
@ -22790,7 +22788,7 @@ static JSAtom js_parse_destructuring_var(JSParseState *s, int tok, int is_arg)
JSAtom name; JSAtom name;
if (!(s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved) if (!(s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved)
|| ((s->cur_func->js_mode & JS_MODE_STRICT) && || (s->cur_func->is_strict_mode &&
(s->token.u.ident.atom == JS_ATOM_eval || s->token.u.ident.atom == JS_ATOM_arguments))) { (s->token.u.ident.atom == JS_ATOM_eval || s->token.u.ident.atom == JS_ATOM_arguments))) {
js_parse_error(s, "invalid destructuring target"); js_parse_error(s, "invalid destructuring target");
return JS_ATOM_NULL; return JS_ATOM_NULL;
@ -23024,7 +23022,7 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
/* prop_type = PROP_TYPE_VAR, cannot be a computed property */ /* prop_type = PROP_TYPE_VAR, cannot be a computed property */
if (is_arg && js_parse_check_duplicate_parameter(s, prop_name)) if (is_arg && js_parse_check_duplicate_parameter(s, prop_name))
goto prop_error; goto prop_error;
if ((s->cur_func->js_mode & JS_MODE_STRICT) && if (s->cur_func->is_strict_mode &&
(prop_name == JS_ATOM_eval || prop_name == JS_ATOM_arguments)) { (prop_name == JS_ATOM_eval || prop_name == JS_ATOM_arguments)) {
js_parse_error(s, "invalid destructuring target"); js_parse_error(s, "invalid destructuring target");
goto prop_error; goto prop_error;
@ -23950,7 +23948,7 @@ static __exception int js_parse_delete(JSParseState *s)
name = get_u32(fd->byte_code.buf + fd->last_opcode_pos + 1); name = get_u32(fd->byte_code.buf + fd->last_opcode_pos + 1);
if (name == JS_ATOM_this || name == JS_ATOM_new_target) if (name == JS_ATOM_this || name == JS_ATOM_new_target)
goto ret_true; goto ret_true;
if (fd->js_mode & JS_MODE_STRICT) { if (fd->is_strict_mode) {
return js_parse_error(s, "cannot delete a direct reference in strict mode"); return js_parse_error(s, "cannot delete a direct reference in strict mode");
} else { } else {
fd->byte_code.buf[fd->last_opcode_pos] = OP_scope_delete_var; fd->byte_code.buf[fd->last_opcode_pos] = OP_scope_delete_var;
@ -25171,8 +25169,7 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name,
if (is_async) if (is_async)
return js_parse_error(s, "'for await' loop should be used with 'of'"); return js_parse_error(s, "'for await' loop should be used with 'of'");
if (has_initializer && if (has_initializer &&
(tok != TOK_VAR || (fd->js_mode & JS_MODE_STRICT) || (tok != TOK_VAR || fd->is_strict_mode || has_destructuring)) {
has_destructuring)) {
initializer_error: initializer_error:
return js_parse_error(s, "a declaration in the head of a for-%s loop can't have an initializer", return js_parse_error(s, "a declaration in the head of a for-%s loop can't have an initializer",
is_for_of ? "of" : "in"); is_for_of ? "of" : "in");
@ -25314,7 +25311,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s,
label_break = new_label(s); label_break = new_label(s);
push_break_entry(s->cur_func, &break_entry, push_break_entry(s->cur_func, &break_entry,
label_name, label_break, -1, 0); label_name, label_break, -1, 0);
if (!(s->cur_func->js_mode & JS_MODE_STRICT) && if (!s->cur_func->is_strict_mode &&
(decl_mask & DECL_MASK_FUNC_WITH_LABEL)) { (decl_mask & DECL_MASK_FUNC_WITH_LABEL)) {
mask = DECL_MASK_FUNC | DECL_MASK_FUNC_WITH_LABEL; mask = DECL_MASK_FUNC | DECL_MASK_FUNC_WITH_LABEL;
} else { } else {
@ -25394,7 +25391,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s,
if (js_parse_expr_paren(s)) if (js_parse_expr_paren(s))
goto fail; goto fail;
label1 = emit_goto(s, OP_if_false, -1); label1 = emit_goto(s, OP_if_false, -1);
if (s->cur_func->js_mode & JS_MODE_STRICT) if (s->cur_func->is_strict_mode)
mask = 0; mask = 0;
else else
mask = DECL_MASK_FUNC; /* Annex B.3.4 */ mask = DECL_MASK_FUNC; /* Annex B.3.4 */
@ -25912,7 +25909,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s,
goto fail; goto fail;
break; break;
case TOK_WITH: case TOK_WITH:
if (s->cur_func->js_mode & JS_MODE_STRICT) { if (s->cur_func->is_strict_mode) {
js_parse_error(s, "invalid keyword: with"); js_parse_error(s, "invalid keyword: with");
goto fail; goto fail;
} else { } else {
@ -28247,7 +28244,7 @@ static JSFunctionDef *js_new_function_def(JSContext *ctx,
fd->parent_cpool_idx = -1; fd->parent_cpool_idx = -1;
if (parent) { if (parent) {
list_add_tail(&fd->link, &parent->child_list); list_add_tail(&fd->link, &parent->child_list);
fd->js_mode = parent->js_mode; fd->is_strict_mode = parent->is_strict_mode;
fd->parent_scope_level = parent->scope_level; fd->parent_scope_level = parent->scope_level;
} }
@ -28777,13 +28774,7 @@ static __maybe_unused void js_dump_function_bytecode(JSContext *ctx, JSFunctionB
str = JS_AtomGetStr(ctx, atom_buf, sizeof(atom_buf), b->func_name); str = JS_AtomGetStr(ctx, atom_buf, sizeof(atom_buf), b->func_name);
printf("function: %s%s\n", &"*"[b->func_kind != JS_FUNC_GENERATOR], str); printf("function: %s%s\n", &"*"[b->func_kind != JS_FUNC_GENERATOR], str);
if (b->js_mode) { printf(" mode: %s\n", b->is_strict_mode ? "strict" : "sloppy");
printf(" mode:");
if (b->js_mode & JS_MODE_STRICT)
printf(" strict");
printf("\n");
}
if (b->arg_count && b->vardefs) { if (b->arg_count && b->vardefs) {
printf(" args:"); printf(" args:");
for(i = 0; i < b->arg_count; i++) { for(i = 0; i < b->arg_count; i++) {
@ -28997,12 +28988,11 @@ static int optimize_scope_make_global_ref(JSContext *ctx, JSFunctionDef *s,
JSAtom var_name) JSAtom var_name)
{ {
int label_pos, end_pos, pos, op; int label_pos, end_pos, pos, op;
BOOL is_strict; BOOL is_strict_mode = s->is_strict_mode;
is_strict = ((s->js_mode & JS_MODE_STRICT) != 0);
/* replace the reference get/put with normal variable /* replace the reference get/put with normal variable
accesses */ accesses */
if (is_strict) { if (is_strict_mode) {
/* need to check if the variable exists before evaluating the right /* need to check if the variable exists before evaluating the right
expression */ expression */
/* XXX: need an extra OP_true if destructuring an array */ /* XXX: need an extra OP_true if destructuring an array */
@ -29024,7 +29014,7 @@ static int optimize_scope_make_global_ref(JSContext *ctx, JSFunctionDef *s,
assert(bc_buf[pos] == OP_label); assert(bc_buf[pos] == OP_label);
end_pos = label_pos + 2; end_pos = label_pos + 2;
op = bc_buf[label_pos]; op = bc_buf[label_pos];
if (is_strict) { if (is_strict_mode) {
if (op != OP_nop) { if (op != OP_nop) {
switch(op) { switch(op) {
case OP_insert3: case OP_insert3:
@ -29045,7 +29035,7 @@ static int optimize_scope_make_global_ref(JSContext *ctx, JSFunctionDef *s,
if (op == OP_insert3) if (op == OP_insert3)
bc_buf[pos++] = OP_dup; bc_buf[pos++] = OP_dup;
} }
if (is_strict) { if (is_strict_mode) {
bc_buf[pos] = OP_put_var_strict; bc_buf[pos] = OP_put_var_strict;
/* XXX: need 1 extra OP_drop if destructuring an array */ /* XXX: need 1 extra OP_drop if destructuring an array */
} else { } else {
@ -29782,7 +29772,7 @@ static void add_eval_variables(JSContext *ctx, JSFunctionDef *s)
/* in non strict mode, variables are created in the caller's /* in non strict mode, variables are created in the caller's
environment object */ environment object */
if (!s->is_eval && !(s->js_mode & JS_MODE_STRICT)) { if (!s->is_eval && !s->is_strict_mode) {
s->var_object_idx = add_var(ctx, s, JS_ATOM__var_); s->var_object_idx = add_var(ctx, s, JS_ATOM__var_);
if (s->has_parameter_expressions) { if (s->has_parameter_expressions) {
/* an additional variable object is needed for the /* an additional variable object is needed for the
@ -29809,7 +29799,7 @@ static void add_eval_variables(JSContext *ctx, JSFunctionDef *s)
/* also add an arguments binding in the argument scope to /* also add an arguments binding in the argument scope to
raise an error if a direct eval in the argument scope tries raise an error if a direct eval in the argument scope tries
to redefine it */ to redefine it */
if (s->has_parameter_expressions && !(s->js_mode & JS_MODE_STRICT)) if (s->has_parameter_expressions && !s->is_strict_mode)
add_arguments_arg(ctx, s); add_arguments_arg(ctx, s);
} }
if (s->is_func_expr && s->func_name != JS_ATOM_NULL) if (s->is_func_expr && s->func_name != JS_ATOM_NULL)
@ -30982,7 +30972,7 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s)
} }
/* initialize the 'arguments' variable if needed */ /* initialize the 'arguments' variable if needed */
if (s->arguments_var_idx >= 0) { if (s->arguments_var_idx >= 0) {
if ((s->js_mode & JS_MODE_STRICT) || !s->has_simple_parameter_list) { if (s->is_strict_mode || !s->has_simple_parameter_list) {
dbuf_putc(&bc_out, OP_special_object); dbuf_putc(&bc_out, OP_special_object);
dbuf_putc(&bc_out, OP_SPECIAL_OBJECT_ARGUMENTS); dbuf_putc(&bc_out, OP_SPECIAL_OBJECT_ARGUMENTS);
} else { } else {
@ -32250,7 +32240,7 @@ static JSValue js_create_function(JSContext *ctx, JSFunctionDef *fd)
b->has_prototype = fd->has_prototype; b->has_prototype = fd->has_prototype;
b->has_simple_parameter_list = fd->has_simple_parameter_list; b->has_simple_parameter_list = fd->has_simple_parameter_list;
b->js_mode = fd->js_mode; b->is_strict_mode = fd->is_strict_mode;
b->is_derived_class_constructor = fd->is_derived_class_constructor; b->is_derived_class_constructor = fd->is_derived_class_constructor;
b->func_kind = fd->func_kind; b->func_kind = fd->func_kind;
b->need_home_object = (fd->home_object_var_idx >= 0 || b->need_home_object = (fd->home_object_var_idx >= 0 ||
@ -32405,7 +32395,7 @@ static __exception int js_parse_directives(JSParseState *s)
break; break;
if (!strcmp(str, "use strict")) { if (!strcmp(str, "use strict")) {
s->cur_func->has_use_strict = TRUE; s->cur_func->has_use_strict = TRUE;
s->cur_func->js_mode |= JS_MODE_STRICT; s->cur_func->is_strict_mode = TRUE;
} }
} }
return js_parse_seek_token(s, &pos); return js_parse_seek_token(s, &pos);
@ -32436,7 +32426,7 @@ static int js_parse_function_check_names(JSParseState *s, JSFunctionDef *fd,
JSAtom name; JSAtom name;
int i, idx; int i, idx;
if (fd->js_mode & JS_MODE_STRICT) { if (fd->is_strict_mode) {
if (!fd->has_simple_parameter_list && fd->has_use_strict) { if (!fd->has_simple_parameter_list && fd->has_use_strict) {
return js_parse_error(s, "\"use strict\" not allowed in function with default or destructuring parameter"); return js_parse_error(s, "\"use strict\" not allowed in function with default or destructuring parameter");
} }
@ -32451,7 +32441,7 @@ static int js_parse_function_check_names(JSParseState *s, JSFunctionDef *fd,
} }
} }
/* check async_generator case */ /* check async_generator case */
if ((fd->js_mode & JS_MODE_STRICT) if (fd->is_strict_mode
|| !fd->has_simple_parameter_list || !fd->has_simple_parameter_list
|| (fd->func_type == JS_PARSE_FUNC_METHOD && fd->func_kind == JS_FUNC_ASYNC) || (fd->func_type == JS_PARSE_FUNC_METHOD && fd->func_kind == JS_FUNC_ASYNC)
|| fd->func_type == JS_PARSE_FUNC_ARROW || fd->func_type == JS_PARSE_FUNC_ARROW
@ -32558,7 +32548,7 @@ static __exception int js_parse_function_decl2(JSParseState *s,
} }
} }
if (s->token.val == TOK_IDENT || if (s->token.val == TOK_IDENT ||
(((s->token.val == TOK_YIELD && !(fd->js_mode & JS_MODE_STRICT)) || (((s->token.val == TOK_YIELD && !fd->is_strict_mode) ||
(s->token.val == TOK_AWAIT && !s->is_module)) && (s->token.val == TOK_AWAIT && !s->is_module)) &&
func_type == JS_PARSE_FUNC_EXPR)) { func_type == JS_PARSE_FUNC_EXPR)) {
func_name = JS_DupAtom(ctx, s->token.u.ident.atom); func_name = JS_DupAtom(ctx, s->token.u.ident.atom);
@ -32589,7 +32579,7 @@ static __exception int js_parse_function_decl2(JSParseState *s,
} }
if (func_type == JS_PARSE_FUNC_VAR) { if (func_type == JS_PARSE_FUNC_VAR) {
if (!(fd->js_mode & JS_MODE_STRICT) if (!fd->is_strict_mode
&& func_kind == JS_FUNC_NORMAL && func_kind == JS_FUNC_NORMAL
&& find_lexical_decl(ctx, fd, func_name, fd->scope_first, FALSE) < 0 && find_lexical_decl(ctx, fd, func_name, fd->scope_first, FALSE) < 0
&& !((func_idx = find_var(ctx, fd, func_name)) >= 0 && (func_idx & ARGUMENT_VAR_OFFSET)) && !((func_idx = find_var(ctx, fd, func_name)) >= 0 && (func_idx & ARGUMENT_VAR_OFFSET))
@ -32998,7 +32988,7 @@ done:
(needed for annex B.3.3.4 and B.3.3.5 (needed for annex B.3.3.4 and B.3.3.5
checks) */ checks) */
hf->scope_level = 0; hf->scope_level = 0;
hf->force_init = ((s->cur_func->js_mode & JS_MODE_STRICT) != 0); hf->force_init = s->cur_func->is_strict_mode;
/* store directly into global var, bypass lexical scope */ /* store directly into global var, bypass lexical scope */
emit_op(s, OP_dup); emit_op(s, OP_dup);
emit_op(s, OP_scope_put_var); emit_op(s, OP_scope_put_var);
@ -33097,7 +33087,7 @@ static __exception int js_parse_program(JSParseState *s)
fd->is_global_var = (fd->eval_type == JS_EVAL_TYPE_GLOBAL) || fd->is_global_var = (fd->eval_type == JS_EVAL_TYPE_GLOBAL) ||
(fd->eval_type == JS_EVAL_TYPE_MODULE) || (fd->eval_type == JS_EVAL_TYPE_MODULE) ||
!(fd->js_mode & JS_MODE_STRICT); !fd->is_strict_mode;
if (!s->is_module) { if (!s->is_module) {
/* hidden variable for the return value */ /* hidden variable for the return value */
@ -33198,13 +33188,14 @@ static JSValue __JS_EvalInternal(JSContext *ctx, JSValue this_obj,
const char *filename, int flags, int scope_idx) const char *filename, int flags, int scope_idx)
{ {
JSParseState s1, *s = &s1; JSParseState s1, *s = &s1;
int err, js_mode, eval_type; int err, eval_type;
JSValue fun_obj, ret_val; JSValue fun_obj, ret_val;
JSStackFrame *sf; JSStackFrame *sf;
JSVarRef **var_refs; JSVarRef **var_refs;
JSFunctionBytecode *b; JSFunctionBytecode *b;
JSFunctionDef *fd; JSFunctionDef *fd;
JSModuleDef *m; JSModuleDef *m;
BOOL is_strict_mode;
js_parse_init(ctx, s, input, input_len, filename); js_parse_init(ctx, s, input, input_len, filename);
skip_shebang(&s->buf_ptr, s->buf_end); skip_shebang(&s->buf_ptr, s->buf_end);
@ -33220,14 +33211,12 @@ static JSValue __JS_EvalInternal(JSContext *ctx, JSValue this_obj,
assert(js_class_has_bytecode(p->class_id)); assert(js_class_has_bytecode(p->class_id));
b = p->u.func.function_bytecode; b = p->u.func.function_bytecode;
var_refs = p->u.func.var_refs; var_refs = p->u.func.var_refs;
js_mode = b->js_mode; is_strict_mode = b->is_strict_mode;
} else { } else {
sf = NULL; sf = NULL;
b = NULL; b = NULL;
var_refs = NULL; var_refs = NULL;
js_mode = 0; is_strict_mode = (flags & JS_EVAL_FLAG_STRICT) != 0;
if (flags & JS_EVAL_FLAG_STRICT)
js_mode |= JS_MODE_STRICT;
if (eval_type == JS_EVAL_TYPE_MODULE) { if (eval_type == JS_EVAL_TYPE_MODULE) {
JSAtom module_name = JS_NewAtom(ctx, filename); JSAtom module_name = JS_NewAtom(ctx, filename);
if (module_name == JS_ATOM_NULL) if (module_name == JS_ATOM_NULL)
@ -33235,7 +33224,7 @@ static JSValue __JS_EvalInternal(JSContext *ctx, JSValue this_obj,
m = js_new_module_def(ctx, module_name); m = js_new_module_def(ctx, module_name);
if (!m) if (!m)
return JS_EXCEPTION; return JS_EXCEPTION;
js_mode |= JS_MODE_STRICT; is_strict_mode = TRUE;
} }
} }
fd = js_new_function_def(ctx, NULL, TRUE, FALSE, filename, 1, 1); fd = js_new_function_def(ctx, NULL, TRUE, FALSE, filename, 1, 1);
@ -33256,7 +33245,7 @@ static JSValue __JS_EvalInternal(JSContext *ctx, JSValue this_obj,
fd->super_allowed = FALSE; fd->super_allowed = FALSE;
fd->arguments_allowed = TRUE; fd->arguments_allowed = TRUE;
} }
fd->js_mode = js_mode; fd->is_strict_mode = is_strict_mode;
fd->func_name = JS_DupAtom(ctx, JS_ATOM__eval_); fd->func_name = JS_DupAtom(ctx, JS_ATOM__eval_);
if (b) { if (b) {
if (add_closure_variables(ctx, fd, b, scope_idx)) if (add_closure_variables(ctx, fd, b, scope_idx))
@ -33881,7 +33870,7 @@ static int JS_WriteFunctionTag(BCWriterState *s, JSValue obj)
bc_set_flags(&flags, &idx, s->allow_debug, 1); bc_set_flags(&flags, &idx, s->allow_debug, 1);
assert(idx <= 16); assert(idx <= 16);
bc_put_u16(s, flags); bc_put_u16(s, flags);
bc_put_u8(s, b->js_mode); bc_put_u8(s, b->is_strict_mode);
bc_put_atom(s, b->func_name); bc_put_atom(s, b->func_name);
bc_put_leb128(s, b->arg_count); bc_put_leb128(s, b->arg_count);
@ -34843,7 +34832,7 @@ static JSValue JS_ReadFunctionTag(BCReaderState *s)
has_debug_info = bc_get_flags(v16, &idx, 1); has_debug_info = bc_get_flags(v16, &idx, 1);
if (bc_get_u8(s, &v8)) if (bc_get_u8(s, &v8))
goto fail; goto fail;
bc.js_mode = v8; bc.is_strict_mode = (v8 > 0);
if (bc_get_atom(s, &bc.func_name)) if (bc_get_atom(s, &bc.func_name))
goto fail; goto fail;
if (bc_get_leb128_u16(s, &bc.arg_count)) if (bc_get_leb128_u16(s, &bc.arg_count))