Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion gen/function_source.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
const uint32_t qjsc_function_source_size = 384;

const uint8_t qjsc_function_source[384] = {
0x0c, 0x06, 0x0c, 0x61, 0x63, 0x74, 0x75, 0x61,
0x0d, 0x06, 0x0c, 0x61, 0x63, 0x74, 0x75, 0x61,
0x6c, 0x02, 0x66, 0x30, 0x74, 0x65, 0x73, 0x74,
0x73, 0x2f, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69,
0x6f, 0x6e, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63,
Expand Down
2 changes: 1 addition & 1 deletion gen/hello.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
const uint32_t qjsc_hello_size = 89;

const uint8_t qjsc_hello[89] = {
0x0c, 0x04, 0x0e, 0x63, 0x6f, 0x6e, 0x73, 0x6f,
0x0d, 0x04, 0x0e, 0x63, 0x6f, 0x6e, 0x73, 0x6f,
0x6c, 0x65, 0x06, 0x6c, 0x6f, 0x67, 0x16, 0x48,
0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72,
0x6c, 0x64, 0x22, 0x65, 0x78, 0x61, 0x6d, 0x70,
Expand Down
4 changes: 2 additions & 2 deletions gen/hello_module.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
const uint32_t qjsc_fib_module_size = 311;

const uint8_t qjsc_fib_module[311] = {
0x0c, 0x03, 0x2c, 0x65, 0x78, 0x61, 0x6d, 0x70,
0x0d, 0x03, 0x2c, 0x65, 0x78, 0x61, 0x6d, 0x70,
0x6c, 0x65, 0x73, 0x2f, 0x66, 0x69, 0x62, 0x5f,
0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x2e, 0x6a,
0x73, 0x06, 0x66, 0x69, 0x62, 0x02, 0x6e, 0x0d,
Expand Down Expand Up @@ -49,7 +49,7 @@ const uint8_t qjsc_fib_module[311] = {
const uint32_t qjsc_hello_module_size = 178;

const uint8_t qjsc_hello_module[178] = {
0x0c, 0x07, 0x30, 0x65, 0x78, 0x61, 0x6d, 0x70,
0x0d, 0x07, 0x30, 0x65, 0x78, 0x61, 0x6d, 0x70,
0x6c, 0x65, 0x73, 0x2f, 0x68, 0x65, 0x6c, 0x6c,
0x6f, 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65,
0x2e, 0x6a, 0x73, 0x1e, 0x2e, 0x2f, 0x66, 0x69,
Expand Down
2 changes: 1 addition & 1 deletion gen/repl.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
const uint32_t qjsc_repl_size = 22730;

const uint8_t qjsc_repl[22730] = {
0x0c, 0x92, 0x04, 0x0e, 0x72, 0x65, 0x70, 0x6c,
0x0d, 0x92, 0x04, 0x0e, 0x72, 0x65, 0x70, 0x6c,
0x2e, 0x6a, 0x73, 0x06, 0x73, 0x74, 0x64, 0x04,
0x6f, 0x73, 0x0a, 0x62, 0x6a, 0x73, 0x6f, 0x6e,
0x02, 0x67, 0x10, 0x69, 0x73, 0x46, 0x69, 0x6e,
Expand Down
2 changes: 1 addition & 1 deletion gen/test_fib.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
const uint32_t qjsc_test_fib_size = 167;

const uint8_t qjsc_test_fib[167] = {
0x0c, 0x07, 0x28, 0x65, 0x78, 0x61, 0x6d, 0x70,
0x0d, 0x07, 0x28, 0x65, 0x78, 0x61, 0x6d, 0x70,
0x6c, 0x65, 0x73, 0x2f, 0x74, 0x65, 0x73, 0x74,
0x5f, 0x66, 0x69, 0x62, 0x2e, 0x6a, 0x73, 0x10,
0x2e, 0x2f, 0x66, 0x69, 0x62, 0x2e, 0x73, 0x6f,
Expand Down
117 changes: 116 additions & 1 deletion quickjs.c
Original file line number Diff line number Diff line change
Expand Up @@ -33114,9 +33114,11 @@ typedef enum BCTagEnum {
BC_TAG_DATE,
BC_TAG_OBJECT_VALUE,
BC_TAG_OBJECT_REFERENCE,
BC_TAG_MAP,
BC_TAG_SET,
} BCTagEnum;

#define BC_VERSION 12
#define BC_VERSION 13

typedef struct BCWriterState {
JSContext *ctx;
Expand Down Expand Up @@ -33757,6 +33759,9 @@ static int JS_WriteRegExp(BCWriterState *s, JSRegExp regexp)
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)
{
uint32_t tag;
Expand Down Expand Up @@ -33860,6 +33865,14 @@ static int JS_WriteObjectRec(BCWriterState *s, JSValue obj)
bc_put_u8(s, BC_TAG_OBJECT_VALUE);
ret = JS_WriteObjectRec(s, p->u.object_data);
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:
if (p->class_id >= JS_CLASS_UINT8C_ARRAY &&
p->class_id <= JS_CLASS_FLOAT64_ARRAY) {
Expand Down Expand Up @@ -34996,6 +35009,9 @@ static JSValue JS_ReadObjectValue(BCReaderState *s)
return JS_EXCEPTION;
}

static JSValue JS_ReadMap(BCReaderState *s);
static JSValue JS_ReadSet(BCReaderState *s);

static JSValue JS_ReadObjectRec(BCReaderState *s)
{
JSContext *ctx = s->ctx;
Expand Down Expand Up @@ -35103,6 +35119,12 @@ static JSValue JS_ReadObjectRec(BCReaderState *s)
obj = js_dup(JS_MKPTR(JS_TAG_OBJECT, s->objects[val]));
}
break;
case BC_TAG_MAP:
obj = JS_ReadMap(s);
break;
case BC_TAG_SET:
obj = JS_ReadSet(s);
break;
default:
invalid_tag:
return JS_ThrowSyntaxError(ctx, "invalid tag (tag=%d pos=%u)",
Expand Down Expand Up @@ -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++) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
for(i = 0; i < prop_count; i++) {
for (i = 0; i < prop_count; i++) {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm merely following the predominant style for for loops here (of the 533 for statements in quickjs.c, 66.8% are written this way.)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh!

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fabrice and i differ on this, I always put a space after if, for, while, switch, return with a value etc. Fabrice is less adamant about it :)

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;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this necessary since yoy are about to return?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, because it's inside a loop, otherwise we can end up double-freeing argv[1] on the next iteration.

(And I'm clearing argv[0] for clarity's sake, otherwise a casual reader will stop and think: "Why one and not the other?")

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great!

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[] = {
JS_CFUNC_DEF("groupBy", 2, js_map_groupBy ),
JS_CGETSET_DEF("[Symbol.species]", js_get_this, NULL ),
Expand Down
24 changes: 24 additions & 0 deletions tests/test_bjson.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,28 @@ function bjson_test_regexp()
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()
{
var obj;
Expand Down Expand Up @@ -184,6 +206,8 @@ function bjson_test_all()

bjson_test_reference();
bjson_test_regexp();
bjson_test_map();
bjson_test_set();
}

bjson_test_all();