Skip to content

Commit 6446efc

Browse files
authored
Test that global object prototype can be changed (#1180)
Also fix JS_SetPrototype's function prototype because it suggested it took ownership of the prototype object (i.e., was responsible for freeing it) when it doesn't.
1 parent 5f91729 commit 6446efc

File tree

3 files changed

+89
-2
lines changed

3 files changed

+89
-2
lines changed

api-test.c

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,92 @@ static void new_errors(void)
545545
JS_FreeRuntime(rt);
546546
}
547547

548+
static int gop_get_own_property(JSContext *ctx, JSPropertyDescriptor *desc,
549+
JSValueConst obj, JSAtom prop)
550+
{
551+
const char *name;
552+
int found;
553+
554+
found = 0;
555+
name = JS_AtomToCString(ctx, prop);
556+
if (!name)
557+
return -1;
558+
if (!strcmp(name, "answer")) {
559+
found = 1;
560+
*desc = (JSPropertyDescriptor){
561+
.value = JS_NewInt32(ctx, 42),
562+
.flags = JS_PROP_C_W_E | JS_PROP_HAS_VALUE,
563+
};
564+
}
565+
JS_FreeCString(ctx, name);
566+
return found;
567+
}
568+
569+
static void global_object_prototype(void)
570+
{
571+
static const char code[] = "answer";
572+
JSValue global_object, proto, ret;
573+
JSClassID class_id;
574+
JSRuntime *rt;
575+
JSContext *ctx;
576+
int32_t answer;
577+
int res;
578+
579+
{
580+
rt = JS_NewRuntime();
581+
ctx = JS_NewContext(rt);
582+
proto = JS_NewObject(ctx);
583+
assert(JS_IsObject(proto));
584+
JSCFunctionListEntry prop = JS_PROP_INT32_DEF("answer", 42, JS_PROP_C_W_E);
585+
JS_SetPropertyFunctionList(ctx, proto, &prop, 1);
586+
global_object = JS_GetGlobalObject(ctx);
587+
res = JS_SetPrototype(ctx, global_object, proto);
588+
assert(res == true);
589+
JS_FreeValue(ctx, global_object);
590+
JS_FreeValue(ctx, proto);
591+
ret = JS_Eval(ctx, code, strlen(code), "*", JS_EVAL_TYPE_GLOBAL);
592+
assert(!JS_IsException(ret));
593+
assert(JS_IsNumber(ret));
594+
res = JS_ToInt32(ctx, &answer, ret);
595+
assert(res == 0);
596+
assert(answer == 42);
597+
JS_FreeValue(ctx, ret);
598+
JS_FreeContext(ctx);
599+
JS_FreeRuntime(rt);
600+
}
601+
{
602+
JSClassExoticMethods exotic = (JSClassExoticMethods){
603+
.get_own_property = gop_get_own_property,
604+
};
605+
JSClassDef def = (JSClassDef){
606+
.class_name = "Global Object",
607+
.exotic = &exotic,
608+
};
609+
rt = JS_NewRuntime();
610+
class_id = 0;
611+
JS_NewClassID(rt, &class_id);
612+
res = JS_NewClass(rt, class_id, &def);
613+
assert(res == 0);
614+
ctx = JS_NewContext(rt);
615+
proto = JS_NewObjectClass(ctx, class_id);
616+
assert(JS_IsObject(proto));
617+
global_object = JS_GetGlobalObject(ctx);
618+
res = JS_SetPrototype(ctx, global_object, proto);
619+
assert(res == true);
620+
JS_FreeValue(ctx, global_object);
621+
JS_FreeValue(ctx, proto);
622+
ret = JS_Eval(ctx, code, strlen(code), "*", JS_EVAL_TYPE_GLOBAL);
623+
assert(!JS_IsException(ret));
624+
assert(JS_IsNumber(ret));
625+
res = JS_ToInt32(ctx, &answer, ret);
626+
assert(res == 0);
627+
assert(answer == 42);
628+
JS_FreeValue(ctx, ret);
629+
JS_FreeContext(ctx);
630+
JS_FreeRuntime(rt);
631+
}
632+
}
633+
548634
int main(void)
549635
{
550636
sync_call();
@@ -558,5 +644,6 @@ int main(void)
558644
promise_hook();
559645
dump_memory_usage();
560646
new_errors();
647+
global_object_prototype();
561648
return 0;
562649
}

quickjs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7362,7 +7362,7 @@ static int JS_SetPrototypeInternal(JSContext *ctx, JSValueConst obj,
73627362
}
73637363

73647364
/* return -1 (exception) or true/false */
7365-
int JS_SetPrototype(JSContext *ctx, JSValueConst obj, JSValue proto_val)
7365+
int JS_SetPrototype(JSContext *ctx, JSValueConst obj, JSValueConst proto_val)
73667366
{
73677367
return JS_SetPrototypeInternal(ctx, obj, proto_val, true);
73687368
}

quickjs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -882,7 +882,7 @@ JS_EXTERN int JS_HasProperty(JSContext *ctx, JSValueConst this_obj, JSAtom prop)
882882
JS_EXTERN int JS_IsExtensible(JSContext *ctx, JSValueConst obj);
883883
JS_EXTERN int JS_PreventExtensions(JSContext *ctx, JSValueConst obj);
884884
JS_EXTERN int JS_DeleteProperty(JSContext *ctx, JSValueConst obj, JSAtom prop, int flags);
885-
JS_EXTERN int JS_SetPrototype(JSContext *ctx, JSValueConst obj, JSValue proto_val);
885+
JS_EXTERN int JS_SetPrototype(JSContext *ctx, JSValueConst obj, JSValueConst proto_val);
886886
JS_EXTERN JSValue JS_GetPrototype(JSContext *ctx, JSValueConst val);
887887
JS_EXTERN int JS_GetLength(JSContext *ctx, JSValueConst obj, int64_t *pres);
888888
JS_EXTERN int JS_SetLength(JSContext *ctx, JSValueConst obj, int64_t len);

0 commit comments

Comments
 (0)