shithub: libmujs

Download patch

ref: 546ee1e6c2a129369a098e13d4a841101397876d
parent: 7a45bb4363e8afa095ca18346c1b8a70f1269491
author: Tor Andersson <tor@ccxvii.net>
date: Thu Jan 23 19:40:19 EST 2014

Fix switch test-chain stack leftovers. Fix iterator on null and undefined.

--- a/jscompile.c
+++ b/jscompile.c
@@ -756,12 +756,11 @@
 				jsC_error(J, clause, "more than one default label in switch");
 			def = clause;
 		} else {
-			emit(J, F, OP_DUP);
 			cexp(J, F, clause->a);
-			emit(J, F, OP_STRICTEQ);
-			clause->casejump = jump(J, F, OP_JTRUE);
+			clause->casejump = jump(J, F, OP_JCASE);
 		}
 	}
+	emit(J, F, OP_POP);
 	if (def)
 		def->casejump = jump(J, F, OP_JUMP);
 	else
@@ -809,7 +808,7 @@
 		cstmlist(J, F, stm->a);
 		break;
 
-	case STM_NOP:
+	case STM_EMPTY:
 		break;
 
 	case STM_VAR:
--- a/jscompile.h
+++ b/jscompile.h
@@ -78,6 +78,7 @@
 	OP_NE,
 	OP_STRICTEQ,
 	OP_STRICTNE,
+	OP_JCASE,
 	OP_BITAND,
 	OP_BITXOR,
 	OP_BITOR,
--- a/jsdump.c
+++ b/jsdump.c
@@ -381,7 +381,7 @@
 		in(d); ps("}");
 		break;
 
-	case STM_NOP:
+	case STM_EMPTY:
 		pc(';');
 		break;
 
@@ -662,6 +662,7 @@
 		case OP_JUMP:
 		case OP_JTRUE:
 		case OP_JFALSE:
+		case OP_JCASE:
 		case OP_TRY:
 			printf(" %d", *p++);
 			break;
--- a/jsparse.c
+++ b/jsparse.c
@@ -721,7 +721,7 @@
 
 	/* empty statement */
 	if (accept(J, ';')) {
-		return STM0(NOP);
+		return STM0(EMPTY);
 	}
 
 	if (accept(J, TK_IF)) {
--- a/jsparse.h
+++ b/jsparse.h
@@ -91,7 +91,7 @@
 
 	/* statements */
 	STM_BLOCK,
-	STM_NOP,
+	STM_EMPTY,
 	STM_VAR,
 	STM_IF,
 	STM_DO,
--- a/jsrun.c
+++ b/jsrun.c
@@ -96,6 +96,14 @@
 	return 0;
 }
 
+int js_isiterator(js_State *J, int idx)
+{
+	const js_Value *v = stackidx(J, idx);
+	if (v->type == JS_TOBJECT)
+		return v->u.object->type == JS_CITERATOR;
+	return 0;
+}
+
 static const char *js_typeof(js_State *J, int idx)
 {
 	switch (stackidx(J, idx)->type) {
@@ -662,17 +670,24 @@
 		// OP_DELPROPS
 
 		case OP_ITERATOR:
-			obj = jsV_newiterator(J, js_toobject(J, -1));
-			js_pop(J, 1);
-			js_pushobject(J, obj);
+			if (!js_isundefined(J, -1) && !js_isnull(J, -1)) {
+				obj = jsV_newiterator(J, js_toobject(J, -1));
+				js_pop(J, 1);
+				js_pushobject(J, obj);
+			}
 			break;
 
 		case OP_NEXTITER:
-			obj = js_toobject(J, -1);
-			str = jsV_nextiterator(J, obj);
-			if (str) {
-				js_pushliteral(J, str);
-				js_pushboolean(J, 1);
+			if (js_isiterator(J, -1)) {
+				obj = js_toobject(J, -1);
+				str = jsV_nextiterator(J, obj);
+				if (str) {
+					js_pushliteral(J, str);
+					js_pushboolean(J, 1);
+				} else {
+					js_pop(J, 1);
+					js_pushboolean(J, 0);
+				}
 			} else {
 				js_pop(J, 1);
 				js_pushboolean(J, 0);
@@ -782,10 +797,10 @@
 
 		/* Relational operators */
 
-		case OP_LT: b = js_compare(J); js_pushboolean(J, b < 0); break;
-		case OP_GT: b = js_compare(J); js_pushboolean(J, b > 0); break;
-		case OP_LE: b = js_compare(J); js_pushboolean(J, b <= 0); break;
-		case OP_GE: b = js_compare(J); js_pushboolean(J, b >= 0); break;
+		case OP_LT: b = js_compare(J); js_pop(J, 2); js_pushboolean(J, b < 0); break;
+		case OP_GT: b = js_compare(J); js_pop(J, 2); js_pushboolean(J, b > 0); break;
+		case OP_LE: b = js_compare(J); js_pop(J, 2); js_pushboolean(J, b <= 0); break;
+		case OP_GE: b = js_compare(J); js_pop(J, 2); js_pushboolean(J, b >= 0); break;
 
 		case OP_INSTANCEOF:
 			b = js_instanceof(J);
@@ -795,10 +810,21 @@
 
 		/* Equality */
 
-		case OP_EQ: b = js_equal(J); js_pushboolean(J, b); break;
-		case OP_NE: b = js_equal(J); js_pushboolean(J, !b); break;
-		case OP_STRICTEQ: b = js_strictequal(J); js_pushboolean(J, b); break;
-		case OP_STRICTNE: b = js_strictequal(J); js_pushboolean(J, !b); break;
+		case OP_EQ: b = js_equal(J); js_pop(J, 2); js_pushboolean(J, b); break;
+		case OP_NE: b = js_equal(J); js_pop(J, 2); js_pushboolean(J, !b); break;
+		case OP_STRICTEQ: b = js_strictequal(J); js_pop(J, 2); js_pushboolean(J, b); break;
+		case OP_STRICTNE: b = js_strictequal(J); js_pop(J, 2); js_pushboolean(J, !b); break;
+
+		case OP_JCASE:
+			offset = *pc++;
+			b = js_strictequal(J);
+			if (b) {
+				js_pop(J, 2);
+				pc = pcstart + offset;
+			} else {
+				js_pop(J, 1);
+			}
+			break;
 
 		/* Binary bitwise operators */
 
--- a/jsvalue.c
+++ b/jsvalue.c
@@ -347,7 +347,7 @@
 {
 	js_Value va = js_toprimitive(J, -2, JS_HNUMBER);
 	js_Value vb = js_toprimitive(J, -1, JS_HNUMBER);
-	js_pop(J, 2);
+
 	if (va.type == JS_TSTRING && vb.type == JS_TSTRING) {
 		return strcmp(va.u.string, vb.u.string);
 	} else {
@@ -361,7 +361,6 @@
 {
 	js_Value va = js_tovalue(J, -2);
 	js_Value vb = js_tovalue(J, -1);
-	js_pop(J, 2);
 
 retry:
 	if (va.type == vb.type) {
@@ -398,7 +397,6 @@
 {
 	js_Value va = js_tovalue(J, -2);
 	js_Value vb = js_tovalue(J, -1);
-	js_pop(J, 2);
 
 	if (va.type != vb.type) return 0;
 	if (va.type == JS_TUNDEFINED) return 1;