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;
}