mirror of
https://github.com/ccxvii/mujs.git
synced 2026-09-24 17:43:36 +08:00
Allow holes at the end of a simple array.
Don't unflatten when creating with a = new Array(10). Don't unflatten when deleting the last element.
This commit is contained in:
@@ -318,7 +318,7 @@ static void Ap_sort(js_State *J)
|
||||
js_pushvalue(J, array[i].v);
|
||||
js_setindex(J, 0, i);
|
||||
}
|
||||
for (i = n; i < len; ++i) {
|
||||
for (i = len-i; i >= n; --i) {
|
||||
js_delindex(J, 0, i);
|
||||
}
|
||||
|
||||
@@ -351,7 +351,6 @@ static void Ap_splice(js_State *J)
|
||||
if (del < 0)
|
||||
del = 0;
|
||||
|
||||
|
||||
js_newarray(J);
|
||||
|
||||
/* copy deleted items to return array */
|
||||
|
||||
@@ -108,7 +108,7 @@ static void jsG_scanobject(js_State *J, int mark, js_Object *obj)
|
||||
jsG_markobject(J, mark, obj->prototype);
|
||||
if (obj->type == JS_CARRAY && obj->u.a.simple) {
|
||||
int i;
|
||||
for (i = 0; i < obj->u.a.length; ++i) {
|
||||
for (i = 0; i < obj->u.a.flat_length; ++i) {
|
||||
js_Value *v = &obj->u.a.array[i];
|
||||
if (v->type == JS_TMEMSTR && v->u.memstr->gcmark != mark)
|
||||
v->u.memstr->gcmark = mark;
|
||||
|
||||
+2
-2
@@ -73,7 +73,7 @@ static void Op_hasOwnProperty(js_State *J)
|
||||
}
|
||||
|
||||
if (self->type == JS_CARRAY && self->u.a.simple) {
|
||||
if (js_isarrayindex(J, name, &k) && k >= 0 && k < self->u.a.length) {
|
||||
if (js_isarrayindex(J, name, &k) && k >= 0 && k < self->u.a.flat_length) {
|
||||
js_pushboolean(J, 1);
|
||||
return;
|
||||
}
|
||||
@@ -189,7 +189,7 @@ static void O_getOwnPropertyNames(js_State *J)
|
||||
js_pushliteral(J, "length");
|
||||
js_setindex(J, -2, i++);
|
||||
if (obj->u.a.simple) {
|
||||
for (k = 0; k < obj->u.a.length; ++k) {
|
||||
for (k = 0; k < obj->u.a.flat_length; ++k) {
|
||||
js_itoa(name, k);
|
||||
js_pushstring(J, name);
|
||||
js_setindex(J, -2, i++);
|
||||
|
||||
+1
-1
@@ -293,7 +293,7 @@ js_Object *jsV_newiterator(js_State *J, js_Object *obj, int own)
|
||||
io->u.iter.n = obj->u.s.length;
|
||||
|
||||
if (obj->type == JS_CARRAY && obj->u.a.simple)
|
||||
io->u.iter.n = obj->u.a.length;
|
||||
io->u.iter.n = obj->u.a.flat_length;
|
||||
|
||||
return io;
|
||||
}
|
||||
|
||||
@@ -528,14 +528,15 @@ void jsR_unflattenarray(js_State *J, js_Object *obj) {
|
||||
obj->properties = NULL;
|
||||
js_throw(J);
|
||||
}
|
||||
for (i = 0; i < obj->u.a.length; ++i) {
|
||||
for (i = 0; i < obj->u.a.flat_length; ++i) {
|
||||
js_itoa(name, i);
|
||||
ref = jsV_setproperty(J, obj, name);
|
||||
ref->value = obj->u.a.array[i];
|
||||
}
|
||||
js_free(J, obj->u.a.array);
|
||||
obj->u.a.simple = 0;
|
||||
obj->u.a.capacity = 0;
|
||||
obj->u.a.flat_length = 0;
|
||||
obj->u.a.flat_capacity = 0;
|
||||
obj->u.a.array = NULL;
|
||||
js_endtry(J);
|
||||
}
|
||||
@@ -553,10 +554,11 @@ static int jsR_hasproperty(js_State *J, js_Object *obj, const char *name)
|
||||
}
|
||||
if (obj->u.a.simple) {
|
||||
if (js_isarrayindex(J, name, &k)) {
|
||||
if (k >= 0 && k < obj->u.a.length) {
|
||||
if (k >= 0 && k < obj->u.a.flat_length) {
|
||||
js_pushvalue(J, obj->u.a.array[k]);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -626,9 +628,12 @@ static void jsR_getproperty(js_State *J, js_Object *obj, const char *name)
|
||||
static int jsR_hasindex(js_State *J, js_Object *obj, int k)
|
||||
{
|
||||
char buf[32];
|
||||
if (obj->type == JS_CARRAY && obj->u.a.simple && k >= 0 && k < obj->u.a.length) {
|
||||
js_pushvalue(J, obj->u.a.array[k]);
|
||||
return 1;
|
||||
if (obj->type == JS_CARRAY && obj->u.a.simple) {
|
||||
if (k >= 0 && k < obj->u.a.flat_length) {
|
||||
js_pushvalue(J, obj->u.a.array[k]);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return jsR_hasproperty(J, obj, js_itoa(buf, k));
|
||||
}
|
||||
@@ -646,19 +651,21 @@ static void jsR_setarrayindex(js_State *J, js_Object *obj, int k, js_Value *valu
|
||||
assert(k >= 0);
|
||||
if (newlen > JS_ARRAYLIMIT)
|
||||
js_rangeerror(J, "array too large");
|
||||
if (newlen > obj->u.a.length) {
|
||||
assert(newlen == obj->u.a.length + 1);
|
||||
if (newlen > obj->u.a.capacity) {
|
||||
int newcap = obj->u.a.capacity;
|
||||
if (newlen > obj->u.a.flat_length) {
|
||||
assert(newlen == obj->u.a.flat_length + 1);
|
||||
if (newlen > obj->u.a.flat_capacity) {
|
||||
int newcap = obj->u.a.flat_capacity;
|
||||
if (newcap == 0)
|
||||
newcap = 8;
|
||||
while (newcap < newlen)
|
||||
newcap <<= 1;
|
||||
obj->u.a.array = js_realloc(J, obj->u.a.array, newcap * sizeof(js_Value));
|
||||
obj->u.a.capacity = newcap;
|
||||
obj->u.a.flat_capacity = newcap;
|
||||
}
|
||||
obj->u.a.length = newlen;
|
||||
obj->u.a.flat_length = newlen;
|
||||
}
|
||||
if (newlen > obj->u.a.length)
|
||||
obj->u.a.length = newlen;
|
||||
obj->u.a.array[k] = *value;
|
||||
}
|
||||
|
||||
@@ -678,26 +685,28 @@ static void jsR_setproperty(js_State *J, js_Object *obj, const char *name, int t
|
||||
if (newlen > JS_ARRAYLIMIT)
|
||||
js_rangeerror(J, "array too large");
|
||||
if (obj->u.a.simple) {
|
||||
if (newlen <= obj->u.a.length) {
|
||||
obj->u.a.length = newlen;
|
||||
return;
|
||||
}
|
||||
jsR_unflattenarray(J, obj);
|
||||
obj->u.a.length = newlen;
|
||||
if (newlen <= obj->u.a.flat_length)
|
||||
obj->u.a.flat_length = newlen;
|
||||
} else {
|
||||
jsV_resizearray(J, obj, newlen);
|
||||
}
|
||||
jsV_resizearray(J, obj, newlen);
|
||||
return;
|
||||
}
|
||||
|
||||
if (js_isarrayindex(J, name, &k)) {
|
||||
if (obj->u.a.simple) {
|
||||
if (k >= 0 && k <= obj->u.a.length) {
|
||||
if (k >= 0 && k <= obj->u.a.flat_length) {
|
||||
jsR_setarrayindex(J, obj, k, value);
|
||||
return;
|
||||
} else {
|
||||
jsR_unflattenarray(J, obj);
|
||||
if (obj->u.a.length < k + 1)
|
||||
obj->u.a.length = k + 1;
|
||||
}
|
||||
jsR_unflattenarray(J, obj);
|
||||
} else {
|
||||
if (obj->u.a.length < k + 1)
|
||||
obj->u.a.length = k + 1;
|
||||
}
|
||||
if (k + 1 > obj->u.a.length)
|
||||
obj->u.a.length = k + 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -771,7 +780,7 @@ readonly:
|
||||
static void jsR_setindex(js_State *J, js_Object *obj, int k, int transient)
|
||||
{
|
||||
char buf[32];
|
||||
if (obj->type == JS_CARRAY && obj->u.a.simple && k >= 0 && k <= obj->u.a.length) {
|
||||
if (obj->type == JS_CARRAY && obj->u.a.simple && k >= 0 && k <= obj->u.a.flat_length) {
|
||||
jsR_setarrayindex(J, obj, k, stackidx(J, -1));
|
||||
} else {
|
||||
jsR_setproperty(J, obj, js_itoa(buf, k), transient);
|
||||
@@ -890,6 +899,16 @@ dontconf:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void jsR_delindex(js_State *J, js_Object *obj, int k)
|
||||
{
|
||||
char buf[32];
|
||||
/* Allow deleting last element of a simple array without unflattening */
|
||||
if (obj->type == JS_CARRAY && obj->u.a.simple && k == obj->u.a.flat_length - 1)
|
||||
obj->u.a.flat_length = k;
|
||||
else
|
||||
jsR_delproperty(J, obj, js_itoa(buf, k));
|
||||
}
|
||||
|
||||
/* Registry, global and object property accessors */
|
||||
|
||||
const char *js_ref(js_State *J)
|
||||
@@ -1010,8 +1029,7 @@ void js_setindex(js_State *J, int idx, int i)
|
||||
|
||||
void js_delindex(js_State *J, int idx, int i)
|
||||
{
|
||||
char buf[32];
|
||||
js_delproperty(J, idx, js_itoa(buf, i));
|
||||
jsR_delindex(J, js_toobject(J, idx), i);
|
||||
}
|
||||
|
||||
/* Iterator */
|
||||
|
||||
@@ -93,9 +93,10 @@ struct js_Object
|
||||
char shrstr[16];
|
||||
} s;
|
||||
struct {
|
||||
int length;
|
||||
int length; /* actual length */
|
||||
int simple; /* true if array has only non-sparse array properties */
|
||||
int capacity;
|
||||
int flat_length; /* used length of simple array part */
|
||||
int flat_capacity; /* allocated length of simple array part */
|
||||
js_Value *array;
|
||||
} a;
|
||||
struct {
|
||||
|
||||
Reference in New Issue
Block a user