remove property access for bytecode functions

This commit is contained in:
2026-01-11 13:22:36 -06:00
parent 17b9aaaf51
commit ffe7b61ae2
4 changed files with 263 additions and 17 deletions

View File

@@ -13252,6 +13252,15 @@ static JSValue JS_CallInternal_OLD(JSContext *caller_ctx, JSValueConst func_obj,
{
JSValue val;
/* User-defined functions don't support property access in cell script */
if (JS_VALUE_GET_TAG(sp[-1]) == JS_TAG_OBJECT) {
JSObject *fp = JS_VALUE_GET_OBJ(sp[-1]);
if (fp->class_id == JS_CLASS_BYTECODE_FUNCTION) {
JS_ThrowTypeError(ctx, "cannot get property of function");
goto exception;
}
}
sf->cur_pc = pc;
val = JS_GetProperty(ctx, sp[-1], JS_ATOM_length);
if (unlikely(JS_IsException(val)))
@@ -14370,6 +14379,15 @@ static JSValue JS_CallInternal_OLD(JSContext *caller_ctx, JSValueConst func_obj,
#endif
obj = sp[-1];
/* User-defined functions don't support property access in cell script */
if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) {
JSObject *fp = JS_VALUE_GET_OBJ(obj);
if (fp->class_id == JS_CLASS_BYTECODE_FUNCTION) {
JS_ThrowTypeError(ctx, "cannot get property of function");
goto exception;
}
}
/* Monomorphic IC fast path: shape-guarded own-property lookup */
if (likely(JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT)) {
JSObject *p = JS_VALUE_GET_OBJ(obj);
@@ -14450,6 +14468,15 @@ static JSValue JS_CallInternal_OLD(JSContext *caller_ctx, JSValueConst func_obj,
#endif
obj = sp[-1];
/* User-defined functions don't support property access in cell script */
if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) {
JSObject *fp = JS_VALUE_GET_OBJ(obj);
if (fp->class_id == JS_CLASS_BYTECODE_FUNCTION) {
JS_ThrowTypeError(ctx, "cannot get property of function");
goto exception;
}
}
/* Monomorphic IC fast path */
if (likely(JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT)) {
JSObject *p = JS_VALUE_GET_OBJ(obj);
@@ -14516,6 +14543,15 @@ static JSValue JS_CallInternal_OLD(JSContext *caller_ctx, JSValueConst func_obj,
/* Record property access site */
profile_record_prop_site(rt, b, (uint32_t)(pc - b->byte_code_buf), atom);
#endif
/* User-defined functions don't support property assignment in cell script */
if (JS_VALUE_GET_TAG(sp[-2]) == JS_TAG_OBJECT) {
JSObject *fp = JS_VALUE_GET_OBJ(sp[-2]);
if (fp->class_id == JS_CLASS_BYTECODE_FUNCTION) {
JS_ThrowTypeError(ctx, "cannot set property of function");
goto exception;
}
}
ret = JS_SetPropertyInternal(ctx, sp[-2], atom, sp[-1], sp[-2],
JS_PROP_THROW_STRICT);
JS_FreeValue(ctx, sp[-2]);
@@ -14653,6 +14689,15 @@ static JSValue JS_CallInternal_OLD(JSContext *caller_ctx, JSValueConst func_obj,
{
JSValue val;
/* User-defined functions don't support property access in cell script */
if (JS_VALUE_GET_TAG(sp[-2]) == JS_TAG_OBJECT) {
JSObject *fp = JS_VALUE_GET_OBJ(sp[-2]);
if (fp->class_id == JS_CLASS_BYTECODE_FUNCTION) {
JS_ThrowTypeError(ctx, "cannot get property of function");
goto exception;
}
}
sf->cur_pc = pc;
val = JS_GetPropertyValue(ctx, sp[-2], sp[-1]);
JS_FreeValue(ctx, sp[-2]);
@@ -14667,6 +14712,15 @@ static JSValue JS_CallInternal_OLD(JSContext *caller_ctx, JSValueConst func_obj,
{
JSValue val;
/* User-defined functions don't support property access in cell script */
if (JS_VALUE_GET_TAG(sp[-2]) == JS_TAG_OBJECT) {
JSObject *fp = JS_VALUE_GET_OBJ(sp[-2]);
if (fp->class_id == JS_CLASS_BYTECODE_FUNCTION) {
JS_ThrowTypeError(ctx, "cannot get property of function");
goto exception;
}
}
sf->cur_pc = pc;
val = JS_GetPropertyValue(ctx, sp[-2], sp[-1]);
sp[-1] = val;
@@ -14679,6 +14733,15 @@ static JSValue JS_CallInternal_OLD(JSContext *caller_ctx, JSValueConst func_obj,
{
JSValue val;
/* User-defined functions don't support property access in cell script */
if (JS_VALUE_GET_TAG(sp[-2]) == JS_TAG_OBJECT) {
JSObject *fp = JS_VALUE_GET_OBJ(sp[-2]);
if (fp->class_id == JS_CLASS_BYTECODE_FUNCTION) {
JS_ThrowTypeError(ctx, "cannot get property of function");
goto exception;
}
}
switch (JS_VALUE_GET_TAG(sp[-2])) {
case JS_TAG_INT:
case JS_TAG_STRING:
@@ -14747,6 +14810,15 @@ static JSValue JS_CallInternal_OLD(JSContext *caller_ctx, JSValueConst func_obj,
{
int ret;
/* User-defined functions don't support property assignment in cell script */
if (JS_VALUE_GET_TAG(sp[-3]) == JS_TAG_OBJECT) {
JSObject *fp = JS_VALUE_GET_OBJ(sp[-3]);
if (fp->class_id == JS_CLASS_BYTECODE_FUNCTION) {
JS_ThrowTypeError(ctx, "cannot set property of function");
goto exception;
}
}
sf->cur_pc = pc;
ret = JS_SetPropertyValue(ctx, sp[-3], sp[-2], sp[-1], JS_PROP_THROW_STRICT);
JS_FreeValue(ctx, sp[-3]);
@@ -29320,13 +29392,19 @@ static JSValue js_function_toString(JSContext *ctx, JSValueConst this_val,
return JS_NewStringLen(ctx, b->debug.source, b->debug.source_len);
}
}
{
JSValue name;
const char *pref, *suff;
pref = "function ";
pref = "function ";
suff = "() {\n [native code]\n}";
name = JS_GetProperty(ctx, this_val, JS_ATOM_name);
/* Get name directly from structure rather than via property access */
if (js_class_has_bytecode(p->class_id)) {
JSFunctionBytecode *b = p->u.func.function_bytecode;
name = JS_AtomToString(ctx, b->func_name);
} else {
name = JS_AtomToString(ctx, JS_ATOM_empty_string);
}
if (JS_IsNull(name))
name = JS_AtomToString(ctx, JS_ATOM_empty_string);
return JS_ConcatString3(ctx, pref, name, suff);
@@ -35480,6 +35558,7 @@ static const JSCFunctionListEntry js_symbol_proto_funcs[] = {
static JSValue js_map_constructor(JSContext *ctx, JSValueConst new_target,
int argc, JSValueConst *argv, int magic)
{
JSMapState *s;
JSValue obj, adder = JS_NULL, iter = JS_NULL, next_method = JS_NULL;
JSValueConst arr;
@@ -35570,11 +35649,13 @@ static JSValue js_map_constructor(JSContext *ctx, JSValueConst new_target,
JS_FreeValue(ctx, iter);
JS_FreeValue(ctx, adder);
}
return obj;
fail_close:
/* close the iterator object, preserving pending exception */
JS_IteratorClose(ctx, iter, TRUE);
fail:
JS_FreeValue(ctx, next_method);
JS_FreeValue(ctx, iter);
JS_FreeValue(ctx, adder);
@@ -37184,6 +37265,42 @@ static JSValue js_cell_text(JSContext *ctx, JSValueConst this_val,
return string_buffer_end(b);
}
/* Handle function - return source or native stub */
if (JS_IsFunction(ctx, arg)) {
JSObject *p = JS_VALUE_GET_OBJ(arg);
if (js_class_has_bytecode(p->class_id)) {
JSFunctionBytecode *b = p->u.func.function_bytecode;
if (b->has_debug && b->debug.source) {
return JS_NewStringLen(ctx, b->debug.source, b->debug.source_len);
}
}
/* Native function - generate stub */
const char *pref = "function ";
const char *suff = "() {\n [native code]\n}";
const char *name = NULL;
JSObject *fp = JS_VALUE_GET_OBJ(arg);
if (js_class_has_bytecode(fp->class_id)) {
JSFunctionBytecode *fb = fp->u.func.function_bytecode;
name = JS_AtomToCString(ctx, fb->func_name);
}
if (!name) name = "";
size_t plen = strlen(pref);
size_t nlen = strlen(name);
size_t slen = strlen(suff);
char *result = js_malloc(ctx, plen + nlen + slen + 1);
if (!result) {
if (name[0]) JS_FreeCString(ctx, name);
return JS_EXCEPTION;
}
memcpy(result, pref, plen);
memcpy(result + plen, name, nlen);
memcpy(result + plen + nlen, suff, slen + 1);
JSValue ret = JS_NewString(ctx, result);
js_free(ctx, result);
if (name[0]) JS_FreeCString(ctx, name);
return ret;
}
/* Handle null */
if (JS_IsNull(arg))
return JS_NULL;
@@ -39530,12 +39647,19 @@ static JSValue js_cell_length(JSContext *ctx, JSValueConst this_val,
if (JS_IsNull(val))
return JS_NULL;
/* Functions return arity */
/* Functions return arity (accessed directly, not via properties) */
if (JS_IsFunction(ctx, val)) {
JSValue len = JS_GetPropertyStr(ctx, val, "length");
if (JS_IsException(len))
return len;
return len;
JSObject *p = JS_VALUE_GET_OBJ(val);
switch (p->class_id) {
case JS_CLASS_BYTECODE_FUNCTION:
return JS_NewInt32(ctx, p->u.func.function_bytecode->defined_arg_count);
case JS_CLASS_C_FUNCTION:
return JS_NewInt32(ctx, p->u.cfunc.length);
case JS_CLASS_C_FUNCTION_DATA:
return JS_NewInt32(ctx, p->u.c_function_data_record->length);
default:
return JS_NewInt32(ctx, 0);
}
}
int tag = JS_VALUE_GET_TAG(val);
@@ -39579,6 +39703,31 @@ static JSValue js_cell_length(JSContext *ctx, JSValueConst this_val,
return JS_NULL;
}
/* ============================================================================
* call() function - call a function with explicit this and arguments
* ============================================================================ */
/* call(func, this_val, ...args) */
static JSValue js_cell_call(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
if (argc < 1)
return JS_ThrowTypeError(ctx, "call requires a function argument");
JSValue func = argv[0];
if (!JS_IsFunction(ctx, func))
return JS_ThrowTypeError(ctx, "first argument must be a function");
JSValue this_arg = JS_NULL;
if (argc >= 2)
this_arg = argv[1];
int call_argc = argc > 2 ? argc - 2 : 0;
JSValueConst *call_argv = call_argc > 0 ? &argv[2] : NULL;
return JS_Call(ctx, func, this_arg, call_argc, call_argv);
}
/* ============================================================================
* is_* type checking functions
* ============================================================================ */
@@ -40011,6 +40160,11 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx)
JS_NewCFunction(ctx, js_cell_length, "length", 1),
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
/* call() function */
JS_DefinePropertyValueStr(ctx, ctx->global_obj, "call",
JS_NewCFunction(ctx, js_cell_call, "call", 3),
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
/* is_* type checking functions */
JS_DefinePropertyValueStr(ctx, ctx->global_obj, "is_array",
JS_NewCFunction(ctx, js_cell_is_array, "is_array", 1),