mirror of
https://github.com/DoneJS-Runtime/quickjs-done-nextgen.git
synced 2025-01-09 17:43:15 +00:00
Support (de)serializing Map and Set objects (#483)
Fixes: https://github.com/quickjs-ng/quickjs/issues/482
This commit is contained in:
parent
5db156fb08
commit
3a58376485
7 changed files with 140 additions and 1 deletions
Binary file not shown.
BIN
gen/hello.c
BIN
gen/hello.c
Binary file not shown.
Binary file not shown.
BIN
gen/repl.c
BIN
gen/repl.c
Binary file not shown.
BIN
gen/test_fib.c
BIN
gen/test_fib.c
Binary file not shown.
117
quickjs.c
117
quickjs.c
|
@ -33114,9 +33114,11 @@ typedef enum BCTagEnum {
|
||||||
BC_TAG_DATE,
|
BC_TAG_DATE,
|
||||||
BC_TAG_OBJECT_VALUE,
|
BC_TAG_OBJECT_VALUE,
|
||||||
BC_TAG_OBJECT_REFERENCE,
|
BC_TAG_OBJECT_REFERENCE,
|
||||||
|
BC_TAG_MAP,
|
||||||
|
BC_TAG_SET,
|
||||||
} BCTagEnum;
|
} BCTagEnum;
|
||||||
|
|
||||||
#define BC_VERSION 12
|
#define BC_VERSION 13
|
||||||
|
|
||||||
typedef struct BCWriterState {
|
typedef struct BCWriterState {
|
||||||
JSContext *ctx;
|
JSContext *ctx;
|
||||||
|
@ -33757,6 +33759,9 @@ static int JS_WriteRegExp(BCWriterState *s, JSRegExp regexp)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int JS_WriteMap(BCWriterState *s, struct JSMapState *map_state);
|
||||||
|
static int JS_WriteSet(BCWriterState *s, struct JSMapState *map_state);
|
||||||
|
|
||||||
static int JS_WriteObjectRec(BCWriterState *s, JSValue obj)
|
static int JS_WriteObjectRec(BCWriterState *s, JSValue obj)
|
||||||
{
|
{
|
||||||
uint32_t tag;
|
uint32_t tag;
|
||||||
|
@ -33860,6 +33865,14 @@ static int JS_WriteObjectRec(BCWriterState *s, JSValue obj)
|
||||||
bc_put_u8(s, BC_TAG_OBJECT_VALUE);
|
bc_put_u8(s, BC_TAG_OBJECT_VALUE);
|
||||||
ret = JS_WriteObjectRec(s, p->u.object_data);
|
ret = JS_WriteObjectRec(s, p->u.object_data);
|
||||||
break;
|
break;
|
||||||
|
case JS_CLASS_MAP:
|
||||||
|
bc_put_u8(s, BC_TAG_MAP);
|
||||||
|
ret = JS_WriteMap(s, p->u.map_state);
|
||||||
|
break;
|
||||||
|
case JS_CLASS_SET:
|
||||||
|
bc_put_u8(s, BC_TAG_SET);
|
||||||
|
ret = JS_WriteSet(s, p->u.map_state);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
if (p->class_id >= JS_CLASS_UINT8C_ARRAY &&
|
if (p->class_id >= JS_CLASS_UINT8C_ARRAY &&
|
||||||
p->class_id <= JS_CLASS_FLOAT64_ARRAY) {
|
p->class_id <= JS_CLASS_FLOAT64_ARRAY) {
|
||||||
|
@ -34996,6 +35009,9 @@ static JSValue JS_ReadObjectValue(BCReaderState *s)
|
||||||
return JS_EXCEPTION;
|
return JS_EXCEPTION;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static JSValue JS_ReadMap(BCReaderState *s);
|
||||||
|
static JSValue JS_ReadSet(BCReaderState *s);
|
||||||
|
|
||||||
static JSValue JS_ReadObjectRec(BCReaderState *s)
|
static JSValue JS_ReadObjectRec(BCReaderState *s)
|
||||||
{
|
{
|
||||||
JSContext *ctx = s->ctx;
|
JSContext *ctx = s->ctx;
|
||||||
|
@ -35103,6 +35119,12 @@ static JSValue JS_ReadObjectRec(BCReaderState *s)
|
||||||
obj = js_dup(JS_MKPTR(JS_TAG_OBJECT, s->objects[val]));
|
obj = js_dup(JS_MKPTR(JS_TAG_OBJECT, s->objects[val]));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case BC_TAG_MAP:
|
||||||
|
obj = JS_ReadMap(s);
|
||||||
|
break;
|
||||||
|
case BC_TAG_SET:
|
||||||
|
obj = JS_ReadSet(s);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
invalid_tag:
|
invalid_tag:
|
||||||
return JS_ThrowSyntaxError(ctx, "invalid tag (tag=%d pos=%u)",
|
return JS_ThrowSyntaxError(ctx, "invalid tag (tag=%d pos=%u)",
|
||||||
|
@ -46026,6 +46048,99 @@ static JSValue js_map_iterator_next(JSContext *ctx, JSValue this_val,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static JSValue js_map_read(BCReaderState *s, int magic)
|
||||||
|
{
|
||||||
|
JSContext *ctx = s->ctx;
|
||||||
|
JSValue obj, rv, argv[2];
|
||||||
|
uint32_t i, prop_count;
|
||||||
|
|
||||||
|
argv[0] = JS_UNDEFINED;
|
||||||
|
argv[1] = JS_UNDEFINED;
|
||||||
|
obj = js_map_constructor(ctx, JS_UNDEFINED, 0, NULL, magic);
|
||||||
|
if (JS_IsException(obj))
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
if (BC_add_object_ref(s, obj))
|
||||||
|
goto fail;
|
||||||
|
if (bc_get_leb128(s, &prop_count))
|
||||||
|
goto fail;
|
||||||
|
for(i = 0; i < prop_count; i++) {
|
||||||
|
argv[0] = JS_ReadObjectRec(s);
|
||||||
|
if (JS_IsException(argv[0]))
|
||||||
|
goto fail;
|
||||||
|
if (!(magic & MAGIC_SET)) {
|
||||||
|
argv[1] = JS_ReadObjectRec(s);
|
||||||
|
if (JS_IsException(argv[1]))
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
rv = js_map_set(ctx, obj, countof(argv), argv, magic);
|
||||||
|
if (JS_IsException(rv))
|
||||||
|
goto fail;
|
||||||
|
JS_FreeValue(ctx, rv);
|
||||||
|
JS_FreeValue(ctx, argv[0]);
|
||||||
|
JS_FreeValue(ctx, argv[1]);
|
||||||
|
argv[0] = JS_UNDEFINED;
|
||||||
|
argv[1] = JS_UNDEFINED;
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
fail:
|
||||||
|
JS_FreeValue(ctx, obj);
|
||||||
|
JS_FreeValue(ctx, argv[0]);
|
||||||
|
JS_FreeValue(ctx, argv[1]);
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int js_map_write(BCWriterState *s, struct JSMapState *map_state,
|
||||||
|
int magic)
|
||||||
|
{
|
||||||
|
struct list_head *el;
|
||||||
|
JSMapRecord *mr;
|
||||||
|
uint32_t count;
|
||||||
|
|
||||||
|
count = 0;
|
||||||
|
|
||||||
|
if (map_state) {
|
||||||
|
list_for_each(el, &map_state->records) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bc_put_leb128(s, count);
|
||||||
|
|
||||||
|
if (map_state) {
|
||||||
|
list_for_each(el, &map_state->records) {
|
||||||
|
mr = list_entry(el, JSMapRecord, link);
|
||||||
|
if (JS_WriteObjectRec(s, mr->key))
|
||||||
|
return -1;
|
||||||
|
// mr->value is always JS_UNDEFINED for sets
|
||||||
|
if (!(magic & MAGIC_SET))
|
||||||
|
if (JS_WriteObjectRec(s, mr->value))
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue JS_ReadMap(BCReaderState *s)
|
||||||
|
{
|
||||||
|
return js_map_read(s, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue JS_ReadSet(BCReaderState *s)
|
||||||
|
{
|
||||||
|
return js_map_read(s, MAGIC_SET);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int JS_WriteMap(BCWriterState *s, struct JSMapState *map_state)
|
||||||
|
{
|
||||||
|
return js_map_write(s, map_state, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int JS_WriteSet(BCWriterState *s, struct JSMapState *map_state)
|
||||||
|
{
|
||||||
|
return js_map_write(s, map_state, MAGIC_SET);
|
||||||
|
}
|
||||||
|
|
||||||
static const JSCFunctionListEntry js_map_funcs[] = {
|
static const JSCFunctionListEntry js_map_funcs[] = {
|
||||||
JS_CFUNC_DEF("groupBy", 2, js_map_groupBy ),
|
JS_CFUNC_DEF("groupBy", 2, js_map_groupBy ),
|
||||||
JS_CGETSET_DEF("[Symbol.species]", js_get_this, NULL ),
|
JS_CGETSET_DEF("[Symbol.species]", js_get_this, NULL ),
|
||||||
|
|
|
@ -155,6 +155,28 @@ function bjson_test_regexp()
|
||||||
assert("sup dog".match(r).groups["𝓓𝓸𝓰"], "dog");
|
assert("sup dog".match(r).groups["𝓓𝓸𝓰"], "dog");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function bjson_test_map()
|
||||||
|
{
|
||||||
|
var buf, r, xs;
|
||||||
|
|
||||||
|
xs = [["key", "value"]];
|
||||||
|
buf = bjson.write(new Map(xs));
|
||||||
|
r = bjson.read(buf, 0, buf.byteLength);
|
||||||
|
assert(r instanceof Map);
|
||||||
|
assert([...r].toString(), xs.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
function bjson_test_set()
|
||||||
|
{
|
||||||
|
var buf, r, xs;
|
||||||
|
|
||||||
|
xs = ["one", "two", "three"];
|
||||||
|
buf = bjson.write(new Set(xs));
|
||||||
|
r = bjson.read(buf, 0, buf.byteLength);
|
||||||
|
assert(r instanceof Set);
|
||||||
|
assert([...r].toString(), xs.toString());
|
||||||
|
}
|
||||||
|
|
||||||
function bjson_test_all()
|
function bjson_test_all()
|
||||||
{
|
{
|
||||||
var obj;
|
var obj;
|
||||||
|
@ -184,6 +206,8 @@ function bjson_test_all()
|
||||||
|
|
||||||
bjson_test_reference();
|
bjson_test_reference();
|
||||||
bjson_test_regexp();
|
bjson_test_regexp();
|
||||||
|
bjson_test_map();
|
||||||
|
bjson_test_set();
|
||||||
}
|
}
|
||||||
|
|
||||||
bjson_test_all();
|
bjson_test_all();
|
||||||
|
|
Loading…
Reference in a new issue