Skip to content

Commit 05abba0

Browse files
committed
Don't stringify numeric keys in JS Maps
1 parent 728da79 commit 05abba0

File tree

3 files changed

+25
-7
lines changed

3 files changed

+25
-7
lines changed

ext/mini_racer_extension/mini_racer_extension.c

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -171,13 +171,14 @@ static void *rendezvous_callback(void *arg);
171171
typedef struct State
172172
{
173173
VALUE a, b;
174+
uint8_t verbatim_keys:1;
174175
} State;
175176

176177
// note: must be stack-allocated or VALUEs won't be visible to ruby's GC
177178
typedef struct DesCtx
178179
{
179180
State *tos;
180-
VALUE refs; // array
181+
VALUE refs; // object refs array
181182
uint8_t transcode_latin1:1;
182183
char err[64];
183184
State stack[512];
@@ -199,7 +200,7 @@ static void DesCtx_init(DesCtx *c)
199200
{
200201
c->tos = c->stack;
201202
c->refs = rb_ary_new();
202-
*c->tos = (State){Qundef, Qundef};
203+
*c->tos = (State){Qundef, Qundef, /*verbatim_keys*/0};
203204
*c->err = '\0';
204205
c->transcode_latin1 = 1; // convert to utf8
205206
}
@@ -220,7 +221,8 @@ static void put(DesCtx *c, VALUE v)
220221
if (*b == Qundef) {
221222
*b = v;
222223
} else {
223-
*b = rb_funcall(*b, rb_intern("to_s"), 0);
224+
if (!c->tos->verbatim_keys)
225+
*b = rb_funcall(*b, rb_intern("to_s"), 0);
224226
rb_hash_aset(*a, *b, v);
225227
*b = Qundef;
226228
}
@@ -242,7 +244,7 @@ static void push(DesCtx *c, VALUE v)
242244
snprintf(c->err, sizeof(c->err), "stack overflow");
243245
return;
244246
}
245-
*++c->tos = (State){v, Qundef};
247+
*++c->tos = (State){v, Qundef, /*verbatim_keys*/0};
246248
rb_ary_push(c->refs, v);
247249
}
248250

@@ -426,6 +428,20 @@ static void des_object_end(void *arg)
426428
pop(arg);
427429
}
428430

431+
static void des_map_begin(void *arg)
432+
{
433+
DesCtx *c;
434+
435+
c = arg;
436+
push(c, rb_hash_new());
437+
c->tos->verbatim_keys = 1; // don't stringify or intern keys
438+
}
439+
440+
static void des_map_end(void *arg)
441+
{
442+
pop(arg);
443+
}
444+
429445
static void des_object_ref(void *arg, uint32_t id)
430446
{
431447
DesCtx *c;

ext/mini_racer_extension/serde.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ static void des_named_props_begin(void *arg);
3131
static void des_named_props_end(void *arg);
3232
static void des_object_begin(void *arg);
3333
static void des_object_end(void *arg);
34+
static void des_map_begin(void *arg);
35+
static void des_map_end(void *arg);
3436
static void des_object_ref(void *arg, uint32_t id);
3537
// des_error_begin: followed by des_object_begin + des_object_end calls
3638
static void des_error_begin(void *arg);
@@ -642,7 +644,7 @@ static int des1(char (*err)[64], const uint8_t **p, const uint8_t *pe,
642644
des_object_end(arg);
643645
break;
644646
case ';': // Map
645-
des_object_begin(arg);
647+
des_map_begin(arg);
646648
for (u = 0; /*empty*/; u++) {
647649
if (*p >= pe)
648650
goto too_short;
@@ -658,7 +660,7 @@ static int des1(char (*err)[64], const uint8_t **p, const uint8_t *pe,
658660
goto bad_varint;
659661
if (t != 2*u)
660662
return bail(err, "map element count mismatch");
661-
des_object_end(arg);
663+
des_map_end(arg);
662664
break;
663665
case '\'': // Set
664666
des_array_begin(arg);

test/mini_racer_test.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1097,7 +1097,7 @@ def test_function_property
10971097
}
10981098
else
10991099
expected = {
1100-
"m" => {"1" => 2, "3" => 4}, # TODO(bnoordhuis) retain numeric keys
1100+
"m" => {1 => 2, 3 => 4},
11011101
"s" => [5, 7, 11, 13],
11021102
"x" => 42,
11031103
}

0 commit comments

Comments
 (0)