Skip to content

Commit

Permalink
Don't stringify numeric keys in JS Maps
Browse files Browse the repository at this point in the history
  • Loading branch information
bnoordhuis committed Jan 18, 2025
1 parent c5880f7 commit ef4d3a5
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 7 deletions.
24 changes: 20 additions & 4 deletions ext/mini_racer_extension/mini_racer_extension.c
Original file line number Diff line number Diff line change
Expand Up @@ -171,13 +171,14 @@ static void *rendezvous_callback(void *arg);
typedef struct State
{
VALUE a, b;
uint8_t verbatim_keys:1;
} State;

// note: must be stack-allocated or VALUEs won't be visible to ruby's GC
typedef struct DesCtx
{
State *tos;
VALUE refs; // array
VALUE refs; // object refs array
uint8_t transcode_latin1:1;
char err[64];
State stack[512];
Expand All @@ -199,7 +200,7 @@ static void DesCtx_init(DesCtx *c)
{
c->tos = c->stack;
c->refs = rb_ary_new();
*c->tos = (State){Qundef, Qundef};
*c->tos = (State){Qundef, Qundef, /*verbatim_keys*/0};
*c->err = '\0';
c->transcode_latin1 = 1; // convert to utf8
}
Expand All @@ -220,7 +221,8 @@ static void put(DesCtx *c, VALUE v)
if (*b == Qundef) {
*b = v;
} else {
*b = rb_funcall(*b, rb_intern("to_s"), 0);
if (!c->tos->verbatim_keys)
*b = rb_funcall(*b, rb_intern("to_s"), 0);
rb_hash_aset(*a, *b, v);
*b = Qundef;
}
Expand All @@ -242,7 +244,7 @@ static void push(DesCtx *c, VALUE v)
snprintf(c->err, sizeof(c->err), "stack overflow");
return;
}
*++c->tos = (State){v, Qundef};
*++c->tos = (State){v, Qundef, /*verbatim_keys*/0};
rb_ary_push(c->refs, v);
}

Expand Down Expand Up @@ -426,6 +428,20 @@ static void des_object_end(void *arg)
pop(arg);
}

static void des_map_begin(void *arg)
{
DesCtx *c;

c = arg;
push(c, rb_hash_new());
c->tos->verbatim_keys = 1; // don't stringify or intern keys
}

static void des_map_end(void *arg)
{
pop(arg);
}

static void des_object_ref(void *arg, uint32_t id)
{
DesCtx *c;
Expand Down
6 changes: 4 additions & 2 deletions ext/mini_racer_extension/serde.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ static void des_named_props_begin(void *arg);
static void des_named_props_end(void *arg);
static void des_object_begin(void *arg);
static void des_object_end(void *arg);
static void des_map_begin(void *arg);
static void des_map_end(void *arg);
static void des_object_ref(void *arg, uint32_t id);
// des_error_begin: followed by des_object_begin + des_object_end calls
static void des_error_begin(void *arg);
Expand Down Expand Up @@ -642,7 +644,7 @@ static int des1(char (*err)[64], const uint8_t **p, const uint8_t *pe,
des_object_end(arg);
break;
case ';': // Map
des_object_begin(arg);
des_map_begin(arg);
for (u = 0; /*empty*/; u++) {
if (*p >= pe)
goto too_short;
Expand All @@ -658,7 +660,7 @@ static int des1(char (*err)[64], const uint8_t **p, const uint8_t *pe,
goto bad_varint;
if (t != 2*u)
return bail(err, "map element count mismatch");
des_object_end(arg);
des_map_end(arg);
break;
case '\'': // Set
des_array_begin(arg);
Expand Down
2 changes: 1 addition & 1 deletion test/mini_racer_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1097,7 +1097,7 @@ def test_function_property
}
else
expected = {
"m" => {"1" => 2, "3" => 4}, # TODO(bnoordhuis) retain numeric keys
"m" => {1 => 2, 3 => 4},
"s" => [5, 7, 11, 13],
"x" => 42,
}
Expand Down

0 comments on commit ef4d3a5

Please sign in to comment.