remove arguments object

This commit is contained in:
2025-06-18 13:24:22 -05:00
parent 7f002e306d
commit 458215f838
4 changed files with 35 additions and 303 deletions

View File

@@ -1,4 +1,4 @@
var N = 10000000;
var N = 1000000;
var num = 0;
for (var i = 0; i < N; i ++) {
var x = 2 * $_.random();

View File

@@ -75,7 +75,7 @@ function add_separator_left(str, sep, n) {
/* -------- main text function --------------------------------------- */
function text() {
function text(...arguments) {
var arg = arguments[0];
// Handle blob conversion

View File

@@ -110,7 +110,6 @@ DEF(object, "object")
DEF(symbol, "symbol")
DEF(integer, "integer")
DEF(unknown, "unknown")
DEF(arguments, "arguments")
DEF(callee, "callee")
DEF(caller, "caller")
DEF(_eval_, "<eval>")
@@ -198,7 +197,6 @@ DEF(Number, "Number")
DEF(String, "String")
DEF(Boolean, "Boolean")
DEF(Symbol, "Symbol")
DEF(Arguments, "Arguments")
DEF(Math, "Math")
DEF(JSON, "JSON")
DEF(Date, "Date")

View File

@@ -123,8 +123,6 @@ enum {
JS_CLASS_STRING, /* u.object_data */
JS_CLASS_BOOLEAN, /* u.object_data */
JS_CLASS_SYMBOL, /* u.object_data */
JS_CLASS_ARGUMENTS, /* u.array | length */
JS_CLASS_MAPPED_ARGUMENTS, /* | length */
JS_CLASS_C_FUNCTION, /* u.cfunc */
JS_CLASS_BYTECODE_FUNCTION, /* u.func */
JS_CLASS_BOUND_FUNCTION, /* u.bound_function */
@@ -494,7 +492,6 @@ typedef struct JSFunctionBytecode {
uint8_t is_derived_class_constructor : 1;
uint8_t func_kind : 2;
uint8_t new_target_allowed : 1;
uint8_t arguments_allowed : 1;
uint8_t has_debug : 1;
uint8_t read_only_bytecode : 1;
uint8_t is_direct_or_indirect_eval : 1; /* used by JS_GetScriptOrModuleName() */
@@ -662,7 +659,7 @@ struct JSObject {
uint8_t extensible : 1;
uint8_t free_mark : 1; /* only used when freeing objects with cycles */
uint8_t is_exotic : 1; /* TRUE if object has exotic property handlers */
uint8_t fast_array : 1; /* TRUE if u.array is used for get/put (for JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS and typed arrays) */
uint8_t fast_array : 1; /* TRUE if u.array is used for get/put (for JS_CLASS_ARRAY and typed arrays) */
uint8_t is_constructor : 1; /* TRUE if object is a constructor function */
uint8_t has_immutable_prototype : 1; /* cannot modify the prototype */
uint8_t tmp_mark : 1; /* used in JS_WriteObjectRec() */
@@ -693,12 +690,12 @@ struct JSObject {
int16_t magic;
} cfunc;
/* array part for fast arrays and typed arrays */
struct { /* JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS, JS_CLASS_UINT8C_ARRAY..JS_CLASS_FLOAT64_ARRAY */
struct { /* JS_CLASS_ARRAY, JS_CLASS_UINT8C_ARRAY..JS_CLASS_FLOAT64_ARRAY */
union {
uint32_t size; /* JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS */
uint32_t size; /* JS_CLASS_ARRAY */
} u1;
union {
JSValue *values; /* JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS */
JSValue *values; /* JS_CLASS_ARRAY */
} u;
uint32_t count; /* <= 2^31-1. 0 for a detached typed array */
} array; /* 12/20 bytes */
@@ -940,7 +937,6 @@ static JSValue js_regexp_toString(JSContext *ctx, JSValueConst this_val,
static JSValue js_error_toString(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv);
static const JSClassExoticMethods js_arguments_exotic_methods;
static const JSClassExoticMethods js_string_exotic_methods;
static const JSClassExoticMethods js_proxy_exotic_methods;
static JSClassID js_class_id_alloc = JS_CLASS_INIT_COUNT;
@@ -1132,8 +1128,6 @@ static JSClassShortDef const js_std_class_def[] = {
{ JS_ATOM_String, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_STRING */
{ JS_ATOM_Boolean, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_BOOLEAN */
{ JS_ATOM_Symbol, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_SYMBOL */
{ JS_ATOM_Arguments, js_array_finalizer, js_array_mark }, /* JS_CLASS_ARGUMENTS */
{ JS_ATOM_Arguments, NULL, NULL }, /* JS_CLASS_MAPPED_ARGUMENTS */
{ JS_ATOM_Function, js_c_function_finalizer, js_c_function_mark }, /* JS_CLASS_C_FUNCTION */
{ JS_ATOM_Function, js_bytecode_function_finalizer, js_bytecode_function_mark }, /* JS_CLASS_BYTECODE_FUNCTION */
{ JS_ATOM_Function, js_bound_function_finalizer, js_bound_function_mark }, /* JS_CLASS_BOUND_FUNCTION */
@@ -1229,7 +1223,6 @@ JSRuntime *JS_NewRuntime2(const JSMallocFunctions *mf, void *opaque)
if (init_class_range(rt, js_std_class_def, JS_CLASS_OBJECT,
countof(js_std_class_def)) < 0)
goto fail;
rt->class_array[JS_CLASS_ARGUMENTS].exotic = &js_arguments_exotic_methods;
rt->class_array[JS_CLASS_STRING].exotic = &js_string_exotic_methods;
rt->class_array[JS_CLASS_C_FUNCTION].call = js_call_c_function;
@@ -4542,11 +4535,6 @@ static JSValue JS_NewObjectFromShape(JSContext *ctx, JSShape *sh, JSClassID clas
case JS_CLASS_C_FUNCTION:
p->prop[0].u.value = JS_NULL;
break;
case JS_CLASS_ARGUMENTS:
p->is_exotic = 1;
p->fast_array = 1;
p->u.array.count = 0;
break;
case JS_CLASS_NUMBER:
case JS_CLASS_STRING:
case JS_CLASS_BOOLEAN:
@@ -5647,7 +5635,6 @@ void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s)
switch(p->class_id) {
case JS_CLASS_ARRAY: /* u.array | length */
case JS_CLASS_ARGUMENTS: /* u.array | length */
s->array_count++;
if (p->fast_array) {
s->fast_array_count++;
@@ -7433,7 +7420,6 @@ static JSValue JS_GetPropertyValue(JSContext *ctx, JSValueConst this_obj,
idx = JS_VALUE_GET_INT(prop);
switch(p->class_id) {
case JS_CLASS_ARRAY:
case JS_CLASS_ARGUMENTS:
if (unlikely(idx >= p->u.array.count)) goto slow_path;
return JS_DupValue(ctx, p->u.array.u.values[idx]);
default:
@@ -7668,8 +7654,7 @@ static int delete_property(JSContext *ctx, JSObject *p, JSAtom atom)
uint32_t idx;
if (JS_AtomIsArrayIndex(ctx, &idx, atom) &&
idx < p->u.array.count) {
if (p->class_id == JS_CLASS_ARRAY ||
p->class_id == JS_CLASS_ARGUMENTS) {
if (p->class_id == JS_CLASS_ARRAY) {
/* Special case deleting the last element of a fast Array */
if (idx == p->u.array.count - 1) {
JS_FreeValue(ctx, p->u.array.u.values[idx]);
@@ -8174,11 +8159,6 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj,
}
set_value(ctx, &p->u.array.u.values[idx], val);
break;
case JS_CLASS_ARGUMENTS:
if (unlikely(idx >= (uint32_t)p->u.array.count))
goto slow_path;
set_value(ctx, &p->u.array.u.values[idx], val);
break;
default:
goto slow_path;
}
@@ -11590,136 +11570,10 @@ static JSValue js_function_proto_lineNumber(JSContext *ctx,
return JS_NULL;
}
static int js_arguments_define_own_property(JSContext *ctx,
JSValueConst this_obj,
JSAtom prop, JSValueConst val,
JSValueConst getter, JSValueConst setter, int flags)
{
JSObject *p;
uint32_t idx;
p = JS_VALUE_GET_OBJ(this_obj);
/* convert to normal array when redefining an existing numeric field */
if (p->fast_array && JS_AtomIsArrayIndex(ctx, &idx, prop) &&
idx < p->u.array.count) {
if (convert_fast_array_to_array(ctx, p))
return -1;
}
/* run the default define own property */
return JS_DefineProperty(ctx, this_obj, prop, val, getter, setter,
flags | JS_PROP_NO_EXOTIC);
}
static const JSClassExoticMethods js_arguments_exotic_methods = {
.define_own_property = js_arguments_define_own_property,
};
static JSValue js_build_arguments(JSContext *ctx, int argc, JSValueConst *argv)
{
JSValue val, *tab;
JSProperty *pr;
JSObject *p;
int i;
val = JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_OBJECT],
JS_CLASS_ARGUMENTS);
if (JS_IsException(val))
return val;
p = JS_VALUE_GET_OBJ(val);
/* add the length field (cannot fail) */
pr = add_property(ctx, p, JS_ATOM_length,
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
if (unlikely(!pr))
goto fail;
pr->u.value = JS_NewInt32(ctx, argc);
/* initialize the fast array part */
tab = NULL;
if (argc > 0) {
tab = js_malloc(ctx, sizeof(tab[0]) * argc);
if (!tab)
goto fail;
for(i = 0; i < argc; i++) {
tab[i] = JS_DupValue(ctx, argv[i]);
}
}
p->u.array.u.values = tab;
p->u.array.count = argc;
JS_DefinePropertyValue(ctx, val, JS_ATOM_Symbol_iterator,
JS_DupValue(ctx, ctx->array_proto_values),
JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE);
/* add callee property to throw a TypeError in strict mode */
JS_DefineProperty(ctx, val, JS_ATOM_callee, JS_NULL,
ctx->throw_type_error, ctx->throw_type_error,
JS_PROP_HAS_GET | JS_PROP_HAS_SET);
return val;
fail:
JS_FreeValue(ctx, val);
return JS_EXCEPTION;
}
#define GLOBAL_VAR_OFFSET 0x40000000
#define ARGUMENT_VAR_OFFSET 0x20000000
/* legacy arguments object: add references to the function arguments */
static JSValue js_build_mapped_arguments(JSContext *ctx, int argc,
JSValueConst *argv,
JSStackFrame *sf, int arg_count)
{
JSValue val;
JSProperty *pr;
JSObject *p;
int i;
val = JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_OBJECT],
JS_CLASS_MAPPED_ARGUMENTS);
if (JS_IsException(val))
return val;
p = JS_VALUE_GET_OBJ(val);
/* add the length field (cannot fail) */
pr = add_property(ctx, p, JS_ATOM_length,
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
if (unlikely(!pr))
goto fail;
pr->u.value = JS_NewInt32(ctx, argc);
for(i = 0; i < arg_count; i++) {
JSVarRef *var_ref;
var_ref = get_var_ref(ctx, sf, i, TRUE);
if (!var_ref)
goto fail;
pr = add_property(ctx, p, __JS_AtomFromUInt32(i), JS_PROP_C_W_E | JS_PROP_VARREF);
if (!pr) {
free_var_ref(ctx->rt, var_ref);
goto fail;
}
pr->u.var_ref = var_ref;
}
/* the arguments not mapped to the arguments of the function can
be normal properties */
for(i = arg_count; i < argc; i++) {
if (JS_DefinePropertyValueUint32(ctx, val, i,
JS_DupValue(ctx, argv[i]),
JS_PROP_C_W_E) < 0)
goto fail;
}
JS_DefinePropertyValue(ctx, val, JS_ATOM_Symbol_iterator,
JS_DupValue(ctx, ctx->array_proto_values),
JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE);
/* callee returns this function in non strict mode */
JS_DefinePropertyValue(ctx, val, JS_ATOM_callee,
JS_DupValue(ctx, ctx->rt->current_stack_frame->cur_func),
JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE);
return val;
fail:
JS_FreeValue(ctx, val);
return JS_EXCEPTION;
}
static JSValue js_build_rest(JSContext *ctx, int first, int argc, JSValueConst *argv)
{
JSValue val;
@@ -12868,8 +12722,6 @@ static JSValue js_call_bound_function(JSContext *ctx, JSValueConst func_obj,
/* argument of OP_special_object */
typedef enum {
OP_SPECIAL_OBJECT_ARGUMENTS,
OP_SPECIAL_OBJECT_MAPPED_ARGUMENTS,
OP_SPECIAL_OBJECT_THIS_FUNC,
OP_SPECIAL_OBJECT_NEW_TARGET,
OP_SPECIAL_OBJECT_VAR_OBJECT,
@@ -13081,17 +12933,6 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
{
int arg = *pc++;
switch(arg) {
case OP_SPECIAL_OBJECT_ARGUMENTS:
*sp++ = js_build_arguments(ctx, argc, (JSValueConst *)argv);
if (unlikely(JS_IsException(sp[-1])))
goto exception;
break;
case OP_SPECIAL_OBJECT_MAPPED_ARGUMENTS:
*sp++ = js_build_mapped_arguments(ctx, argc, (JSValueConst *)argv,
sf, min_int(argc, b->arg_count));
if (unlikely(JS_IsException(sp[-1])))
goto exception;
break;
case OP_SPECIAL_OBJECT_THIS_FUNC:
*sp++ = JS_DupValue(ctx, sf->cur_func);
break;
@@ -15558,13 +15399,10 @@ typedef struct JSFunctionDef {
BOOL has_parameter_expressions; /* if true, an argument scope is created */
BOOL has_use_strict; /* to reject directive in special cases */
BOOL has_eval_call; /* true if the function contains a call to eval() */
BOOL has_arguments_binding; /* true if the 'arguments' binding is
available in the function */
BOOL has_this_binding; /* true if the 'this' and new.target binding are
available in the function */
BOOL new_target_allowed; /* true if the 'new.target' does not
throw a syntax error */
BOOL arguments_allowed; /* true if the 'arguments' identifier is allowed */
BOOL is_derived_class_constructor;
BOOL in_function_body;
JSParseFunctionEnum func_type : 8;
@@ -15580,9 +15418,6 @@ typedef struct JSFunctionDef {
int defined_arg_count;
int var_object_idx; /* -1 if none */
int arg_var_object_idx; /* -1 if none (var object for the argument scope) */
int arguments_var_idx; /* -1 if none */
int arguments_arg_idx; /* argument variable definition in argument scope,
-1 if none */
int func_var_idx; /* variable containing the current function (-1
if none, only used if is_func_expr is true) */
int eval_ret_idx; /* variable containing the return value of the eval, -1 if none */
@@ -17657,39 +17492,6 @@ static int add_func_var(JSContext *ctx, JSFunctionDef *fd, JSAtom name)
return idx;
}
static int add_arguments_var(JSContext *ctx, JSFunctionDef *fd)
{
int idx = fd->arguments_var_idx;
if (idx < 0 && (idx = add_var(ctx, fd, JS_ATOM_arguments)) >= 0) {
fd->arguments_var_idx = idx;
}
return idx;
}
/* add an argument definition in the argument scope. Only needed when
"eval()" may be called in the argument scope. Return 0 if OK. */
static int add_arguments_arg(JSContext *ctx, JSFunctionDef *fd)
{
int idx;
if (fd->arguments_arg_idx < 0) {
idx = find_var_in_scope(ctx, fd, JS_ATOM_arguments, ARG_SCOPE_INDEX);
if (idx < 0) {
/* XXX: the scope links are not fully updated. May be an
issue if there are child scopes of the argument
scope */
idx = add_var(ctx, fd, JS_ATOM_arguments);
if (idx < 0)
return -1;
fd->vars[idx].scope_next = fd->scopes[ARG_SCOPE_INDEX].first;
fd->scopes[ARG_SCOPE_INDEX].first = idx;
fd->vars[idx].scope_level = ARG_SCOPE_INDEX;
fd->vars[idx].is_lexical = TRUE;
fd->arguments_arg_idx = idx;
}
}
return 0;
}
static int add_arg(JSContext *ctx, JSFunctionDef *fd, JSAtom name)
{
@@ -17856,8 +17658,6 @@ static int define_var(JSParseState *s, JSFunctionDef *fd, JSAtom name,
break;
idx = add_var(ctx, fd, name);
if (idx >= 0) {
if (name == JS_ATOM_arguments && fd->has_arguments_binding)
fd->arguments_var_idx = idx;
fd->vars[idx].scope_next = fd->scope_level;
}
}
@@ -18646,8 +18446,7 @@ static __exception int get_lvalue(JSParseState *s, int *popcode, int *pscope,
case OP_scope_get_var:
name = get_u32(fd->byte_code.buf + fd->last_opcode_pos + 1);
scope = get_u16(fd->byte_code.buf + fd->last_opcode_pos + 5);
if ((name == JS_ATOM_arguments || name == JS_ATOM_eval) &&
(fd->js_mode & JS_MODE_STRICT)) {
if (name == JS_ATOM_eval && (fd->js_mode & JS_MODE_STRICT)) {
return js_parse_error(s, "invalid lvalue in strict mode");
}
if (name == JS_ATOM_this || name == JS_ATOM_new_target)
@@ -18842,8 +18641,7 @@ static __exception int js_define_var(JSParseState *s, JSAtom name, int tok)
JSFunctionDef *fd = s->cur_func;
JSVarDefEnum var_def_type;
if ((name == JS_ATOM_arguments || name == JS_ATOM_eval)
&& (fd->js_mode & JS_MODE_STRICT)) {
if (name == JS_ATOM_eval && (fd->js_mode & JS_MODE_STRICT)) {
return js_parse_error(s, "invalid variable name in strict mode");
}
if (name == JS_ATOM_let
@@ -18941,7 +18739,7 @@ static JSAtom js_parse_destructuring_var(JSParseState *s, int tok, int is_arg)
if (!(s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved)
|| ((s->cur_func->js_mode & JS_MODE_STRICT) &&
(s->token.u.ident.atom == JS_ATOM_eval || s->token.u.ident.atom == JS_ATOM_arguments))) {
(s->token.u.ident.atom == JS_ATOM_eval))) {
js_parse_error(s, "invalid destructuring target");
return JS_ATOM_NULL;
}
@@ -19190,7 +18988,7 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
if (is_arg && js_parse_check_duplicate_parameter(s, prop_name))
goto prop_error;
if ((s->cur_func->js_mode & JS_MODE_STRICT) &&
(prop_name == JS_ATOM_eval || prop_name == JS_ATOM_arguments)) {
(prop_name == JS_ATOM_eval)) {
js_parse_error(s, "invalid destructuring target");
goto prop_error;
}
@@ -19553,11 +19351,6 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags)
return js_parse_error_reserved_identifier(s);
}
source_ptr = s->token.ptr;
if (s->token.u.ident.atom == JS_ATOM_arguments &&
!s->cur_func->arguments_allowed) {
js_parse_error(s, "'arguments' identifier is not allowed in class field initializer");
return -1;
}
name = JS_DupAtom(s->ctx, s->token.u.ident.atom);
if (next_token(s)) {
JS_FreeAtom(s->ctx, name);
@@ -21800,8 +21593,6 @@ static JSFunctionDef *js_new_function_def(JSContext *ctx,
fd->func_name = JS_ATOM_NULL;
fd->var_object_idx = -1;
fd->arg_var_object_idx = -1;
fd->arguments_var_idx = -1;
fd->arguments_arg_idx = -1;
fd->func_var_idx = -1;
fd->eval_ret_idx = -1;
fd->this_var_idx = -1;
@@ -22669,11 +22460,6 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s,
if (var_idx < 0 && is_pseudo_var)
var_idx = resolve_pseudo_var(ctx, s, var_name);
if (var_idx < 0 && var_name == JS_ATOM_arguments &&
s->has_arguments_binding) {
/* 'arguments' pseudo variable */
var_idx = add_arguments_var(ctx, s);
}
if (var_idx < 0 && s->is_func_expr && var_name == s->func_name) {
/* add a new variable with the function name */
var_idx = add_func_var(ctx, s, var_name);
@@ -22828,10 +22614,6 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s,
if (var_idx >= 0)
break;
}
if (var_name == JS_ATOM_arguments && fd->has_arguments_binding) {
var_idx = add_arguments_var(ctx, fd);
break;
}
if (fd->is_func_expr && fd->func_name == var_name) {
/* add a new variable with the function name */
var_idx = add_func_var(ctx, fd, var_name);
@@ -23072,7 +22854,7 @@ static void add_eval_variables(JSContext *ctx, JSFunctionDef *s)
JSFunctionDef *fd;
JSVarDef *vd;
int i, scope_level, scope_idx;
BOOL has_arguments_binding, has_this_binding, is_arg_scope;
BOOL has_this_binding, is_arg_scope;
/* in non strict mode, variables are created in the caller's
environment object */
@@ -23095,15 +22877,6 @@ static void add_eval_variables(JSContext *ctx, JSFunctionDef *s)
if (s->is_derived_class_constructor && s->this_active_func_var_idx < 0)
s->this_active_func_var_idx = add_var(ctx, s, JS_ATOM_this_active_func);
}
has_arguments_binding = s->has_arguments_binding;
if (has_arguments_binding) {
add_arguments_var(ctx, s);
/* also add an arguments binding in the argument scope to
raise an error if a direct eval in the argument scope tries
to redefine it */
if (s->has_parameter_expressions && !(s->js_mode & JS_MODE_STRICT))
add_arguments_arg(ctx, s);
}
if (s->is_func_expr && s->func_name != JS_ATOM_NULL)
add_func_var(ctx, s, s->func_name);
@@ -23130,11 +22903,6 @@ static void add_eval_variables(JSContext *ctx, JSFunctionDef *s)
fd->this_active_func_var_idx = add_var(ctx, fd, JS_ATOM_this_active_func);
has_this_binding = TRUE;
}
/* add 'arguments' if it was not previously added */
if (!has_arguments_binding && fd->has_arguments_binding) {
add_arguments_var(ctx, fd);
has_arguments_binding = TRUE;
}
/* add function name */
if (fd->is_func_expr && fd->func_name != JS_ATOM_NULL)
add_func_var(ctx, fd, fd->func_name);
@@ -23819,8 +23587,9 @@ static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s)
for(scope_idx = s->scopes[scope].first; scope_idx >= 0;) {
JSVarDef *vd = &s->vars[scope_idx];
if (vd->scope_level == scope) {
if (scope_idx != s->arguments_arg_idx) {
if (vd->scope_level != scope)
break;
if (vd->var_kind == JS_VAR_FUNCTION_DECL ||
vd->var_kind == JS_VAR_NEW_FUNCTION_DECL) {
/* Initialize lexical variable upon entering scope */
@@ -23834,11 +23603,8 @@ static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s)
dbuf_putc(&bc_out, OP_set_loc_uninitialized);
dbuf_put_u16(&bc_out, scope_idx);
}
}
scope_idx = vd->scope_next;
} else {
break;
}
}
}
break;
@@ -24267,19 +24033,6 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s)
put_short_code(&bc_out, OP_put_loc, s->this_var_idx);
}
}
/* initialize the 'arguments' variable if needed */
if (s->arguments_var_idx >= 0) {
if ((s->js_mode & JS_MODE_STRICT) || !s->has_simple_parameter_list) {
dbuf_putc(&bc_out, OP_special_object);
dbuf_putc(&bc_out, OP_SPECIAL_OBJECT_ARGUMENTS);
} else {
dbuf_putc(&bc_out, OP_special_object);
dbuf_putc(&bc_out, OP_SPECIAL_OBJECT_MAPPED_ARGUMENTS);
}
if (s->arguments_arg_idx >= 0)
put_short_code(&bc_out, OP_set_loc, s->arguments_arg_idx);
put_short_code(&bc_out, OP_put_loc, s->arguments_var_idx);
}
/* initialize a reference to the current function if needed */
if (s->func_var_idx >= 0) {
dbuf_putc(&bc_out, OP_special_object);
@@ -25444,7 +25197,6 @@ static JSValue js_create_function(JSContext *ctx, JSFunctionDef *fd)
b->js_mode = fd->js_mode;
b->is_derived_class_constructor = fd->is_derived_class_constructor;
b->new_target_allowed = fd->new_target_allowed;
b->arguments_allowed = fd->arguments_allowed;
b->is_direct_or_indirect_eval = (fd->eval_type == JS_EVAL_TYPE_DIRECT ||
fd->eval_type == JS_EVAL_TYPE_INDIRECT);
b->realm = JS_DupContext(ctx);
@@ -25607,15 +25359,13 @@ static int js_parse_function_check_names(JSParseState *s, JSFunctionDef *fd,
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");
}
if (func_name == JS_ATOM_eval || func_name == JS_ATOM_arguments ||
is_strict_future_keyword(func_name)) {
if (func_name == JS_ATOM_eval || is_strict_future_keyword(func_name)) {
return js_parse_error(s, "invalid function name in strict code");
}
for (idx = 0; idx < fd->arg_count; idx++) {
name = fd->args[idx].var_name;
if (name == JS_ATOM_eval || name == JS_ATOM_arguments ||
is_strict_future_keyword(name)) {
if (name == JS_ATOM_eval || is_strict_future_keyword(name)) {
return js_parse_error(s, "invalid argument name in strict code");
}
}
@@ -25708,8 +25458,7 @@ static __exception int js_parse_function_decl2(JSParseState *s,
if (func_type == JS_PARSE_FUNC_VAR) {
if (!(fd->js_mode & JS_MODE_STRICT)
&& 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_name == JS_ATOM_arguments && fd->has_arguments_binding)) {
&& !((func_idx = find_var(ctx, fd, func_name)) >= 0 && (func_idx & ARGUMENT_VAR_OFFSET))) {
create_func_var = TRUE;
}
/* Create the lexical name here so that the function closure
@@ -25756,19 +25505,15 @@ static __exception int js_parse_function_decl2(JSParseState *s,
func_type == JS_PARSE_FUNC_VAR ||
func_type == JS_PARSE_FUNC_EXPR);
fd->has_arguments_binding = (func_type != JS_PARSE_FUNC_ARROW &&
fd->has_this_binding = (func_type != JS_PARSE_FUNC_ARROW &&
func_type != JS_PARSE_FUNC_CLASS_STATIC_INIT);
fd->has_this_binding = fd->has_arguments_binding;
fd->is_derived_class_constructor = (func_type == JS_PARSE_FUNC_DERIVED_CLASS_CONSTRUCTOR);
if (func_type == JS_PARSE_FUNC_ARROW) {
fd->new_target_allowed = fd->parent->new_target_allowed;
fd->arguments_allowed = fd->parent->arguments_allowed;
} else if (func_type == JS_PARSE_FUNC_CLASS_STATIC_INIT) {
fd->new_target_allowed = TRUE; // although new.target === undefined
fd->arguments_allowed = FALSE;
} else {
fd->new_target_allowed = TRUE;
fd->arguments_allowed = TRUE;
}
/* fd->in_function_body == FALSE prevents yield/await during the parsing
@@ -26276,10 +26021,8 @@ static JSValue __JS_EvalInternal(JSContext *ctx, JSValueConst this_obj,
fd->has_this_binding = (eval_type != JS_EVAL_TYPE_DIRECT);
if (eval_type == JS_EVAL_TYPE_DIRECT) {
fd->new_target_allowed = b->new_target_allowed;
fd->arguments_allowed = b->arguments_allowed;
} else {
fd->new_target_allowed = FALSE;
fd->arguments_allowed = TRUE;
}
fd->js_mode = js_mode;
fd->func_name = JS_DupAtom(ctx, JS_ATOM__eval_);
@@ -26780,7 +26523,6 @@ static int JS_WriteFunctionTag(BCWriterState *s, JSValueConst obj)
bc_set_flags(&flags, &idx, b->is_derived_class_constructor, 1);
bc_set_flags(&flags, &idx, b->func_kind, 2);
bc_set_flags(&flags, &idx, b->new_target_allowed, 1);
bc_set_flags(&flags, &idx, b->arguments_allowed, 1);
bc_set_flags(&flags, &idx, b->has_debug, 1);
bc_set_flags(&flags, &idx, b->is_direct_or_indirect_eval, 1);
assert(idx <= 16);
@@ -27483,7 +27225,6 @@ static JSValue JS_ReadFunctionTag(BCReaderState *s)
bc.is_derived_class_constructor = bc_get_flags(v16, &idx, 1);
bc.func_kind = bc_get_flags(v16, &idx, 2);
bc.new_target_allowed = bc_get_flags(v16, &idx, 1);
bc.arguments_allowed = bc_get_flags(v16, &idx, 1);
bc.has_debug = bc_get_flags(v16, &idx, 1);
bc.is_direct_or_indirect_eval = bc_get_flags(v16, &idx, 1);
bc.read_only_bytecode = s->is_rom_data;
@@ -28871,8 +28612,6 @@ static JSValue js_object_toString(JSContext *ctx, JSValueConst this_val,
p = JS_VALUE_GET_OBJ(obj);
switch(p->class_id) {
case JS_CLASS_STRING:
case JS_CLASS_ARGUMENTS:
case JS_CLASS_MAPPED_ARGUMENTS:
case JS_CLASS_ERROR:
case JS_CLASS_BOOLEAN:
case JS_CLASS_NUMBER:
@@ -29567,7 +29306,7 @@ static JSValue *build_arg_list(JSContext *ctx, uint32_t *plen,
if (!tab)
return NULL;
p = JS_VALUE_GET_OBJ(array_arg);
if ((p->class_id == JS_CLASS_ARRAY || p->class_id == JS_CLASS_ARGUMENTS) &&
if ((p->class_id == JS_CLASS_ARRAY) &&
p->fast_array &&
len == p->u.array.count) {
for(i = 0; i < len; i++) {
@@ -38839,15 +38578,11 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx)
ctx->throw_type_error = JS_NewCFunction(ctx, js_throw_type_error, NULL, 0);
/* add caller and arguments properties to throw a TypeError */
/* add caller property to throw a TypeError */
JS_DefineProperty(ctx, ctx->function_proto, JS_ATOM_caller, JS_NULL,
ctx->throw_type_error, ctx->throw_type_error,
JS_PROP_HAS_GET | JS_PROP_HAS_SET |
JS_PROP_HAS_CONFIGURABLE | JS_PROP_CONFIGURABLE);
JS_DefineProperty(ctx, ctx->function_proto, JS_ATOM_arguments, JS_NULL,
ctx->throw_type_error, ctx->throw_type_error,
JS_PROP_HAS_GET | JS_PROP_HAS_SET |
JS_PROP_HAS_CONFIGURABLE | JS_PROP_CONFIGURABLE);
JS_FreeValue(ctx, js_object_seal(ctx, JS_NULL, 1, (JSValueConst *)&ctx->throw_type_error, 1));
ctx->global_obj = JS_NewObject(ctx);
@@ -38934,7 +38669,6 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx)
JS_PROP_CONFIGURABLE);
}
/* needed to initialize arguments[Symbol.iterator] */
ctx->array_proto_values =
JS_GetProperty(ctx, ctx->class_proto[JS_CLASS_ARRAY], JS_ATOM_values);