From 632b038561bc20eb3a0f200883bfc910946212a0 Mon Sep 17 00:00:00 2001 From: John Alanbrook Date: Mon, 23 Jun 2025 10:21:07 -0500 Subject: [PATCH] remove last two master updates and remove proxy --- scripts/engine.cm | 18 +- source/cell.c | 74 ---- source/quickjs.c | 1018 +-------------------------------------------- 3 files changed, 5 insertions(+), 1105 deletions(-) diff --git a/scripts/engine.cm b/scripts/engine.cm index 46f3dfaa..9b51ec93 100644 --- a/scripts/engine.cm +++ b/scripts/engine.cm @@ -40,14 +40,14 @@ function console_rec(line, file, msg) { var console_mod = cell.hidden.console -var logs = {} -logs.console = function(msg) +globalThis.log = {} +log.console = function(msg) { var caller = caller_data(2) console_mod.print(console_rec(caller.line, caller.file, msg)) } -logs.error = function(msg = new Error()) +log.error = function(msg = new Error()) { var caller = caller_data(4) @@ -57,21 +57,11 @@ logs.error = function(msg = new Error()) console_mod.print(console_rec(caller.line,caller.file,msg)) } -logs.system = function(msg) { +log.system = function(msg) { msg = "[SYSTEM] " + msg log.console(msg) } -function noop() {} -globalThis.log = new Proxy(logs, { - get(target,prop,receiver) { - if (target[prop]) - return (...args) => target[prop](args.join(' ')) - - return noop - } -}) - // Get hidden modules from cell.hidden before stripping it var hidden = cell.hidden var actor_mod = hidden.actor diff --git a/source/cell.c b/source/cell.c index 558739bc..53549cfb 100644 --- a/source/cell.c +++ b/source/cell.c @@ -751,7 +751,6 @@ void script_startup(cell_rt *prt) JS_AddIntrinsicRegExp(js); JS_AddIntrinsicJSON(js); JS_AddIntrinsicMapSet(js); - JS_AddIntrinsicProxy(js); JS_SetContextOpaque(js, prt); prt->context = js; @@ -870,79 +869,6 @@ int main(int argc, char **argv) int profile_enabled = 0; int script_start = 1; - /* Check for --script flag - execute script directly without engine */ - if (argc > 2 && strcmp(argv[1], "--script") == 0) { - /* Read and execute the script file */ - FILE *f = fopen(argv[2], "rb"); - if (!f) { - perror("fopen"); - return 1; - } - - fseek(f, 0, SEEK_END); - long size = ftell(f); - if (size < 0) { - perror("ftell"); - fclose(f); - return 1; - } - - char *script = malloc(size + 1); - if (!script) { - perror("malloc"); - fclose(f); - return 1; - } - - rewind(f); - if (fread(script, 1, size, f) != size) { - perror("fread"); - free(script); - fclose(f); - return 1; - } - fclose(f); - script[size] = '\0'; - - /* Create minimal JS runtime */ - JSRuntime *rt = JS_NewRuntime(); - JSContext *js = JS_NewContextRaw(rt); - - /* Add basic intrinsics */ - JS_AddIntrinsicBaseObjects(js); - JS_AddIntrinsicEval(js); - JS_AddIntrinsicRegExp(js); - JS_AddIntrinsicJSON(js); - JS_AddIntrinsicMapSet(js); - JS_AddIntrinsicProxy(js); - - cell_rt *prt = malloc(sizeof(*prt)); - JS_SetContextOpaque(js, prt); - - /* Load FFI functions */ - ffi_load(js); - - /* Execute the script */ - JSValue result = JS_Eval(js, script, size, argv[2], 0); - free(script); - - /* Check for exceptions */ - if (JS_IsException(result)) { - JSValue exp = JS_GetException(js); - const char *str = JS_ToCString(js, exp); - if (str) { - fprintf(stderr, "Exception: %s\n", str); - JS_FreeCString(js, str); - } - JS_FreeValue(js, exp); - } - - JS_FreeValue(js, result); - JS_FreeContext(js); - JS_FreeRuntime(rt); - return 0; - } - /* Check for --profile flag */ if (argc > 1 && strcmp(argv[1], "--profile") == 0) { profile_enabled = 1; script_start = 2; diff --git a/source/quickjs.c b/source/quickjs.c index 1852e8dc..bd971471 100644 --- a/source/quickjs.c +++ b/source/quickjs.c @@ -136,7 +136,6 @@ enum { JS_CLASS_ARRAY_ITERATOR, /* u.array_iterator_data */ JS_CLASS_STRING_ITERATOR, /* u.array_iterator_data */ JS_CLASS_REGEXP_STRING_ITERATOR, /* u.regexp_string_iterator_data */ - JS_CLASS_PROXY, /* u.proxy_data */ JS_CLASS_FINALIZATION_REGISTRY, JS_CLASS_INIT_COUNT, /* last entry for predefined classes */ @@ -536,13 +535,6 @@ typedef struct JSRegExp { JSString *bytecode; /* also contains the flags */ } JSRegExp; -typedef struct JSProxyData { - JSValue target; - JSValue handler; - uint8_t is_func; - uint8_t is_revoked; -} JSProxyData; - typedef enum { /* binary operators */ JS_OVOP_ADD, @@ -667,7 +659,6 @@ struct JSObject { struct JSMapIteratorData *map_iterator_data; /* JS_CLASS_MAP_ITERATOR, JS_CLASS_SET_ITERATOR */ struct JSArrayIteratorData *array_iterator_data; /* JS_CLASS_ARRAY_ITERATOR, JS_CLASS_STRING_ITERATOR */ struct JSRegExpStringIteratorData *regexp_string_iterator_data; /* JS_CLASS_REGEXP_STRING_ITERATOR */ - struct JSProxyData *proxy_data; /* JS_CLASS_PROXY */ struct { /* JS_CLASS_BYTECODE_FUNCTION: 12/24 bytes */ struct JSFunctionBytecode *function_bytecode; JSVarRef **var_refs; @@ -813,9 +804,6 @@ static void js_for_in_iterator_finalizer(JSRuntime *rt, JSValue val); static void js_for_in_iterator_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); static void js_regexp_finalizer(JSRuntime *rt, JSValue val); -static void js_proxy_finalizer(JSRuntime *rt, JSValue val); -static void js_proxy_mark(JSRuntime *rt, JSValueConst val, - JS_MarkFunc *mark_func); static void js_map_finalizer(JSRuntime *rt, JSValue val); static void js_map_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); @@ -863,9 +851,6 @@ static JSValue JS_ToObjectFree(JSContext *ctx, JSValue val); static JSProperty *add_property(JSContext *ctx, JSObject *p, JSAtom prop, int prop_flags); JSValue JS_ThrowOutOfMemory(JSContext *ctx); -static JSValue JS_ThrowTypeErrorRevokedProxy(JSContext *ctx); - -static int js_resolve_proxy(JSContext *ctx, JSValueConst *pval, int throw_exception); static int JS_CreateProperty(JSContext *ctx, JSObject *p, JSAtom prop, JSValueConst val, JSValueConst getter, JSValueConst setter, @@ -927,7 +912,6 @@ static JSValue js_error_toString(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv); static const JSClassExoticMethods js_string_exotic_methods; -static const JSClassExoticMethods js_proxy_exotic_methods; static JSClassID js_class_id_alloc = JS_CLASS_INIT_COUNT; static void js_trigger_gc(JSRuntime *rt, size_t size) @@ -1629,7 +1613,6 @@ JSContext *JS_NewContext(JSRuntime *rt) JS_AddIntrinsicStringNormalize(ctx); JS_AddIntrinsicRegExp(ctx); JS_AddIntrinsicJSON(ctx); - JS_AddIntrinsicProxy(ctx); JS_AddIntrinsicMapSet(ctx); return ctx; @@ -5649,7 +5632,6 @@ void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s) case JS_CLASS_SET_ITERATOR: /* u.map_iterator_data */ case JS_CLASS_ARRAY_ITERATOR: /* u.array_iterator_data */ case JS_CLASS_STRING_ITERATOR: /* u.array_iterator_data */ - case JS_CLASS_PROXY: /* u.proxy_data */ /* TODO */ default: /* XXX: class definition should have an opaque block size */ @@ -8909,8 +8891,6 @@ BOOL JS_IsFunction(JSContext *ctx, JSValueConst val) switch(p->class_id) { case JS_CLASS_BYTECODE_FUNCTION: return TRUE; - case JS_CLASS_PROXY: - return p->u.proxy_data->is_func; default: return (ctx->rt->class_array[p->class_id].call != NULL); } @@ -10290,9 +10270,7 @@ static void js_print_object(JSPrintValueState *s, JSObject *p) js_printf(s, "<%u empty item%s>", n, n > 1 ? "s" : ""); } } - } else if (p->class_id == JS_CLASS_BYTECODE_FUNCTION || - (rt->class_array[p->class_id].call != NULL && - p->class_id != JS_CLASS_PROXY)) { + } else if (p->class_id == JS_CLASS_BYTECODE_FUNCTION || rt->class_array[p->class_id].call != NULL) { js_printf(s, "[Function"); /* XXX: allow dump without ctx */ if (!s->options.raw_dump && s->ctx) { @@ -10684,8 +10662,6 @@ static __maybe_unused void JS_DumpGCObject(JSRuntime *rt, JSGCObjectHeader *p) // TODO: should take flags to make proxy resolution and exceptions optional int JS_IsArray(JSContext *ctx, JSValueConst val) { - if (js_resolve_proxy(ctx, &val, TRUE)) - return -1; if (JS_VALUE_GET_TAG(val) == JS_TAG_OBJECT) { JSObject *p = JS_VALUE_GET_OBJ(val); return p->class_id == JS_CLASS_ARRAY; @@ -14799,19 +14775,6 @@ static JSContext *JS_GetFunctionRealm(JSContext *ctx, JSValueConst func_obj) realm = b->realm; } break; - case JS_CLASS_PROXY: - { - JSProxyData *s = p->u.opaque; - if (!s) - return ctx; - if (s->is_revoked) { - JS_ThrowTypeErrorRevokedProxy(ctx); - return NULL; - } else { - realm = JS_GetFunctionRealm(ctx, s->target); - } - } - break; case JS_CLASS_BOUND_FUNCTION: { JSBoundFunction *bf = p->u.bound_function; @@ -28425,8 +28388,6 @@ static JSValue js_object___getClass(JSContext *ctx, JSValueConst this_val, if (tag == JS_TAG_OBJECT) { p = JS_VALUE_GET_OBJ(argv[0]); class_id = p->class_id; - if (class_id == JS_CLASS_PROXY && JS_IsFunction(ctx, argv[0])) - class_id = JS_CLASS_BYTECODE_FUNCTION; atom = ctx->rt->class_array[class_id].class_name; } else { atom = JS_ATOM_empty_string; @@ -35554,983 +35515,6 @@ void JS_AddIntrinsicJSON(JSContext *ctx) JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_json_obj, countof(js_json_obj)); } -/* Proxy */ - -static void js_proxy_finalizer(JSRuntime *rt, JSValue val) -{ - JSProxyData *s = JS_GetOpaque(val, JS_CLASS_PROXY); - if (s) { - JS_FreeValueRT(rt, s->target); - JS_FreeValueRT(rt, s->handler); - js_free_rt(rt, s); - } -} - -static void js_proxy_mark(JSRuntime *rt, JSValueConst val, - JS_MarkFunc *mark_func) -{ - JSProxyData *s = JS_GetOpaque(val, JS_CLASS_PROXY); - if (s) { - JS_MarkValue(rt, s->target, mark_func); - JS_MarkValue(rt, s->handler, mark_func); - } -} - -static JSValue JS_ThrowTypeErrorRevokedProxy(JSContext *ctx) -{ - return JS_ThrowTypeError(ctx, "revoked proxy"); -} - -static JSProxyData *get_proxy_method(JSContext *ctx, JSValue *pmethod, - JSValueConst obj, JSAtom name) -{ - JSProxyData *s = JS_GetOpaque(obj, JS_CLASS_PROXY); - JSValue method; - - /* safer to test recursion in all proxy methods */ - if (js_check_stack_overflow(ctx->rt, 0)) { - JS_ThrowStackOverflow(ctx); - return NULL; - } - - /* 's' should never be NULL */ - if (s->is_revoked) { - JS_ThrowTypeErrorRevokedProxy(ctx); - return NULL; - } - method = JS_GetProperty(ctx, s->handler, name); - if (JS_IsException(method)) - return NULL; - if (JS_IsNull(method)) - method = JS_NULL; - *pmethod = method; - return s; -} - -static JSValue js_proxy_get_prototype(JSContext *ctx, JSValueConst obj) -{ - JSProxyData *s; - JSValue method, ret, proto1; - int res; - - s = get_proxy_method(ctx, &method, obj, JS_ATOM_getPrototypeOf); - if (!s) - return JS_EXCEPTION; - if (JS_IsNull(method)) - return JS_GetPrototype(ctx, s->target); - ret = JS_CallFree(ctx, method, s->handler, 1, (JSValueConst *)&s->target); - if (JS_IsException(ret)) - return ret; - if (JS_VALUE_GET_TAG(ret) != JS_TAG_NULL && - JS_VALUE_GET_TAG(ret) != JS_TAG_OBJECT) { - goto fail; - } - res = JS_IsExtensible(ctx, s->target); - if (res < 0) { - JS_FreeValue(ctx, ret); - return JS_EXCEPTION; - } - if (!res) { - /* check invariant */ - proto1 = JS_GetPrototype(ctx, s->target); - if (JS_IsException(proto1)) { - JS_FreeValue(ctx, ret); - return JS_EXCEPTION; - } - if (!js_same_value(ctx, proto1, ret)) { - JS_FreeValue(ctx, proto1); - fail: - JS_FreeValue(ctx, ret); - return JS_ThrowTypeError(ctx, "proxy: inconsistent prototype"); - } - JS_FreeValue(ctx, proto1); - } - return ret; -} - -static int js_proxy_set_prototype(JSContext *ctx, JSValueConst obj, - JSValueConst proto_val) -{ - JSProxyData *s; - JSValue method, ret, proto1; - JSValueConst args[2]; - BOOL res; - int res2; - - s = get_proxy_method(ctx, &method, obj, JS_ATOM_setPrototypeOf); - if (!s) - return -1; - if (JS_IsNull(method)) - return JS_SetPrototypeInternal(ctx, s->target, proto_val, FALSE); - args[0] = s->target; - args[1] = proto_val; - ret = JS_CallFree(ctx, method, s->handler, 2, args); - if (JS_IsException(ret)) - return -1; - res = JS_ToBoolFree(ctx, ret); - if (!res) - return FALSE; - res2 = JS_IsExtensible(ctx, s->target); - if (res2 < 0) - return -1; - if (!res2) { - proto1 = JS_GetPrototype(ctx, s->target); - if (JS_IsException(proto1)) - return -1; - if (!js_same_value(ctx, proto_val, proto1)) { - JS_FreeValue(ctx, proto1); - JS_ThrowTypeError(ctx, "proxy: inconsistent prototype"); - return -1; - } - JS_FreeValue(ctx, proto1); - } - return TRUE; -} - -static int js_proxy_is_extensible(JSContext *ctx, JSValueConst obj) -{ - JSProxyData *s; - JSValue method, ret; - BOOL res; - int res2; - - s = get_proxy_method(ctx, &method, obj, JS_ATOM_isExtensible); - if (!s) - return -1; - if (JS_IsNull(method)) - return JS_IsExtensible(ctx, s->target); - ret = JS_CallFree(ctx, method, s->handler, 1, (JSValueConst *)&s->target); - if (JS_IsException(ret)) - return -1; - res = JS_ToBoolFree(ctx, ret); - res2 = JS_IsExtensible(ctx, s->target); - if (res2 < 0) - return res2; - if (res != res2) { - JS_ThrowTypeError(ctx, "proxy: inconsistent isExtensible"); - return -1; - } - return res; -} - -static int js_proxy_prevent_extensions(JSContext *ctx, JSValueConst obj) -{ - JSProxyData *s; - JSValue method, ret; - BOOL res; - int res2; - - s = get_proxy_method(ctx, &method, obj, JS_ATOM_preventExtensions); - if (!s) - return -1; - if (JS_IsNull(method)) - return JS_PreventExtensions(ctx, s->target); - ret = JS_CallFree(ctx, method, s->handler, 1, (JSValueConst *)&s->target); - if (JS_IsException(ret)) - return -1; - res = JS_ToBoolFree(ctx, ret); - if (res) { - res2 = JS_IsExtensible(ctx, s->target); - if (res2 < 0) - return res2; - if (res2) { - JS_ThrowTypeError(ctx, "proxy: inconsistent preventExtensions"); - return -1; - } - } - return res; -} - -static int js_proxy_has(JSContext *ctx, JSValueConst obj, JSAtom atom) -{ - JSProxyData *s; - JSValue method, ret1, atom_val; - int ret, res; - JSObject *p; - JSValueConst args[2]; - BOOL res2; - - s = get_proxy_method(ctx, &method, obj, JS_ATOM_has); - if (!s) - return -1; - if (JS_IsNull(method)) - return JS_HasProperty(ctx, s->target, atom); - atom_val = JS_AtomToValue(ctx, atom); - if (JS_IsException(atom_val)) { - JS_FreeValue(ctx, method); - return -1; - } - args[0] = s->target; - args[1] = atom_val; - ret1 = JS_CallFree(ctx, method, s->handler, 2, args); - JS_FreeValue(ctx, atom_val); - if (JS_IsException(ret1)) - return -1; - ret = JS_ToBoolFree(ctx, ret1); - if (!ret) { - JSPropertyDescriptor desc; - p = JS_VALUE_GET_OBJ(s->target); - res = JS_GetOwnPropertyInternal(ctx, &desc, p, atom); - if (res < 0) - return -1; - if (res) { - res2 = !(desc.flags & JS_PROP_CONFIGURABLE); - js_free_desc(ctx, &desc); - if (res2 || !p->extensible) { - JS_ThrowTypeError(ctx, "proxy: inconsistent has"); - return -1; - } - } - } - return ret; -} - -static JSValue js_proxy_get(JSContext *ctx, JSValueConst obj, JSAtom atom, - JSValueConst receiver) -{ - JSProxyData *s; - JSValue method, ret, atom_val; - int res; - JSValueConst args[3]; - JSPropertyDescriptor desc; - - s = get_proxy_method(ctx, &method, obj, JS_ATOM_get); - if (!s) - return JS_EXCEPTION; - /* Note: recursion is possible thru the prototype of s->target */ - if (JS_IsNull(method)) - return JS_GetPropertyInternal(ctx, s->target, atom, receiver, FALSE); - atom_val = JS_AtomToValue(ctx, atom); - if (JS_IsException(atom_val)) { - JS_FreeValue(ctx, method); - return JS_EXCEPTION; - } - args[0] = s->target; - args[1] = atom_val; - args[2] = receiver; - ret = JS_CallFree(ctx, method, s->handler, 3, args); - JS_FreeValue(ctx, atom_val); - if (JS_IsException(ret)) - return JS_EXCEPTION; - res = JS_GetOwnPropertyInternal(ctx, &desc, JS_VALUE_GET_OBJ(s->target), atom); - if (res < 0) { - JS_FreeValue(ctx, ret); - return JS_EXCEPTION; - } - if (res) { - if ((desc.flags & (JS_PROP_GETSET | JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE)) == 0) { - if (!js_same_value(ctx, desc.value, ret)) { - goto fail; - } - } else if ((desc.flags & (JS_PROP_GETSET | JS_PROP_CONFIGURABLE)) == JS_PROP_GETSET) { - if (JS_IsNull(desc.getter) && !JS_IsNull(ret)) { - fail: - js_free_desc(ctx, &desc); - JS_FreeValue(ctx, ret); - return JS_ThrowTypeError(ctx, "proxy: inconsistent get"); - } - } - js_free_desc(ctx, &desc); - } - return ret; -} - -static int js_proxy_set(JSContext *ctx, JSValueConst obj, JSAtom atom, - JSValueConst value, JSValueConst receiver, int flags) -{ - JSProxyData *s; - JSValue method, ret1, atom_val; - int ret, res; - JSValueConst args[4]; - - s = get_proxy_method(ctx, &method, obj, JS_ATOM_set); - if (!s) - return -1; - if (JS_IsNull(method)) { - return JS_SetPropertyInternal(ctx, s->target, atom, - JS_DupValue(ctx, value), receiver, - flags); - } - atom_val = JS_AtomToValue(ctx, atom); - if (JS_IsException(atom_val)) { - JS_FreeValue(ctx, method); - return -1; - } - args[0] = s->target; - args[1] = atom_val; - args[2] = value; - args[3] = receiver; - ret1 = JS_CallFree(ctx, method, s->handler, 4, args); - JS_FreeValue(ctx, atom_val); - if (JS_IsException(ret1)) - return -1; - ret = JS_ToBoolFree(ctx, ret1); - if (ret) { - JSPropertyDescriptor desc; - res = JS_GetOwnPropertyInternal(ctx, &desc, JS_VALUE_GET_OBJ(s->target), atom); - if (res < 0) - return -1; - if (res) { - if ((desc.flags & (JS_PROP_GETSET | JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE)) == 0) { - if (!js_same_value(ctx, desc.value, value)) { - goto fail; - } - } else if ((desc.flags & (JS_PROP_GETSET | JS_PROP_CONFIGURABLE)) == JS_PROP_GETSET && JS_IsNull(desc.setter)) { - fail: - js_free_desc(ctx, &desc); - JS_ThrowTypeError(ctx, "proxy: inconsistent set"); - return -1; - } - js_free_desc(ctx, &desc); - } - } else { - if (flags & JS_PROP_THROW || - flags & JS_PROP_THROW_STRICT) { - JS_ThrowTypeError(ctx, "proxy: cannot set property"); - return -1; - } - } - return ret; -} - -static JSValue js_create_desc(JSContext *ctx, JSValueConst val, - JSValueConst getter, JSValueConst setter, - int flags) -{ - JSValue ret; - ret = JS_NewObject(ctx); - if (JS_IsException(ret)) - return ret; - if (flags & JS_PROP_HAS_GET) { - JS_DefinePropertyValue(ctx, ret, JS_ATOM_get, JS_DupValue(ctx, getter), - JS_PROP_C_W_E); - } - if (flags & JS_PROP_HAS_SET) { - JS_DefinePropertyValue(ctx, ret, JS_ATOM_set, JS_DupValue(ctx, setter), - JS_PROP_C_W_E); - } - if (flags & JS_PROP_HAS_VALUE) { - JS_DefinePropertyValue(ctx, ret, JS_ATOM_value, JS_DupValue(ctx, val), - JS_PROP_C_W_E); - } - if (flags & JS_PROP_HAS_WRITABLE) { - JS_DefinePropertyValue(ctx, ret, JS_ATOM_writable, - JS_NewBool(ctx, flags & JS_PROP_WRITABLE), - JS_PROP_C_W_E); - } - if (flags & JS_PROP_HAS_ENUMERABLE) { - JS_DefinePropertyValue(ctx, ret, JS_ATOM_enumerable, - JS_NewBool(ctx, flags & JS_PROP_ENUMERABLE), - JS_PROP_C_W_E); - } - if (flags & JS_PROP_HAS_CONFIGURABLE) { - JS_DefinePropertyValue(ctx, ret, JS_ATOM_configurable, - JS_NewBool(ctx, flags & JS_PROP_CONFIGURABLE), - JS_PROP_C_W_E); - } - return ret; -} - -static int js_proxy_get_own_property(JSContext *ctx, JSPropertyDescriptor *pdesc, - JSValueConst obj, JSAtom prop) -{ - JSProxyData *s; - JSValue method, trap_result_obj, prop_val; - int res, target_desc_ret, ret; - JSObject *p; - JSValueConst args[2]; - JSPropertyDescriptor result_desc, target_desc; - - s = get_proxy_method(ctx, &method, obj, JS_ATOM_getOwnPropertyDescriptor); - if (!s) - return -1; - p = JS_VALUE_GET_OBJ(s->target); - if (JS_IsNull(method)) { - return JS_GetOwnPropertyInternal(ctx, pdesc, p, prop); - } - prop_val = JS_AtomToValue(ctx, prop); - if (JS_IsException(prop_val)) { - JS_FreeValue(ctx, method); - return -1; - } - args[0] = s->target; - args[1] = prop_val; - trap_result_obj = JS_CallFree(ctx, method, s->handler, 2, args); - JS_FreeValue(ctx, prop_val); - if (JS_IsException(trap_result_obj)) - return -1; - if (!JS_IsObject(trap_result_obj) && !JS_IsNull(trap_result_obj)) { - JS_FreeValue(ctx, trap_result_obj); - goto fail; - } - target_desc_ret = JS_GetOwnPropertyInternal(ctx, &target_desc, p, prop); - if (target_desc_ret < 0) { - JS_FreeValue(ctx, trap_result_obj); - return -1; - } - if (target_desc_ret) - js_free_desc(ctx, &target_desc); - if (JS_IsNull(trap_result_obj)) { - if (target_desc_ret) { - if (!(target_desc.flags & JS_PROP_CONFIGURABLE) || !p->extensible) - goto fail; - } - ret = FALSE; - } else { - int flags1, extensible_target; - extensible_target = JS_IsExtensible(ctx, s->target); - if (extensible_target < 0) { - JS_FreeValue(ctx, trap_result_obj); - return -1; - } - res = js_obj_to_desc(ctx, &result_desc, trap_result_obj); - JS_FreeValue(ctx, trap_result_obj); - if (res < 0) - return -1; - - /* convert the result_desc.flags to property flags */ - if (result_desc.flags & (JS_PROP_HAS_GET | JS_PROP_HAS_SET)) { - result_desc.flags |= JS_PROP_GETSET; - } else { - result_desc.flags |= JS_PROP_NORMAL; - } - result_desc.flags &= (JS_PROP_C_W_E | JS_PROP_TMASK); - - if (target_desc_ret) { - /* convert result_desc.flags to defineProperty flags */ - flags1 = result_desc.flags | JS_PROP_HAS_CONFIGURABLE | JS_PROP_HAS_ENUMERABLE; - if (result_desc.flags & JS_PROP_GETSET) - flags1 |= JS_PROP_HAS_GET | JS_PROP_HAS_SET; - else - flags1 |= JS_PROP_HAS_VALUE | JS_PROP_HAS_WRITABLE; - /* XXX: not complete check: need to compare value & - getter/setter as in defineproperty */ - if (!check_define_prop_flags(target_desc.flags, flags1)) - goto fail1; - } else { - if (!extensible_target) - goto fail1; - } - if (!(result_desc.flags & JS_PROP_CONFIGURABLE)) { - if (!target_desc_ret || (target_desc.flags & JS_PROP_CONFIGURABLE)) - goto fail1; - if ((result_desc.flags & - (JS_PROP_GETSET | JS_PROP_WRITABLE)) == 0 && - target_desc_ret && - (target_desc.flags & JS_PROP_WRITABLE) != 0) { - /* proxy-missing-checks */ - fail1: - js_free_desc(ctx, &result_desc); - fail: - JS_ThrowTypeError(ctx, "proxy: inconsistent getOwnPropertyDescriptor"); - return -1; - } - } - ret = TRUE; - if (pdesc) { - *pdesc = result_desc; - } else { - js_free_desc(ctx, &result_desc); - } - } - return ret; -} - -static int js_proxy_define_own_property(JSContext *ctx, JSValueConst obj, - JSAtom prop, JSValueConst val, - JSValueConst getter, JSValueConst setter, - int flags) -{ - JSProxyData *s; - JSValue method, ret1, prop_val, desc_val; - int res, ret; - JSObject *p; - JSValueConst args[3]; - JSPropertyDescriptor desc; - BOOL setting_not_configurable; - - s = get_proxy_method(ctx, &method, obj, JS_ATOM_defineProperty); - if (!s) - return -1; - if (JS_IsNull(method)) { - return JS_DefineProperty(ctx, s->target, prop, val, getter, setter, flags); - } - prop_val = JS_AtomToValue(ctx, prop); - if (JS_IsException(prop_val)) { - JS_FreeValue(ctx, method); - return -1; - } - desc_val = js_create_desc(ctx, val, getter, setter, flags); - if (JS_IsException(desc_val)) { - JS_FreeValue(ctx, prop_val); - JS_FreeValue(ctx, method); - return -1; - } - args[0] = s->target; - args[1] = prop_val; - args[2] = desc_val; - ret1 = JS_CallFree(ctx, method, s->handler, 3, args); - JS_FreeValue(ctx, prop_val); - JS_FreeValue(ctx, desc_val); - if (JS_IsException(ret1)) - return -1; - ret = JS_ToBoolFree(ctx, ret1); - if (!ret) { - if (flags & JS_PROP_THROW) { - JS_ThrowTypeError(ctx, "proxy: defineProperty exception"); - return -1; - } else { - return 0; - } - } - p = JS_VALUE_GET_OBJ(s->target); - res = JS_GetOwnPropertyInternal(ctx, &desc, p, prop); - if (res < 0) - return -1; - setting_not_configurable = ((flags & (JS_PROP_HAS_CONFIGURABLE | - JS_PROP_CONFIGURABLE)) == - JS_PROP_HAS_CONFIGURABLE); - if (!res) { - if (!p->extensible || setting_not_configurable) - goto fail; - } else { - if (!check_define_prop_flags(desc.flags, flags)) - goto fail1; - /* do the missing check from check_define_prop_flags() */ - if (!(desc.flags & JS_PROP_CONFIGURABLE)) { - if ((desc.flags & JS_PROP_TMASK) == JS_PROP_GETSET) { - if ((flags & JS_PROP_HAS_GET) && - !js_same_value(ctx, getter, desc.getter)) { - goto fail1; - } - if ((flags & JS_PROP_HAS_SET) && - !js_same_value(ctx, setter, desc.setter)) { - goto fail1; - } - } else if (!(desc.flags & JS_PROP_WRITABLE)) { - if ((flags & JS_PROP_HAS_VALUE) && - !js_same_value(ctx, val, desc.value)) { - goto fail1; - } - } - } - - /* additional checks */ - if ((desc.flags & JS_PROP_CONFIGURABLE) && setting_not_configurable) - goto fail1; - - if ((desc.flags & JS_PROP_TMASK) != JS_PROP_GETSET && - (desc.flags & (JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE)) == JS_PROP_WRITABLE && - (flags & (JS_PROP_HAS_WRITABLE | JS_PROP_WRITABLE)) == JS_PROP_HAS_WRITABLE) { - fail1: - js_free_desc(ctx, &desc); - fail: - JS_ThrowTypeError(ctx, "proxy: inconsistent defineProperty"); - return -1; - } - js_free_desc(ctx, &desc); - } - return 1; -} - -static int js_proxy_delete_property(JSContext *ctx, JSValueConst obj, - JSAtom atom) -{ - JSProxyData *s; - JSValue method, ret, atom_val; - int res, res2, is_extensible; - JSValueConst args[2]; - - s = get_proxy_method(ctx, &method, obj, JS_ATOM_deleteProperty); - if (!s) - return -1; - if (JS_IsNull(method)) { - return JS_DeleteProperty(ctx, s->target, atom, 0); - } - atom_val = JS_AtomToValue(ctx, atom);; - if (JS_IsException(atom_val)) { - JS_FreeValue(ctx, method); - return -1; - } - args[0] = s->target; - args[1] = atom_val; - ret = JS_CallFree(ctx, method, s->handler, 2, args); - JS_FreeValue(ctx, atom_val); - if (JS_IsException(ret)) - return -1; - res = JS_ToBoolFree(ctx, ret); - if (res) { - JSPropertyDescriptor desc; - res2 = JS_GetOwnPropertyInternal(ctx, &desc, JS_VALUE_GET_OBJ(s->target), atom); - if (res2 < 0) - return -1; - if (res2) { - if (!(desc.flags & JS_PROP_CONFIGURABLE)) - goto fail; - is_extensible = JS_IsExtensible(ctx, s->target); - if (is_extensible < 0) - goto fail1; - if (!is_extensible) { - /* proxy-missing-checks */ - fail: - JS_ThrowTypeError(ctx, "proxy: inconsistent deleteProperty"); - fail1: - js_free_desc(ctx, &desc); - return -1; - } - js_free_desc(ctx, &desc); - } - } - return res; -} - -/* return the index of the property or -1 if not found */ -static int find_prop_key(const JSPropertyEnum *tab, int n, JSAtom atom) -{ - int i; - for(i = 0; i < n; i++) { - if (tab[i].atom == atom) - return i; - } - return -1; -} - -static int js_proxy_get_own_property_names(JSContext *ctx, - JSPropertyEnum **ptab, - uint32_t *plen, - JSValueConst obj) -{ - JSProxyData *s; - JSValue method, prop_array, val; - uint32_t len, i, len2; - JSPropertyEnum *tab, *tab2; - JSAtom atom; - JSPropertyDescriptor desc; - int res, is_extensible, idx; - - s = get_proxy_method(ctx, &method, obj, JS_ATOM_ownKeys); - if (!s) - return -1; - if (JS_IsNull(method)) { - return JS_GetOwnPropertyNamesInternal(ctx, ptab, plen, - JS_VALUE_GET_OBJ(s->target), - JS_GPN_STRING_MASK | JS_GPN_SYMBOL_MASK); - } - prop_array = JS_CallFree(ctx, method, s->handler, 1, (JSValueConst *)&s->target); - if (JS_IsException(prop_array)) - return -1; - tab = NULL; - len = 0; - tab2 = NULL; - len2 = 0; - if (js_get_length32(ctx, &len, prop_array)) - goto fail; - if (len > 0) { - tab = js_mallocz(ctx, sizeof(tab[0]) * len); - if (!tab) - goto fail; - } - for(i = 0; i < len; i++) { - val = JS_GetPropertyUint32(ctx, prop_array, i); - if (JS_IsException(val)) - goto fail; - if (!JS_IsString(val) && !JS_IsSymbol(val)) { - JS_FreeValue(ctx, val); - JS_ThrowTypeError(ctx, "proxy: properties must be strings or symbols"); - goto fail; - } - atom = JS_ValueToAtom(ctx, val); - JS_FreeValue(ctx, val); - if (atom == JS_ATOM_NULL) - goto fail; - tab[i].atom = atom; - tab[i].is_enumerable = FALSE; /* XXX: redundant? */ - } - - /* check duplicate properties (XXX: inefficient, could store the - * properties an a temporary object to use the hash) */ - for(i = 1; i < len; i++) { - if (find_prop_key(tab, i, tab[i].atom) >= 0) { - JS_ThrowTypeError(ctx, "proxy: duplicate property"); - goto fail; - } - } - - is_extensible = JS_IsExtensible(ctx, s->target); - if (is_extensible < 0) - goto fail; - - /* check if there are non configurable properties */ - if (s->is_revoked) { - JS_ThrowTypeErrorRevokedProxy(ctx); - goto fail; - } - if (JS_GetOwnPropertyNamesInternal(ctx, &tab2, &len2, JS_VALUE_GET_OBJ(s->target), - JS_GPN_STRING_MASK | JS_GPN_SYMBOL_MASK)) - goto fail; - for(i = 0; i < len2; i++) { - if (s->is_revoked) { - JS_ThrowTypeErrorRevokedProxy(ctx); - goto fail; - } - res = JS_GetOwnPropertyInternal(ctx, &desc, JS_VALUE_GET_OBJ(s->target), - tab2[i].atom); - if (res < 0) - goto fail; - if (res) { /* safety, property should be found */ - js_free_desc(ctx, &desc); - if (!(desc.flags & JS_PROP_CONFIGURABLE) || !is_extensible) { - idx = find_prop_key(tab, len, tab2[i].atom); - if (idx < 0) { - JS_ThrowTypeError(ctx, "proxy: target property must be present in proxy ownKeys"); - goto fail; - } - /* mark the property as found */ - if (!is_extensible) - tab[idx].is_enumerable = TRUE; - } - } - } - if (!is_extensible) { - /* check that all property in 'tab' were checked */ - for(i = 0; i < len; i++) { - if (!tab[i].is_enumerable) { - JS_ThrowTypeError(ctx, "proxy: property not present in target were returned by non extensible proxy"); - goto fail; - } - } - } - - JS_FreePropertyEnum(ctx, tab2, len2); - JS_FreeValue(ctx, prop_array); - *ptab = tab; - *plen = len; - return 0; - fail: - JS_FreePropertyEnum(ctx, tab2, len2); - JS_FreePropertyEnum(ctx, tab, len); - JS_FreeValue(ctx, prop_array); - return -1; -} - -static JSValue js_proxy_call_constructor(JSContext *ctx, JSValueConst func_obj, - JSValueConst new_target, - int argc, JSValueConst *argv) -{ - JSProxyData *s; - JSValue method, arg_array, ret; - JSValueConst args[3]; - - s = get_proxy_method(ctx, &method, func_obj, JS_ATOM_construct); - if (!s) - return JS_EXCEPTION; - if (!JS_IsConstructor(ctx, s->target)) - return JS_ThrowTypeError(ctx, "not a constructor"); - if (JS_IsNull(method)) - return JS_CallConstructor2(ctx, s->target, new_target, argc, argv); - arg_array = js_create_array(ctx, argc, argv); - if (JS_IsException(arg_array)) { - ret = JS_EXCEPTION; - goto fail; - } - args[0] = s->target; - args[1] = arg_array; - args[2] = new_target; - ret = JS_Call(ctx, method, s->handler, 3, args); - if (!JS_IsException(ret) && JS_VALUE_GET_TAG(ret) != JS_TAG_OBJECT) { - JS_FreeValue(ctx, ret); - ret = JS_ThrowTypeErrorNotAnObject(ctx); - } - fail: - JS_FreeValue(ctx, method); - JS_FreeValue(ctx, arg_array); - return ret; -} - -static JSValue js_proxy_call(JSContext *ctx, JSValueConst func_obj, - JSValueConst this_obj, - int argc, JSValueConst *argv, int flags) -{ - JSProxyData *s; - JSValue method, arg_array, ret; - JSValueConst args[3]; - - if (flags & JS_CALL_FLAG_CONSTRUCTOR) - return js_proxy_call_constructor(ctx, func_obj, this_obj, argc, argv); - - s = get_proxy_method(ctx, &method, func_obj, JS_ATOM_apply); - if (!s) - return JS_EXCEPTION; - if (!s->is_func) { - JS_FreeValue(ctx, method); - return JS_ThrowTypeError(ctx, "not a function"); - } - if (JS_IsNull(method)) - return JS_Call(ctx, s->target, this_obj, argc, argv); - arg_array = js_create_array(ctx, argc, argv); - if (JS_IsException(arg_array)) { - ret = JS_EXCEPTION; - goto fail; - } - args[0] = s->target; - args[1] = this_obj; - args[2] = arg_array; - ret = JS_Call(ctx, method, s->handler, 3, args); - fail: - JS_FreeValue(ctx, method); - JS_FreeValue(ctx, arg_array); - return ret; -} - -/* `js_resolve_proxy`: resolve the proxy chain - `*pval` is updated with to ultimate proxy target - `throw_exception` controls whether exceptions are thown or not - - return -1 in case of error - - otherwise return 0 - */ -static int js_resolve_proxy(JSContext *ctx, JSValueConst *pval, BOOL throw_exception) { - int depth = 0; - JSObject *p; - JSProxyData *s; - - while (JS_VALUE_GET_TAG(*pval) == JS_TAG_OBJECT) { - p = JS_VALUE_GET_OBJ(*pval); - if (p->class_id != JS_CLASS_PROXY) - break; - if (depth++ > 1000) { - if (throw_exception) - JS_ThrowStackOverflow(ctx); - return -1; - } - s = p->u.opaque; - if (s->is_revoked) { - if (throw_exception) - JS_ThrowTypeErrorRevokedProxy(ctx); - return -1; - } - *pval = s->target; - } - return 0; -} - -static const JSClassExoticMethods js_proxy_exotic_methods = { - .get_own_property = js_proxy_get_own_property, - .define_own_property = js_proxy_define_own_property, - .delete_property = js_proxy_delete_property, - .get_own_property_names = js_proxy_get_own_property_names, - .has_property = js_proxy_has, - .get_property = js_proxy_get, - .set_property = js_proxy_set, - .get_prototype = js_proxy_get_prototype, - .set_prototype = js_proxy_set_prototype, - .is_extensible = js_proxy_is_extensible, - .prevent_extensions = js_proxy_prevent_extensions, -}; - -static JSValue js_proxy_constructor(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSValueConst target, handler; - JSValue obj; - JSProxyData *s; - - target = argv[0]; - handler = argv[1]; - if (JS_VALUE_GET_TAG(target) != JS_TAG_OBJECT || - JS_VALUE_GET_TAG(handler) != JS_TAG_OBJECT) - return JS_ThrowTypeErrorNotAnObject(ctx); - - obj = JS_NewObjectProtoClass(ctx, JS_NULL, JS_CLASS_PROXY); - if (JS_IsException(obj)) - return obj; - s = js_malloc(ctx, sizeof(JSProxyData)); - if (!s) { - JS_FreeValue(ctx, obj); - return JS_EXCEPTION; - } - s->target = JS_DupValue(ctx, target); - s->handler = JS_DupValue(ctx, handler); - s->is_func = JS_IsFunction(ctx, target); - s->is_revoked = FALSE; - JS_SetOpaque(obj, s); - JS_SetConstructorBit(ctx, obj, JS_IsConstructor(ctx, target)); - return obj; -} - -static JSValue js_proxy_revoke(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int magic, - JSValue *func_data) -{ - JSProxyData *s = JS_GetOpaque(func_data[0], JS_CLASS_PROXY); - if (s) { - /* We do not free the handler and target in case they are - referenced as constants in the C call stack */ - s->is_revoked = TRUE; - JS_FreeValue(ctx, func_data[0]); - func_data[0] = JS_NULL; - } - return JS_NULL; -} - -static JSValue js_proxy_revoke_constructor(JSContext *ctx, - JSValueConst proxy_obj) -{ - return JS_NewCFunctionData(ctx, js_proxy_revoke, 0, 0, 1, &proxy_obj); -} - -static JSValue js_proxy_revocable(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSValue proxy_obj, revoke_obj = JS_NULL, obj; - - proxy_obj = js_proxy_constructor(ctx, JS_NULL, argc, argv); - if (JS_IsException(proxy_obj)) - goto fail; - revoke_obj = js_proxy_revoke_constructor(ctx, proxy_obj); - if (JS_IsException(revoke_obj)) - goto fail; - obj = JS_NewObject(ctx); - if (JS_IsException(obj)) - goto fail; - // XXX: exceptions? - JS_DefinePropertyValue(ctx, obj, JS_ATOM_proxy, proxy_obj, JS_PROP_C_W_E); - JS_DefinePropertyValue(ctx, obj, JS_ATOM_revoke, revoke_obj, JS_PROP_C_W_E); - return obj; - fail: - JS_FreeValue(ctx, proxy_obj); - JS_FreeValue(ctx, revoke_obj); - return JS_EXCEPTION; -} - -static const JSCFunctionListEntry js_proxy_funcs[] = { - JS_CFUNC_DEF("revocable", 2, js_proxy_revocable ), -}; - -static const JSClassShortDef js_proxy_class_def[] = { - { JS_ATOM_Object, js_proxy_finalizer, js_proxy_mark }, /* JS_CLASS_PROXY */ -}; - -void JS_AddIntrinsicProxy(JSContext *ctx) -{ - JSRuntime *rt = ctx->rt; - JSValue obj1; - - if (!JS_IsRegisteredClass(rt, JS_CLASS_PROXY)) { - init_class_range(rt, js_proxy_class_def, JS_CLASS_PROXY, - countof(js_proxy_class_def)); - rt->class_array[JS_CLASS_PROXY].exotic = &js_proxy_exotic_methods; - rt->class_array[JS_CLASS_PROXY].call = js_proxy_call; - } - - obj1 = JS_NewCFunction2(ctx, js_proxy_constructor, "Proxy", 2, - JS_CFUNC_constructor, 0); - JS_SetConstructorBit(ctx, obj1, TRUE); - JS_SetPropertyFunctionList(ctx, obj1, js_proxy_funcs, - countof(js_proxy_funcs)); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "Proxy", - obj1, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); -} - /* Symbol */ static JSValue js_symbol_constructor(JSContext *ctx, JSValueConst new_target,