Skip to content

Commit fcbf5ea

Browse files
author
Fabrice Bellard
committed
fixed BJSON array serialization (#457)
1 parent 4bd485d commit fcbf5ea

File tree

2 files changed

+67
-20
lines changed

2 files changed

+67
-20
lines changed

‎quickjs.c‎

Lines changed: 56 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -37258,14 +37258,17 @@ static int JS_WriteModule(BCWriterState *s, JSValueConst obj)
3725837258
return -1;
3725937259
}
3726037260

37261+
/* XXX: be compatible with the structured clone algorithm */
3726137262
static int JS_WriteArray(BCWriterState *s, JSValueConst obj)
3726237263
{
37264+
JSContext *ctx = s->ctx;
3726337265
JSObject *p = JS_VALUE_GET_OBJ(obj);
3726437266
uint32_t i, len;
37265-
JSValue val;
3726637267
int ret;
3726737268
BOOL is_template;
37268-
37269+
JSShapeProperty *prs;
37270+
JSProperty *pr;
37271+
3726937272
if (s->allow_bytecode && !p->extensible) {
3727037273
/* not extensible array: we consider it is a
3727137274
template when we are saving bytecode */
@@ -37275,29 +37278,62 @@ static int JS_WriteArray(BCWriterState *s, JSValueConst obj)
3727537278
bc_put_u8(s, BC_TAG_ARRAY);
3727637279
is_template = FALSE;
3727737280
}
37278-
if (js_get_length32(s->ctx, &len, obj))
37279-
goto fail1;
37281+
if (js_get_length32(ctx, &len, obj)) /* no side effect */
37282+
goto fail;
3728037283
bc_put_leb128(s, len);
37281-
for(i = 0; i < len; i++) {
37282-
val = JS_GetPropertyUint32(s->ctx, obj, i);
37283-
if (JS_IsException(val))
37284-
goto fail1;
37285-
ret = JS_WriteObjectRec(s, val);
37286-
JS_FreeValue(s->ctx, val);
37287-
if (ret)
37288-
goto fail1;
37284+
if (p->fast_array) {
37285+
for(i = 0; i < p->u.array.count; i++) {
37286+
ret = JS_WriteObjectRec(s, p->u.array.u.values[i]);
37287+
if (ret)
37288+
goto fail;
37289+
}
37290+
for(i = p->u.array.count; i < len; i++) {
37291+
ret = JS_WriteObjectRec(s, JS_UNDEFINED);
37292+
if (ret)
37293+
goto fail;
37294+
}
37295+
} else {
37296+
for(i = 0; i < len; i++) {
37297+
JSAtom atom;
37298+
atom = JS_NewAtomUInt32(ctx, i);
37299+
if (atom == JS_ATOM_NULL)
37300+
goto fail;
37301+
prs = find_own_property(&pr, p, atom);
37302+
JS_FreeAtom(ctx, atom);
37303+
if (prs && (prs->flags & JS_PROP_ENUMERABLE)) {
37304+
if (prs->flags & JS_PROP_TMASK) {
37305+
JS_ThrowTypeError(ctx, "only value properties are supported");
37306+
goto fail;
37307+
}
37308+
ret = JS_WriteObjectRec(s, pr->u.value);
37309+
if (ret)
37310+
goto fail;
37311+
} else {
37312+
ret = JS_WriteObjectRec(s, JS_UNDEFINED);
37313+
if (ret)
37314+
goto fail;
37315+
}
37316+
}
3728937317
}
3729037318
if (is_template) {
37291-
val = JS_GetProperty(s->ctx, obj, JS_ATOM_raw);
37292-
if (JS_IsException(val))
37293-
goto fail1;
37294-
ret = JS_WriteObjectRec(s, val);
37295-
JS_FreeValue(s->ctx, val);
37296-
if (ret)
37297-
goto fail1;
37319+
/* the 'raw' property is not enumerable */
37320+
prs = find_own_property(&pr, p, JS_ATOM_raw);
37321+
if (prs) {
37322+
if (prs->flags & JS_PROP_TMASK) {
37323+
JS_ThrowTypeError(ctx, "only value properties are supported");
37324+
goto fail;
37325+
}
37326+
ret = JS_WriteObjectRec(s, pr->u.value);
37327+
if (ret)
37328+
goto fail;
37329+
} else {
37330+
ret = JS_WriteObjectRec(s, JS_UNDEFINED);
37331+
if (ret)
37332+
goto fail;
37333+
}
3729837334
}
3729937335
return 0;
37300-
fail1:
37336+
fail:
3730137337
return -1;
3730237338
}
3730337339

‎tests/test_bjson.js‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,18 @@ function bjson_test_all()
184184
var obj;
185185

186186
bjson_test({x:1, y:2, if:3});
187+
187188
bjson_test([1, 2, 3]);
189+
190+
/* array with holes */
191+
bjson_test([1, , 2, , 3]);
192+
193+
/* fast array with hole */
194+
obj = new Array(5);
195+
obj[0] = 1;
196+
obj[1] = 2;
197+
bjson_test(obj);
198+
188199
bjson_test([1.0, "aa", true, false, undefined, null, NaN, -Infinity, -0.0]);
189200
if (typeof BigInt !== "undefined") {
190201
bjson_test([BigInt("1"), -BigInt("0x123456789"),

0 commit comments

Comments
 (0)