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 */