shithub: libmujs

Download patch

ref: 979c7bc1bd282ff5a6158ea984557fbf5f51af6d
parent: a09493e144f661927c07b53f0a6f15a632721694
author: Tor Andersson <tor@ccxvii.net>
date: Fri Feb 7 05:57:52 EST 2014

Implement extensible object attribute.

--- a/jsobject.c
+++ b/jsobject.c
@@ -292,6 +292,109 @@
 	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 @@
 		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);
--- a/jsproperty.c
+++ b/jsproperty.c
@@ -155,6 +155,7 @@
 	obj->type = type;
 	obj->properties = &sentinel;
 	obj->prototype = prototype;
+	obj->extensible = 1;
 	return obj;
 }
 
@@ -190,6 +191,10 @@
 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) {
--- a/jsrun.c
+++ b/jsrun.c
@@ -467,7 +467,7 @@
 	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 @@
 	}
 
 	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)
--- a/jsvalue.h
+++ b/jsvalue.h
@@ -55,6 +55,7 @@
 struct js_Object
 {
 	js_Class type;
+	int extensible;
 	js_Property *properties;
 	js_Property *head, *tail; /* for enumeration */
 	js_Object *prototype;