shithub: libmujs

Download patch

ref: bd9920c5714bcfe51f3514d5df7b7b963d846058
parent: 7be32a0f5f3a4824593a56facb3c24c7f55ff4e3
author: Tor Andersson <tor.andersson@artifex.com>
date: Mon Jan 7 08:21:36 EST 2019

Handle null/undefined in OP_NEXTITER rather than creating empty iterator.

Only create an iterator for coercible types in OP_ITERATOR, and then
detect the lack of a real iterator in OP_NEXTITER.
Thus we don't need to allocate and push an empty iterator object for
these cases.

--- a/jsproperty.c
+++ b/jsproperty.c
@@ -252,14 +252,6 @@
 	return iter;
 }
 
-js_Object *jsV_emptyiterator(js_State *J)
-{
-	js_Object *io = jsV_newobject(J, JS_CITERATOR, NULL);
-	io->u.iter.target = NULL;
-	io->u.iter.head = NULL;
-	return io;
-}
-
 js_Object *jsV_newiterator(js_State *J, js_Object *obj, int own)
 {
 	char buf[32];
--- a/jsrun.c
+++ b/jsrun.c
@@ -1469,20 +1469,24 @@
 			break;
 
 		case OP_ITERATOR:
-			if (js_isundefined(J, -1) || js_isnull(J, -1))
-				obj = jsV_emptyiterator(J);
-			else
+			if (js_iscoercible(J, -1)) {
 				obj = jsV_newiterator(J, js_toobject(J, -1), 0);
-			js_pop(J, 1);
-			js_pushobject(J, obj);
+				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_isobject(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);
--- a/jsvalue.h
+++ b/jsvalue.h
@@ -173,7 +173,6 @@
 js_Property *jsV_nextproperty(js_State *J, js_Object *obj, const char *name);
 void jsV_delproperty(js_State *J, js_Object *obj, const char *name);
 
-js_Object *jsV_emptyiterator(js_State *J);
 js_Object *jsV_newiterator(js_State *J, js_Object *obj, int own);
 const char *jsV_nextiterator(js_State *J, js_Object *iter);