no more string class type

This commit is contained in:
2026-01-21 17:36:19 -06:00
parent 4da63db16e
commit aa847ddf6e

View File

@@ -172,17 +172,13 @@ enum {
JS_CLASS_OBJECT = 1, /* must be first */
JS_CLASS_ARRAY, /* u.array | length */
JS_CLASS_ERROR,
JS_CLASS_NUMBER, /* u.object_data */
JS_CLASS_STRING, /* u.object_data */
JS_CLASS_BOOLEAN, /* u.object_data */
JS_CLASS_SYMBOL, /* u.object_data */
JS_CLASS_C_FUNCTION, /* u.cfunc */
JS_CLASS_BYTECODE_FUNCTION, /* u.func */
JS_CLASS_BOUND_FUNCTION, /* u.bound_function */
JS_CLASS_C_FUNCTION_DATA, /* u.c_function_data_record */
JS_CLASS_REGEXP, /* u.regexp */
JS_CLASS_FINALIZATION_REGISTRY,
JS_CLASS_BLOB, /* u.opaque (blob *) */
JS_CLASS_BLOB, /* u.opaque (blob *) */
JS_CLASS_INIT_COUNT, /* last entry for predefined classes */
};
@@ -591,9 +587,7 @@ typedef struct JSFunctionBytecode {
uint8_t js_mode;
uint8_t has_prototype : 1; /* true if a prototype field is necessary */
uint8_t has_simple_parameter_list : 1;
uint8_t is_derived_class_constructor : 1;
uint8_t func_kind : 2;
uint8_t new_target_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() */
@@ -701,52 +695,6 @@ typedef struct JSRegExp {
JSString *bytecode; /* also contains the flags */
} JSRegExp;
typedef enum {
/* binary operators */
JS_OVOP_ADD,
JS_OVOP_SUB,
JS_OVOP_MUL,
JS_OVOP_DIV,
JS_OVOP_MOD,
JS_OVOP_POW,
JS_OVOP_OR,
JS_OVOP_AND,
JS_OVOP_XOR,
JS_OVOP_SHL,
JS_OVOP_SAR,
JS_OVOP_SHR,
JS_OVOP_LESS,
JS_OVOP_BINARY_COUNT,
/* unary operators */
JS_OVOP_POS = JS_OVOP_BINARY_COUNT,
JS_OVOP_NEG,
JS_OVOP_INC,
JS_OVOP_DEC,
JS_OVOP_NOT,
JS_OVOP_COUNT,
} JSOverloadableOperatorEnum;
typedef struct {
uint32_t operator_index;
JSObject *ops[JS_OVOP_BINARY_COUNT]; /* self operators */
} JSBinaryOperatorDefEntry;
typedef struct {
int count;
JSBinaryOperatorDefEntry *tab;
} JSBinaryOperatorDef;
typedef struct {
uint32_t operator_counter;
BOOL is_primitive; /* OperatorSet for a primitive type */
/* NULL if no operator is defined */
JSObject *self_ops[JS_OVOP_COUNT]; /* self operators */
JSBinaryOperatorDef left;
JSBinaryOperatorDef right;
} JSOperatorSetData;
typedef struct JSProperty {
union {
JSValue value; /* JS_PROP_NORMAL */
@@ -830,18 +778,17 @@ struct JSObject {
uint8_t cproto;
int16_t magic;
} cfunc;
/* array part for fast arrays and typed arrays */
struct { /* JS_CLASS_ARRAY, JS_CLASS_UINT8C_ARRAY..JS_CLASS_FLOAT64_ARRAY */
/* array part for fast arrays */
struct { /* JS_CLASS_ARRAY */
union {
uint32_t size; /* JS_CLASS_ARRAY */
} u1;
union {
JSValue *values; /* JS_CLASS_ARRAY */
} u;
uint32_t count; /* <= 2^31-1. 0 for a detached typed array */
uint32_t count; /* <= 2^31-1 */
} array; /* 12/20 bytes */
JSRegExp regexp; /* JS_CLASS_REGEXP: 8/16 bytes */
JSValue object_data; /* for JS_SetObjectData(): 8/16/16 bytes */
} u;
};
@@ -927,8 +874,6 @@ static JSValue js_function_apply(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv, int magic);
static void js_array_finalizer(JSRuntime *rt, JSValue val);
static void js_array_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func);
static void js_object_data_finalizer(JSRuntime *rt, JSValue val);
static void js_object_data_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func);
static void js_c_function_finalizer(JSRuntime *rt, JSValue val);
static void js_c_function_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func);
static void js_bytecode_function_finalizer(JSRuntime *rt, JSValue val);
@@ -940,10 +885,8 @@ static void js_bound_function_mark(JSRuntime *rt, JSValueConst val,
static void js_regexp_finalizer(JSRuntime *rt, JSValue val);
#define HINT_STRING 0
#define HINT_NUMBER 1
#define HINT_NONE 2
#define HINT_FORCE_ORDINARY (1 << 4) // don't try Symbol.toPrimitive
static JSValue JS_ToPrimitiveFree(JSContext *ctx, JSValue val, int hint);
static JSValue JS_ToStringFree(JSContext *ctx, JSValue val);
static int JS_ToBoolFree(JSContext *ctx, JSValue val);
static int JS_ToInt32Free(JSContext *ctx, int32_t *pres, JSValue val);
@@ -1032,7 +975,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_string_exotic_methods;
JSClassID js_class_id_alloc = JS_CLASS_INIT_COUNT;
static void js_trigger_gc(JSRuntime *rt, size_t size)
@@ -1217,16 +1159,12 @@ typedef struct JSClassShortDef {
static JSClassShortDef const js_std_class_def[] = {
{ JS_ATOM_Object, NULL, NULL }, /* JS_CLASS_OBJECT */
{ JS_ATOM_Array, js_array_finalizer, js_array_mark }, /* JS_CLASS_ARRAY */
{ JS_ATOM_Error, NULL, NULL }, /* JS_CLASS_ERROR */
{ JS_ATOM_Number, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_NUMBER */
{ 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_Error, NULL, NULL }, /* JS_CLASS_ERROR */
{ 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 */
{ JS_ATOM_Function, js_c_function_data_finalizer, js_c_function_data_mark }, /* JS_CLASS_C_FUNCTION_DATA */
{ JS_ATOM_RegExp, js_regexp_finalizer, NULL }, /* JS_CLASS_REGEXP */
{ JS_ATOM_RegExp, js_regexp_finalizer, NULL }, /* JS_CLASS_REGEXP */
};
static int init_class_range(JSRuntime *rt, JSClassShortDef const *tab,
@@ -1309,8 +1247,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_STRING].exotic = &js_string_exotic_methods;
rt->class_array[JS_CLASS_C_FUNCTION].call = js_call_c_function;
rt->class_array[JS_CLASS_C_FUNCTION_DATA].call = js_c_function_data_call;
rt->class_array[JS_CLASS_BOUND_FUNCTION].call = js_call_bound_function;
@@ -4785,18 +4721,14 @@ 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_NUMBER:
case JS_CLASS_STRING:
case JS_CLASS_BOOLEAN:
case JS_CLASS_SYMBOL:
p->u.object_data = JS_NULL;
goto set_exotic;
case JS_CLASS_REGEXP:
p->u.regexp.pattern = NULL;
p->u.regexp.bytecode = NULL;
goto set_exotic;
if (ctx->rt->class_array[class_id].exotic) {
p->is_exotic = 1;
}
break;
default:
set_exotic:
if (ctx->rt->class_array[class_id].exotic) {
p->is_exotic = 1;
}
@@ -4834,30 +4766,6 @@ JSValue JS_NewObjectProtoClass(JSContext *ctx, JSValueConst proto_val,
return JS_NewObjectFromShape(ctx, sh, class_id);
}
static int JS_SetObjectData(JSContext *ctx, JSValueConst obj, JSValue val)
{
JSObject *p;
if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) {
p = JS_VALUE_GET_OBJ(obj);
switch(p->class_id) {
case JS_CLASS_NUMBER:
case JS_CLASS_STRING:
case JS_CLASS_BOOLEAN:
case JS_CLASS_SYMBOL:
JS_FreeValue(ctx, p->u.object_data);
p->u.object_data = val; /* for JS_CLASS_STRING, 'val' must
be JS_TAG_STRING (and not a
rope) */
return 0;
}
}
JS_FreeValue(ctx, val);
if (!JS_IsException(obj))
JS_ThrowTypeError(ctx, "invalid object type");
return -1;
}
JSValue JS_NewObjectClass(JSContext *ctx, int class_id)
{
return JS_NewObjectProtoClass(ctx, ctx->class_proto[class_id], class_id);
@@ -5205,20 +5113,6 @@ static void js_array_mark(JSRuntime *rt, JSValueConst val,
}
}
static void js_object_data_finalizer(JSRuntime *rt, JSValue val)
{
JSObject *p = JS_VALUE_GET_OBJ(val);
JS_FreeValueRT(rt, p->u.object_data);
p->u.object_data = JS_NULL;
}
static void js_object_data_mark(JSRuntime *rt, JSValueConst val,
JS_MarkFunc *mark_func)
{
JSObject *p = JS_VALUE_GET_OBJ(val);
JS_MarkValue(rt, p->u.object_data, mark_func);
}
static void js_c_function_finalizer(JSRuntime *rt, JSValue val)
{
JSObject *p = JS_VALUE_GET_OBJ(val);
@@ -5865,12 +5759,6 @@ void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s)
}
}
break;
case JS_CLASS_NUMBER: /* u.object_data */
case JS_CLASS_STRING: /* u.object_data */
case JS_CLASS_BOOLEAN: /* u.object_data */
case JS_CLASS_SYMBOL: /* u.object_data */
compute_value_size(p->u.object_data, hp);
break;
case JS_CLASS_C_FUNCTION: /* u.cfunc */
s->c_func_count++;
break;
@@ -6895,21 +6783,6 @@ JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj,
}
}
static uint32_t js_string_obj_get_length(JSContext *ctx,
JSValueConst obj)
{
JSObject *p;
uint32_t len = 0;
/* This is a class exotic method: obj class_id is JS_CLASS_STRING */
p = JS_VALUE_GET_OBJ(obj);
if (JS_VALUE_GET_TAG(p->u.object_data) == JS_TAG_STRING) {
JSString *p1 = JS_VALUE_GET_STRING(p->u.object_data);
len = p1->len;
}
return len;
}
static int num_keys_cmp(const void *p1, const void *p2, void *opaque)
{
JSContext *ctx = opaque;
@@ -7005,11 +6878,7 @@ static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx,
if (flags & JS_GPN_STRING_MASK) {
num_keys_count += p->u.array.count;
}
} else if (p->class_id == JS_CLASS_STRING) {
if (flags & JS_GPN_STRING_MASK) {
num_keys_count += js_string_obj_get_length(ctx, JS_MKPTR(JS_TAG_OBJECT, p));
}
}
}
}
/* fill them */
@@ -7067,16 +6936,9 @@ static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx,
}
if (p->is_exotic) {
int len;
if (p->fast_array) {
if (flags & JS_GPN_STRING_MASK) {
len = p->u.array.count;
goto add_array_keys;
}
} else if (p->class_id == JS_CLASS_STRING) {
if (flags & JS_GPN_STRING_MASK) {
len = js_string_obj_get_length(ctx, JS_MKPTR(JS_TAG_OBJECT, p));
add_array_keys:
int len = p->u.array.count;
for(i = 0; i < len; i++) {
tab_atom[num_index].atom = __JS_AtomFromUInt32(i);
if (tab_atom[num_index].atom == JS_ATOM_NULL) {
@@ -9180,32 +9042,6 @@ void *JS_GetAnyOpaque(JSValueConst obj, JSClassID *class_id)
return p->u.opaque;
}
static JSValue JS_ToPrimitiveFree(JSContext *ctx, JSValue val, int hint)
{
JSValue ret;
if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT)
return val;
hint &= ~HINT_FORCE_ORDINARY;
/* For string/default hint, use text() to convert */
if (hint == HINT_STRING || hint == HINT_NONE) {
ret = js_cell_text(ctx, JS_NULL, 1, (JSValueConst *)&val);
JS_FreeValue(ctx, val);
return ret;
}
/* For number hint, objects cannot be converted */
JS_FreeValue(ctx, val);
return JS_ThrowTypeError(ctx, "cannot convert record to number");
}
static JSValue JS_ToPrimitive(JSContext *ctx, JSValueConst val, int hint)
{
return JS_ToPrimitiveFree(ctx, JS_DupValue(ctx, val), hint);
}
static int JS_ToBoolFree(JSContext *ctx, JSValue val)
{
uint32_t tag = JS_VALUE_GET_TAG(val);
@@ -11579,7 +11415,6 @@ static JSValue js_call_bound_function(JSContext *ctx, JSValueConst func_obj,
/* argument of OP_special_object */
typedef enum {
OP_SPECIAL_OBJECT_THIS_FUNC,
OP_SPECIAL_OBJECT_NEW_TARGET,
OP_SPECIAL_OBJECT_VAR_OBJECT,
} OPSpecialObjectEnum;
@@ -12090,10 +11925,6 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
case OP_SPECIAL_OBJECT_THIS_FUNC:
*sp++ = JS_DupValue(ctx, sf->cur_func);
break;
case OP_SPECIAL_OBJECT_NEW_TARGET:
/* new.target is always null (constructors not supported) */
*sp++ = JS_NULL;
break;
case OP_SPECIAL_OBJECT_VAR_OBJECT:
*sp++ = JS_NewObjectProto(ctx, JS_NULL);
if (unlikely(JS_IsException(sp[-1])))
@@ -14379,16 +14210,6 @@ static JSContext *JS_GetFunctionRealm(JSContext *ctx, JSValueConst func_obj)
return realm;
}
static JSValue js_create_from_ctor(JSContext *ctx, JSValueConst ctor,
int class_id)
{
/* Simplified: always use the default class prototype */
JSValue proto = JS_DupValue(ctx, ctx->class_proto[class_id]);
JSValue obj = JS_NewObjectProtoClass(ctx, proto, class_id);
JS_FreeValue(ctx, proto);
return obj;
}
JSValue JS_Invoke(JSContext *ctx, JSValueConst this_val, JSAtom atom,
int argc, JSValueConst *argv)
{
@@ -14602,11 +14423,7 @@ 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_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 is_derived_class_constructor;
BOOL has_this_binding; /* true if the 'this' binding is available in the function */
BOOL in_function_body;
JSParseFunctionEnum func_type : 8;
uint8_t js_mode; /* bitmap of JS_MODE_x */
@@ -14625,7 +14442,6 @@ typedef struct JSFunctionDef {
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 */
int this_var_idx; /* variable containg the 'this' value, -1 if none */
int new_target_var_idx; /* variable containg the 'new.target' value, -1 if none */
int this_active_func_var_idx; /* variable containg the 'this.active_func' value, -1 if none */
int scope_level; /* index into fd->scopes if the current lexical scope */
@@ -20172,7 +19988,6 @@ static JSFunctionDef *js_new_function_def(JSContext *ctx,
fd->func_var_idx = -1;
fd->eval_ret_idx = -1;
fd->this_var_idx = -1;
fd->new_target_var_idx = -1;
fd->this_active_func_var_idx = -1;
/* XXX: should distinguish arg, var and var object and body scopes */
@@ -20918,15 +20733,7 @@ static int optimize_scope_make_global_ref(JSContext *ctx, JSFunctionDef *s,
static int add_var_this(JSContext *ctx, JSFunctionDef *fd)
{
int idx;
idx = add_var(ctx, fd, JS_ATOM_this);
if (idx >= 0 && fd->is_derived_class_constructor) {
JSVarDef *vd = &fd->vars[idx];
/* XXX: should have is_this flag or var type */
vd->is_lexical = 1; /* used to trigger 'uninitialized' checks
in a derived class constructor */
}
return idx;
return add_var(ctx, fd, JS_ATOM_this);
}
static int resolve_pseudo_var(JSContext *ctx, JSFunctionDef *s,
@@ -20944,10 +20751,8 @@ static int resolve_pseudo_var(JSContext *ctx, JSFunctionDef *s,
var_idx = s->this_active_func_var_idx;
break;
case JS_ATOM_new_target:
/* 'new.target' pseudo variable */
if (s->new_target_var_idx < 0)
s->new_target_var_idx = add_var(ctx, s, var_name);
var_idx = s->new_target_var_idx;
/* 'new.target' not supported - constructors removed */
var_idx = -1;
break;
case JS_ATOM_this:
/* 'this' pseudo variable */
@@ -21422,10 +21227,6 @@ static void add_eval_variables(JSContext *ctx, JSFunctionDef *s)
if (has_this_binding) {
if (s->this_var_idx < 0)
s->this_var_idx = add_var_this(ctx, s);
if (s->new_target_var_idx < 0)
s->new_target_var_idx = add_var(ctx, s, JS_ATOM_new_target);
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);
}
if (s->is_func_expr && s->func_name != JS_ATOM_NULL)
add_func_var(ctx, s, s->func_name);
@@ -21447,10 +21248,6 @@ static void add_eval_variables(JSContext *ctx, JSFunctionDef *s)
if (!has_this_binding && fd->has_this_binding) {
if (fd->this_var_idx < 0)
fd->this_var_idx = add_var_this(ctx, fd);
if (fd->new_target_var_idx < 0)
fd->new_target_var_idx = add_var(ctx, fd, JS_ATOM_new_target);
if (fd->is_derived_class_constructor && fd->this_active_func_var_idx < 0)
fd->this_active_func_var_idx = add_var(ctx, fd, JS_ATOM_this_active_func);
has_this_binding = TRUE;
}
/* add function name */
@@ -22560,22 +22357,10 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s)
dbuf_putc(&bc_out, OP_SPECIAL_OBJECT_THIS_FUNC);
put_short_code(&bc_out, OP_put_loc, s->this_active_func_var_idx);
}
/* initialize the 'new.target' variable if needed */
if (s->new_target_var_idx >= 0) {
dbuf_putc(&bc_out, OP_special_object);
dbuf_putc(&bc_out, OP_SPECIAL_OBJECT_NEW_TARGET);
put_short_code(&bc_out, OP_put_loc, s->new_target_var_idx);
}
/* initialize the 'this' variable if needed. In a derived class
constructor, this is initially uninitialized. */
/* initialize the 'this' variable if needed */
if (s->this_var_idx >= 0) {
if (s->is_derived_class_constructor) {
dbuf_putc(&bc_out, OP_set_loc_uninitialized);
dbuf_put_u16(&bc_out, s->this_var_idx);
} else {
dbuf_putc(&bc_out, OP_push_this);
put_short_code(&bc_out, OP_put_loc, s->this_var_idx);
}
dbuf_putc(&bc_out, OP_push_this);
put_short_code(&bc_out, OP_put_loc, s->this_var_idx);
}
/* initialize a reference to the current function if needed */
if (s->func_var_idx >= 0) {
@@ -23684,7 +23469,6 @@ static JSValue js_create_function(JSContext *ctx, JSFunctionDef *fd)
b->has_prototype = fd->has_prototype;
b->has_simple_parameter_list = fd->has_simple_parameter_list;
b->js_mode = fd->js_mode;
b->is_derived_class_constructor = fd->is_derived_class_constructor;
#ifdef DUMP_PROFILE
/* Initialize profiling data */
@@ -23701,7 +23485,6 @@ static JSValue js_create_function(JSContext *ctx, JSFunctionDef *fd)
b->ic_slots = NULL;
b->ic_count = 0;
b->new_target_allowed = fd->new_target_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);
@@ -24009,14 +23792,6 @@ static __exception int js_parse_function_decl2(JSParseState *s,
fd->has_this_binding = (func_type != JS_PARSE_FUNC_ARROW &&
func_type != JS_PARSE_FUNC_CLASS_STATIC_INIT);
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;
} else if (func_type == JS_PARSE_FUNC_CLASS_STATIC_INIT) {
fd->new_target_allowed = TRUE; // although new.target === undefined
} else {
fd->new_target_allowed = TRUE;
}
/* fd->in_function_body == FALSE prevents yield/await during the parsing
of the arguments in generator/async functions. They are parsed as
@@ -24511,11 +24286,6 @@ static JSValue __JS_EvalInternal(JSContext *ctx, JSValueConst this_obj,
s->cur_func = fd;
fd->eval_type = eval_type;
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;
} else {
fd->new_target_allowed = FALSE;
}
fd->js_mode = js_mode;
fd->func_name = JS_DupAtom(ctx, JS_ATOM__eval_);
if (b) {
@@ -25008,9 +24778,7 @@ static int JS_WriteFunctionTag(BCWriterState *s, JSValueConst obj)
flags = idx = 0;
bc_set_flags(&flags, &idx, b->has_prototype, 1);
bc_set_flags(&flags, &idx, b->has_simple_parameter_list, 1);
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->has_debug, 1);
bc_set_flags(&flags, &idx, b->is_direct_or_indirect_eval, 1);
assert(idx <= 16);
@@ -25246,12 +25014,6 @@ static int JS_WriteObjectRec(BCWriterState *s, JSValueConst obj)
case JS_CLASS_OBJECT:
ret = JS_WriteObjectTag(s, obj);
break;
case JS_CLASS_NUMBER:
case JS_CLASS_STRING:
case JS_CLASS_BOOLEAN:
bc_put_u8(s, BC_TAG_OBJECT_VALUE);
ret = JS_WriteObjectRec(s, p->u.object_data);
break;
default:
JS_ThrowTypeError(s->ctx, "unsupported object class");
ret = -1;
@@ -25710,9 +25472,7 @@ static JSValue JS_ReadFunctionTag(BCReaderState *s)
idx = 0;
bc.has_prototype = bc_get_flags(v16, &idx, 1);
bc.has_simple_parameter_list = bc_get_flags(v16, &idx, 1);
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.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;
@@ -27040,96 +26800,6 @@ static JSValue js_create_array(JSContext *ctx, int len, JSValueConst *tab)
return obj;
}
/* String */
static int js_string_get_own_property(JSContext *ctx,
JSPropertyDescriptor *desc,
JSValueConst obj, JSAtom prop)
{
JSObject *p;
JSString *p1;
uint32_t idx, ch;
/* This is a class exotic method: obj class_id is JS_CLASS_STRING */
if (__JS_AtomIsTaggedInt(prop)) {
p = JS_VALUE_GET_OBJ(obj);
if (JS_VALUE_GET_TAG(p->u.object_data) == JS_TAG_STRING) {
p1 = JS_VALUE_GET_STRING(p->u.object_data);
idx = __JS_AtomToUInt32(prop);
if (idx < p1->len) {
if (desc) {
ch = string_get(p1, idx);
desc->flags = JS_PROP_ENUMERABLE;
desc->value = js_new_string_char(ctx, ch);
desc->getter = JS_NULL;
desc->setter = JS_NULL;
}
return TRUE;
}
}
}
return FALSE;
}
static int js_string_define_own_property(JSContext *ctx,
JSValueConst this_obj,
JSAtom prop, JSValueConst val,
JSValueConst getter,
JSValueConst setter, int flags)
{
uint32_t idx;
JSObject *p;
JSString *p1, *p2;
if (__JS_AtomIsTaggedInt(prop)) {
idx = __JS_AtomToUInt32(prop);
p = JS_VALUE_GET_OBJ(this_obj);
if (JS_VALUE_GET_TAG(p->u.object_data) != JS_TAG_STRING)
goto def;
p1 = JS_VALUE_GET_STRING(p->u.object_data);
if (idx >= p1->len)
goto def;
if (!check_define_prop_flags(JS_PROP_ENUMERABLE, flags))
goto fail;
/* check that the same value is configured */
if (flags & JS_PROP_HAS_VALUE) {
if (JS_VALUE_GET_TAG(val) != JS_TAG_STRING)
goto fail;
p2 = JS_VALUE_GET_STRING(val);
if (p2->len != 1)
goto fail;
if (string_get(p1, idx) != string_get(p2, 0)) {
fail:
return JS_ThrowTypeErrorOrFalse(ctx, flags, "property is not configurable");
}
}
return TRUE;
} else {
def:
return JS_DefineProperty(ctx, this_obj, prop, val, getter, setter,
flags | JS_PROP_NO_EXOTIC);
}
}
static int js_string_delete_property(JSContext *ctx,
JSValueConst obj, JSAtom prop)
{
uint32_t idx;
if (__JS_AtomIsTaggedInt(prop)) {
idx = __JS_AtomToUInt32(prop);
if (idx < js_string_obj_get_length(ctx, obj)) {
return FALSE;
}
}
return TRUE;
}
static const JSClassExoticMethods js_string_exotic_methods = {
.get_own_property = js_string_get_own_property,
.define_own_property = js_string_define_own_property,
.delete_property = js_string_delete_property,
};
static int string_cmp(JSString *p1, JSString *p2, int x1, int x2, int len)
{
int i, c1, c2;
@@ -28346,24 +28016,6 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc,
}
if (JS_IsObject(val)) {
p = JS_VALUE_GET_OBJ(val);
cl = p->class_id;
if (cl == JS_CLASS_STRING) {
val = JS_ToStringFree(ctx, val);
if (JS_IsException(val))
goto exception;
goto concat_primitive;
} else if (cl == JS_CLASS_NUMBER) {
val = JS_ToNumberFree(ctx, val);
if (JS_IsException(val))
goto exception;
goto concat_primitive;
} else if (cl == JS_CLASS_BOOLEAN)
{
/* This will thow the same error as for the primitive object */
set_value(ctx, &val, JS_DupValue(ctx, p->u.object_data));
goto concat_primitive;
}
v = js_array_includes(ctx, jsc->stack, 1, (JSValueConst *)&val);
if (JS_IsException(v))
goto exception;
@@ -28550,16 +28202,9 @@ JSValue JS_JSONStringify(JSContext *ctx, JSValueConst obj,
if (JS_IsException(v))
goto exception;
if (JS_IsObject(v)) {
JSObject *p = JS_VALUE_GET_OBJ(v);
if (p->class_id == JS_CLASS_STRING ||
p->class_id == JS_CLASS_NUMBER) {
v = JS_ToStringFree(ctx, v);
if (JS_IsException(v))
goto exception;
} else {
JS_FreeValue(ctx, v);
continue;
}
/* Objects are not valid property list items */
JS_FreeValue(ctx, v);
continue;
} else if (JS_IsNumber(v)) {
v = JS_ToStringFree(ctx, v);
if (JS_IsException(v))
@@ -28583,18 +28228,6 @@ JSValue JS_JSONStringify(JSContext *ctx, JSValueConst obj,
}
}
space = JS_DupValue(ctx, space0);
if (JS_IsObject(space)) {
JSObject *p = JS_VALUE_GET_OBJ(space);
if (p->class_id == JS_CLASS_NUMBER) {
space = JS_ToNumberFree(ctx, space);
} else if (p->class_id == JS_CLASS_STRING) {
space = JS_ToStringFree(ctx, space);
}
if (JS_IsException(space)) {
JS_FreeValue(ctx, space);
goto exception;
}
}
if (JS_IsNumber(space)) {
int n;
if (JS_ToInt32Clamp(ctx, &n, space, 0, 10, 0))
@@ -32921,13 +32554,6 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx)
ctx->array_proto_values =
JS_GetProperty(ctx, ctx->class_proto[JS_CLASS_ARRAY], JS_ATOM_values);
/* String - no constructor, just use text() global function */
ctx->class_proto[JS_CLASS_STRING] = JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_OBJECT],
JS_CLASS_STRING);
/* Symbol - no constructor, but keep symbol type for object keys */
ctx->class_proto[JS_CLASS_SYMBOL] = JS_NewObject(ctx);
/* global properties */
JS_DefinePropertyValue(ctx, ctx->global_obj, JS_ATOM_globalThis,
JS_DupValue(ctx, ctx->global_obj),