shithub: libmujs

Download patch

ref: 44c0e12d62ee9adcc37d7ff603232c29b9d90101
parent: 63a542aa08477b30e3ce3f7dcceb347396ee4844
author: Tor Andersson <tor.andersson@artifex.com>
date: Wed Jan 7 17:37:34 EST 2015

strict mode: Check duplicate property names.

Also simplify object initialiser opcode set.

--- a/jscompile.c
+++ b/jscompile.c
@@ -1,6 +1,7 @@
 #include "jsi.h"
 #include "jsparse.h"
 #include "jscompile.h"
+#include "jsvalue.h" /* for jsV_numbertostring */
 
 #define cexp jsC_cexp /* collision with math.h */
 
@@ -253,8 +254,8 @@
 	while (list) {
 		if (list->a->type != EXP_UNDEF) {
 			cexp(J, F, list->a);
-			emit(J, F, OP_INITPROP_N);
-			emitraw(J, F, i++);
+			emitnumber(J, F, i++);
+			emit(J, F, OP_INITPROP);
 		} else {
 			++i;
 		}
@@ -262,39 +263,63 @@
 	}
 }
 
+static void checkdup(JF, js_Ast *list, js_Ast *end)
+{
+	char nbuf[32], sbuf[32];
+	const char *needle, *straw;
+
+	if (end->a->type == EXP_NUMBER)
+		needle = jsV_numbertostring(J, nbuf, end->a->number);
+	else
+		needle = end->a->string;
+
+	while (list->a != end) {
+		if (list->a->type == end->type) {
+			js_Ast *prop = list->a->a;
+			if (prop->type == EXP_NUMBER)
+				straw = jsV_numbertostring(J, sbuf, prop->number);
+			else
+				straw =  prop->string;
+			if (!strcmp(needle, straw))
+				jsC_error(J, list, "duplicate property '%s' in object literal", needle);
+		}
+		list = list->b;
+	}
+}
+
 static void cobject(JF, js_Ast *list)
 {
+	js_Ast *head = list;
+
 	while (list) {
 		js_Ast *kv = list->a;
 		js_Ast *prop = kv->a;
-		if (kv->type == EXP_PROP_VAL) {
-			if (prop->type == AST_IDENTIFIER || prop->type == EXP_STRING) {
-				cexp(J, F, kv->b);
-				emitstring(J, F, OP_INITPROP_S, prop->string);
-			} else if (prop->type == EXP_NUMBER) {
-				if (prop->number == (js_Instruction)prop->number) {
-					cexp(J, F, kv->b);
-					emit(J, F, OP_INITPROP_N);
-					emitraw(J, F, (js_Instruction)prop->number);
-				} else {
-					emitnumber(J, F, prop->number);
-					cexp(J, F, kv->b);
-					emit(J, F, OP_INITPROP);
-				}
-			} else {
-				jsC_error(J, list, "illegal property name in object initializer");
-			}
-		} else {
-			if (prop->type == AST_IDENTIFIER || prop->type == EXP_STRING)
-				emitstring(J, F, OP_STRING, prop->string);
-			if (prop->type == EXP_NUMBER)
-				emitnumber(J, F, prop->number);
+
+		if (prop->type == AST_IDENTIFIER || prop->type == EXP_STRING)
+			emitstring(J, F, OP_STRING, prop->string);
+		else if (prop->type == EXP_NUMBER)
+			emitnumber(J, F, prop->number);
+		else
+			jsC_error(J, prop, "illegal property name in object initializer");
+
+		if (J->strict)
+			checkdup(J, F, head, kv);
+
+		switch (kv->type) {
+		case EXP_PROP_VAL:
+			cexp(J, F, kv->b);
+			emit(J, F, OP_INITPROP);
+			break;
+		case EXP_PROP_GET:
 			emitfunction(J, F, newfun(J, NULL, kv->b, kv->c, 0));
-			if (kv->type == EXP_PROP_GET)
-				emit(J, F, OP_INITGETTER);
-			if (kv->type == EXP_PROP_SET)
-				emit(J, F, OP_INITSETTER);
+			emit(J, F, OP_INITGETTER);
+			break;
+		case EXP_PROP_SET:
+			emitfunction(J, F, newfun(J, NULL, kv->b, kv->c, 0));
+			emit(J, F, OP_INITSETTER);
+			break;
 		}
+
 		list = list->b;
 	}
 }
--- a/jscompile.h
+++ b/jscompile.h
@@ -47,9 +47,6 @@
 	OP_IN,		/* <name> <obj> -- <exists?> */
 
 	OP_INITPROP,	/* <obj> <key> <val> -- <obj> */
-	OP_INITPROP_N,	/* <obj> <val> -- <obj> */
-	OP_INITPROP_S,	/* <obj> <val> -- <obj> */
-
 	OP_INITGETTER,	/* <obj> <key> <closure> -- <obj> */
 	OP_INITSETTER,	/* <obj> <key> <closure> -- <obj> */
 
--- a/jsdump.c
+++ b/jsdump.c
@@ -753,7 +753,6 @@
 		case OP_GETPROP_S:
 		case OP_SETPROP_S:
 		case OP_DELPROP_S:
-		case OP_INITPROP_S:
 		case OP_CATCH:
 			pc(' ');
 			ps(F->strtab[*p++]);
@@ -767,7 +766,6 @@
 		case OP_DELLOCAL:
 		case OP_NUMBER_POS:
 		case OP_NUMBER_NEG:
-		case OP_INITPROP_N:
 		case OP_CALL:
 		case OP_NEW:
 		case OP_JUMP:
--- a/jsrun.c
+++ b/jsrun.c
@@ -1188,7 +1188,6 @@
 	int offset;
 
 	const char *str;
-	char buf[32];
 	js_Object *obj;
 	double x, y;
 	unsigned int ux, uy;
@@ -1287,6 +1286,13 @@
 			js_pushboolean(J, b);
 			break;
 
+		case OP_INITPROP:
+			obj = js_toobject(J, -3);
+			str = js_tostring(J, -2);
+			jsR_setproperty(J, obj, str, stackidx(J, -1));
+			js_pop(J, 2);
+			break;
+
 		case OP_INITGETTER:
 			obj = js_toobject(J, -3);
 			str = js_tostring(J, -2);
@@ -1299,27 +1305,6 @@
 			str = js_tostring(J, -2);
 			jsR_defproperty(J, obj, str, 0, NULL, NULL, jsR_tofunction(J, -1));
 			js_pop(J, 2);
-			break;
-
-		case OP_INITPROP:
-			str = js_tostring(J, -2);
-			obj = js_toobject(J, -3);
-			jsR_setproperty(J, obj, str, stackidx(J, -1));
-			js_pop(J, 2);
-			break;
-
-		case OP_INITPROP_S:
-			str = ST[*pc++];
-			obj = js_toobject(J, -2);
-			jsR_setproperty(J, obj, str, stackidx(J, -1));
-			js_pop(J, 1);
-			break;
-
-		case OP_INITPROP_N:
-			str = jsV_numbertostring(J, buf, *pc++);
-			obj = js_toobject(J, -2);
-			jsR_setproperty(J, obj, str, stackidx(J, -1));
-			js_pop(J, 1);
 			break;
 
 		case OP_GETPROP:
--- a/opnames.h
+++ b/opnames.h
@@ -33,8 +33,6 @@
 "delvar",
 "in",
 "initprop",
-"initprop_n",
-"initprop_s",
 "initgetter",
 "initsetter",
 "getprop",