From 979c7bc1bd282ff5a6158ea984557fbf5f51af6d Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Fri, 7 Feb 2014 10:57:52 +0100 Subject: [PATCH] Implement extensible object attribute. --- jsobject.c | 115 ++++++++++++++++++++++++++++++++++++++++++++++++--- jsproperty.c | 5 +++ jsrun.c | 18 ++++---- jsvalue.h | 1 + 4 files changed, 125 insertions(+), 14 deletions(-) diff --git a/jsobject.c b/jsobject.c index 82f631d..b096205 100644 --- a/jsobject.c +++ b/jsobject.c @@ -292,6 +292,109 @@ static int O_keys(js_State *J, int argc) return 1; } +static int O_preventExtensions(js_State *J, int argc) +{ + if (!js_isobject(J, 1)) + js_typeerror(J, "not an object"); + js_toobject(J, 1)->extensible = 0; + js_copy(J, 1); + return 1; +} + +static int O_isExtensible(js_State *J, int argc) +{ + if (!js_isobject(J, 1)) + js_typeerror(J, "not an object"); + js_pushboolean(J, js_toobject(J, 1)->extensible); + return 1; +} + +static int O_seal(js_State *J, int argc) +{ + js_Object *obj; + js_Property *ref; + + if (!js_isobject(J, 1)) + js_typeerror(J, "not an object"); + + obj = js_toobject(J, 1); + obj->extensible = 0; + + for (ref = obj->head; ref; ref = ref->next) + ref->atts |= JS_DONTCONF; + + js_copy(J, 1); + return 1; +} + +static int O_isSealed(js_State *J, int argc) +{ + js_Object *obj; + js_Property *ref; + + if (!js_isobject(J, 1)) + js_typeerror(J, "not an object"); + + obj = js_toobject(J, 1); + if (obj->extensible) { + js_pushboolean(J, 0); + return 1; + } + + for (ref = obj->head; ref; ref = ref->next) { + if (!(ref->atts & JS_DONTCONF)) { + js_pushboolean(J, 0); + return 1; + } + } + + js_pushboolean(J, 1); + return 1; +} + +static int O_freeze(js_State *J, int argc) +{ + js_Object *obj; + js_Property *ref; + + if (!js_isobject(J, 1)) + js_typeerror(J, "not an object"); + + obj = js_toobject(J, 1); + obj->extensible = 0; + + for (ref = obj->head; ref; ref = ref->next) + ref->atts |= JS_READONLY | JS_DONTCONF; + + js_copy(J, 1); + return 1; +} + +static int O_isFrozen(js_State *J, int argc) +{ + js_Object *obj; + js_Property *ref; + + if (!js_isobject(J, 1)) + js_typeerror(J, "not an object"); + + obj = js_toobject(J, 1); + if (obj->extensible) { + js_pushboolean(J, 0); + return 1; + } + + for (ref = obj->head; ref; ref = ref->next) { + if (!(ref->atts & (JS_READONLY | JS_DONTCONF))) { + js_pushboolean(J, 0); + return 1; + } + } + + js_pushboolean(J, 1); + return 1; +} + void jsB_initobject(js_State *J) { js_pushobject(J, J->Object_prototype); @@ -312,12 +415,12 @@ void jsB_initobject(js_State *J) jsB_propf(J, "create", O_create, 2); jsB_propf(J, "defineProperty", O_defineProperty, 3); jsB_propf(J, "defineProperties", O_defineProperties, 2); - //jsB_propf(J, "seal", O_seal, 1); - //jsB_propf(J, "freeze", O_freeze, 1); - //jsB_propf(J, "preventExtensions", O_preventExtensions, 1); - //jsB_propf(J, "isSealed", O_isSealed, 1); - //jsB_propf(J, "isFrozen", O_isFrozen, 1); - //jsB_propf(J, "isExtensible", O_isExtensible, 1); + jsB_propf(J, "seal", O_seal, 1); + jsB_propf(J, "freeze", O_freeze, 1); + jsB_propf(J, "preventExtensions", O_preventExtensions, 1); + jsB_propf(J, "isSealed", O_isSealed, 1); + jsB_propf(J, "isFrozen", O_isFrozen, 1); + jsB_propf(J, "isExtensible", O_isExtensible, 1); jsB_propf(J, "keys", O_keys, 1); } js_defglobal(J, "Object", JS_DONTENUM); diff --git a/jsproperty.c b/jsproperty.c index eb6d2da..ea7e89e 100644 --- a/jsproperty.c +++ b/jsproperty.c @@ -155,6 +155,7 @@ js_Object *jsV_newobject(js_State *J, js_Class type, js_Object *prototype) obj->type = type; obj->properties = &sentinel; obj->prototype = prototype; + obj->extensible = 1; return obj; } @@ -190,6 +191,10 @@ js_Property *jsV_getproperty(js_State *J, js_Object *obj, const char *name) js_Property *jsV_setproperty(js_State *J, js_Object *obj, const char *name) { js_Property *result; + + if (!obj->extensible) + return lookup(obj->properties, name); + obj->properties = insert(J, obj->properties, name, &result); if (!result->prevp) { if (!obj->head) { diff --git a/jsrun.c b/jsrun.c index 4f1fed3..c25cfc9 100644 --- a/jsrun.c +++ b/jsrun.c @@ -467,7 +467,7 @@ static void jsR_setproperty(js_State *J, js_Object *obj, const char *name, const if (!ref || !own) ref = jsV_setproperty(J, obj, name); - if (!(ref->atts & JS_READONLY)) + if (ref && !(ref->atts & JS_READONLY)) ref->value = *value; } @@ -491,13 +491,15 @@ static void jsR_defproperty(js_State *J, js_Object *obj, const char *name, } ref = jsV_setproperty(J, obj, name); - if (value && !(ref->atts & JS_READONLY)) - ref->value = *value; - if (getter && !(ref->atts & JS_DONTCONF)) - ref->getter = getter; - if (setter && !(ref->atts & JS_DONTCONF)) - ref->setter = setter; - ref->atts |= atts; + if (ref) { + if (value && !(ref->atts & JS_READONLY)) + ref->value = *value; + if (getter && !(ref->atts & JS_DONTCONF)) + ref->getter = getter; + if (setter && !(ref->atts & JS_DONTCONF)) + ref->setter = setter; + ref->atts |= atts; + } } static int jsR_delproperty(js_State *J, js_Object *obj, const char *name) diff --git a/jsvalue.h b/jsvalue.h index bff3b12..d9e2fc2 100644 --- a/jsvalue.h +++ b/jsvalue.h @@ -55,6 +55,7 @@ struct js_Regexp struct js_Object { js_Class type; + int extensible; js_Property *properties; js_Property *head, *tail; /* for enumeration */ js_Object *prototype;