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",