remove property access for bytecode functions
This commit is contained in:
170
source/quickjs.c
170
source/quickjs.c
@@ -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),
|
||||
|
||||
Reference in New Issue
Block a user