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;