shithub: libmujs

Download patch

ref: 8b5ba209570d6d5e102a931945bd301164e1f9e6
parent: d592c785c0b2f9fea982ac3fe7b88fdd7c4817fc
author: Tor Andersson <tor.andersson@artifex.com>
date: Thu Oct 20 08:59:49 EDT 2022

Issue #166: Use special iterator for string and array indices.

Add a scratch buffer to js_State to hold temporary strings.

--- a/jsi.h
+++ b/jsi.h
@@ -244,6 +244,8 @@
 
 	unsigned int seed; /* Math.random seed */
 
+	char scratch[12]; /* scratch buffer for iterating over array indices */
+
 	int nextref; /* for js_ref use */
 	js_Object *R; /* registry of hidden values */
 	js_Object *G; /* the global object */
--- a/jsproperty.c
+++ b/jsproperty.c
@@ -229,20 +229,12 @@
 /* Flatten hierarchy of enumerable properties into an iterator object */
 
 static js_Iterator *itnewnode(js_State *J, const char *name, js_Iterator *next) {
-	js_Iterator *node = js_malloc(J, offsetof(js_Iterator, buf));
+	js_Iterator *node = js_malloc(J, sizeof(js_Iterator));
 	node->name = name;
 	node->next = next;
 	return node;
 }
 
-static js_Iterator *itnewnodeix(js_State *J, int ix) {
-	js_Iterator *node = js_malloc(J, sizeof(js_Iterator));
-	js_itoa(node->buf, ix);
-	node->name = node->buf;
-	node->next = NULL;
-	return node;
-}
-
 static js_Iterator *itwalk(js_State *J, js_Iterator *iter, js_Property *prop, js_Object *seen)
 {
 	if (prop->right != &sentinel)
@@ -269,10 +261,10 @@
 
 js_Object *jsV_newiterator(js_State *J, js_Object *obj, int own)
 {
-	char buf[32];
-	int k;
 	js_Object *io = jsV_newobject(J, JS_CITERATOR, NULL);
 	io->u.iter.target = obj;
+	io->u.iter.i = 0;
+	io->u.iter.n = 0;
 	if (own) {
 		io->u.iter.head = NULL;
 		if (obj->properties != &sentinel)
@@ -281,40 +273,11 @@
 		io->u.iter.head = itflatten(J, obj);
 	}
 
-	if (obj->type == JS_CSTRING) {
-		js_Iterator *tail = io->u.iter.head;
-		if (tail)
-			while (tail->next)
-				tail = tail->next;
-		for (k = 0; k < obj->u.s.length; ++k) {
-			js_itoa(buf, k);
-			if (!jsV_getenumproperty(J, obj, buf)) {
-				js_Iterator *node = itnewnodeix(J, k);
-				if (!tail)
-					io->u.iter.head = tail = node;
-				else {
-					tail->next = node;
-					tail = node;
-				}
-			}
-		}
-	}
+	if (obj->type == JS_CSTRING)
+		io->u.iter.n = obj->u.s.length;
 
-	if (obj->type == JS_CARRAY && obj->u.a.simple) {
-		js_Iterator *tail = io->u.iter.head;
-		if (tail)
-			while (tail->next)
-				tail = tail->next;
-		for (k = 0; k < obj->u.a.length; ++k) {
-			js_Iterator *node = itnewnodeix(J, k);
-			if (!tail)
-				io->u.iter.head = tail = node;
-			else {
-				tail->next = node;
-				tail = node;
-			}
-		}
-	}
+	if (obj->type == JS_CARRAY && obj->u.a.simple)
+		io->u.iter.n = obj->u.a.length;
 
 	return io;
 }
@@ -324,6 +287,11 @@
 	int k;
 	if (io->type != JS_CITERATOR)
 		js_typeerror(J, "not an iterator");
+	if (io->u.iter.i < io->u.iter.n) {
+		js_itoa(J->scratch, io->u.iter.i);
+		io->u.iter.i++;
+		return J->scratch;
+	}
 	while (io->u.iter.head) {
 		js_Iterator *next = io->u.iter.head->next;
 		const char *name = io->u.iter.head->name;
--- a/jsvalue.h
+++ b/jsvalue.h
@@ -93,7 +93,7 @@
 		} s;
 		struct {
 			int length;
-			int simple; // true if array has only non-sparse array properties
+			int simple; /* true if array has only non-sparse array properties */
 			int capacity;
 			js_Value *array;
 		} a;
@@ -112,7 +112,8 @@
 		js_Regexp r;
 		struct {
 			js_Object *target;
-			js_Iterator *head;
+			int i, n; /* for array part */
+			js_Iterator *head; /* for object part */
 		} iter;
 		struct {
 			const char *tag;
@@ -143,7 +144,6 @@
 {
 	const char *name;
 	js_Iterator *next;
-	char buf[12]; /* for integer iterators */
 };
 
 /* jsrun.c */