shithub: libmujs

Download patch

ref: 91dc20d3e3bdf5e30a5a750fcb35395d570673e1
parent: b51b05b21687850c07b3f04bd40b6709f859b0bf
author: Tor Andersson <tor.andersson@artifex.com>
date: Wed Jan 7 13:06:50 EST 2015

strict mode: Errors on read-only and non-configurable properties.

--- a/jsrun.c
+++ b/jsrun.c
@@ -521,17 +521,17 @@
 
 	if (obj->type == JS_CSTRING) {
 		if (!strcmp(name, "length"))
-			return;
+			goto readonly;
 		if (js_isarrayindex(J, name, &k))
 			if (js_runeat(J, obj->u.s.string, k))
-				return;
+				goto readonly;
 	}
 
 	if (obj->type == JS_CREGEXP) {
-		if (!strcmp(name, "source")) return;
-		if (!strcmp(name, "global")) return;
-		if (!strcmp(name, "ignoreCase")) return;
-		if (!strcmp(name, "multiline")) return;
+		if (!strcmp(name, "source")) goto readonly;
+		if (!strcmp(name, "global")) goto readonly;
+		if (!strcmp(name, "ignoreCase")) goto readonly;
+		if (!strcmp(name, "multiline")) goto readonly;
 		if (!strcmp(name, "lastIndex")) {
 			obj->u.r.last = jsV_tointeger(J, value);
 			return;
@@ -553,8 +553,18 @@
 	if (!ref || !own)
 		ref = jsV_setproperty(J, obj, name);
 
-	if (ref && !(ref->atts & JS_READONLY))
-		ref->value = *value;
+	if (ref) {
+		if (!(ref->atts & JS_READONLY))
+			ref->value = *value;
+		else
+			goto readonly;
+	}
+
+	return;
+
+readonly:
+	if (J->strict)
+		js_typeerror(J, "'%s' is read-only", name);
 }
 
 static void jsR_defproperty(js_State *J, js_Object *obj, const char *name,
@@ -565,34 +575,52 @@
 
 	if (obj->type == JS_CARRAY)
 		if (!strcmp(name, "length"))
-			return;
+			goto readonly;
 
 	if (obj->type == JS_CSTRING) {
 		if (!strcmp(name, "length"))
-			return;
+			goto readonly;
 		if (js_isarrayindex(J, name, &k))
 			if (js_runeat(J, obj->u.s.string, k))
-				return;
+				goto readonly;
 	}
 
 	if (obj->type == JS_CREGEXP) {
-		if (!strcmp(name, "source")) return;
-		if (!strcmp(name, "global")) return;
-		if (!strcmp(name, "ignoreCase")) return;
-		if (!strcmp(name, "multiline")) return;
-		if (!strcmp(name, "lastIndex")) return;
+		if (!strcmp(name, "source")) goto readonly;
+		if (!strcmp(name, "global")) goto readonly;
+		if (!strcmp(name, "ignoreCase")) goto readonly;
+		if (!strcmp(name, "multiline")) goto readonly;
+		if (!strcmp(name, "lastIndex")) goto readonly;
 	}
 
 	ref = jsV_setproperty(J, obj, name);
 	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;
+		if (value) {
+			if (!(ref->atts & JS_READONLY))
+				ref->value = *value;
+			else if (J->strict)
+				js_typeerror(J, "'%s' is read-only", name);
+		}
+		if (getter) {
+			if (!(ref->atts & JS_DONTCONF))
+				ref->getter = getter;
+			else if (J->strict)
+				js_typeerror(J, "'%s' is non-configurable", name);
+		}
+		if (setter) {
+			if (!(ref->atts & JS_DONTCONF))
+				ref->setter = setter;
+			else if (J->strict)
+				js_typeerror(J, "'%s' is non-configurable", name);
+		}
 		ref->atts |= atts;
 	}
+
+	return;
+
+readonly:
+	if (J->strict)
+		js_typeerror(J, "'%s' is read-only or non-configurable", name);
 }
 
 static int jsR_delproperty(js_State *J, js_Object *obj, const char *name)
@@ -601,31 +629,37 @@
 	unsigned int k;
 
 	if (obj->type == JS_CARRAY)
-		if (!strcmp(name, "length")) return 0;
+		if (!strcmp(name, "length"))
+			goto dontconf;
 
 	if (obj->type == JS_CSTRING) {
 		if (!strcmp(name, "length"))
-			return 0;
+			goto dontconf;
 		if (js_isarrayindex(J, name, &k))
 			if (js_runeat(J, obj->u.s.string, k))
-				return 0;
+				goto dontconf;
 	}
 
 	if (obj->type == JS_CREGEXP) {
-		if (!strcmp(name, "source")) return 0;
-		if (!strcmp(name, "global")) return 0;
-		if (!strcmp(name, "ignoreCase")) return 0;
-		if (!strcmp(name, "multiline")) return 0;
-		if (!strcmp(name, "lastIndex")) return 0;
+		if (!strcmp(name, "source")) goto dontconf;
+		if (!strcmp(name, "global")) goto dontconf;
+		if (!strcmp(name, "ignoreCase")) goto dontconf;
+		if (!strcmp(name, "multiline")) goto dontconf;
+		if (!strcmp(name, "lastIndex")) goto dontconf;
 	}
 
 	ref = jsV_getownproperty(J, obj, name);
 	if (ref) {
 		if (ref->atts & JS_DONTCONF)
-			return 0;
+			goto dontconf;
 		jsV_delproperty(J, obj, name);
 	}
 	return 1;
+
+dontconf:
+	if (J->strict)
+		js_typeerror(J, "'%s' is non-configurable", name);
+	return 0;
 }
 
 /* Registry, global and object property accessors */
@@ -798,6 +832,8 @@
 			}
 			if (!(ref->atts & JS_READONLY))
 				ref->value = *stackidx(J, -1);
+			else if (J->strict)
+				js_typeerror(J, "'%s' is read-only", name);
 			return;
 		}
 		E = E->outer;
@@ -813,8 +849,11 @@
 	do {
 		js_Property *ref = jsV_getownproperty(J, E->variables, name);
 		if (ref) {
-			if (ref->atts & JS_DONTCONF)
+			if (ref->atts & JS_DONTCONF) {
+				if (J->strict)
+					js_typeerror(J, "'%s' is non-configurable", name);
 				return 0;
+			}
 			jsV_delproperty(J, E->variables, name);
 			return 1;
 		}