summaryrefslogtreecommitdiff
path: root/quickjs.c
diff options
context:
space:
mode:
authorFabrice Bellard <fabrice@bellard.org>2025-04-29 19:03:36 +0200
committerFabrice Bellard <fabrice@bellard.org>2025-04-29 19:03:36 +0200
commit30fe3de91dd49bc6f725bbae24095c99fe7d001f (patch)
tree490cd74f8fa9528127b18a7e5ace7fcbf1d54084 /quickjs.c
parent53327c2580de657b3d243d9f7de99e6ff2f227b8 (diff)
downloadquickjs-30fe3de91dd49bc6f725bbae24095c99fe7d001f.tar.gz
quickjs-30fe3de91dd49bc6f725bbae24095c99fe7d001f.zip
Object.prototype has an immutable prototype
Diffstat (limited to 'quickjs.c')
-rw-r--r--quickjs.c23
1 files changed, 22 insertions, 1 deletions
diff --git a/quickjs.c b/quickjs.c
index 9979dc4..aa174e9 100644
--- a/quickjs.c
+++ b/quickjs.c
@@ -914,6 +914,7 @@ struct JSObject {
uint8_t is_exotic : 1; /* TRUE if object has exotic property handlers */
uint8_t fast_array : 1; /* TRUE if u.array is used for get/put (for JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS and typed arrays) */
uint8_t is_constructor : 1; /* TRUE if object is a constructor function */
+ uint8_t has_immutable_prototype : 1; /* cannot modify the prototype */
uint8_t tmp_mark : 1; /* used in JS_WriteObjectRec() */
uint8_t is_HTMLDDA : 1; /* specific annex B IsHtmlDDA behavior */
uint16_t class_id; /* see JS_CLASS_x */
@@ -5053,6 +5054,7 @@ static JSValue JS_NewObjectFromShape(JSContext *ctx, JSShape *sh, JSClassID clas
p->is_exotic = 0;
p->fast_array = 0;
p->is_constructor = 0;
+ p->has_immutable_prototype = 0;
p->tmp_mark = 0;
p->is_HTMLDDA = 0;
p->weakref_count = 0;
@@ -7192,6 +7194,15 @@ static inline __exception int js_poll_interrupts(JSContext *ctx)
}
}
+static void JS_SetImmutablePrototype(JSContext *ctx, JSValueConst obj)
+{
+ JSObject *p;
+ if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)
+ return;
+ p = JS_VALUE_GET_OBJ(obj);
+ p->has_immutable_prototype = TRUE;
+}
+
/* Return -1 (exception) or TRUE/FALSE. 'throw_flag' = FALSE indicates
that it is called from Reflect.setPrototypeOf(). */
static int JS_SetPrototypeInternal(JSContext *ctx, JSValueConst obj,
@@ -7241,7 +7252,15 @@ static int JS_SetPrototypeInternal(JSContext *ctx, JSValueConst obj,
sh = p->shape;
if (sh->proto == proto)
return TRUE;
- if (!p->extensible) {
+ if (unlikely(p->has_immutable_prototype)) {
+ if (throw_flag) {
+ JS_ThrowTypeError(ctx, "prototype is immutable");
+ return -1;
+ } else {
+ return FALSE;
+ }
+ }
+ if (unlikely(!p->extensible)) {
if (throw_flag) {
JS_ThrowTypeError(ctx, "object is not extensible");
return -1;
@@ -51162,6 +51181,8 @@ static void JS_AddIntrinsicBasicObjects(JSContext *ctx)
int i;
ctx->class_proto[JS_CLASS_OBJECT] = JS_NewObjectProto(ctx, JS_NULL);
+ JS_SetImmutablePrototype(ctx, ctx->class_proto[JS_CLASS_OBJECT]);
+
ctx->function_proto = JS_NewCFunction3(ctx, js_function_proto, "", 0,
JS_CFUNC_generic, 0,
ctx->class_proto[JS_CLASS_OBJECT]);