Skip to content

Commit 29a3382

Browse files
fix: uneval emits valid JS for repeated empty Map/Set (#168)
* fix: uneval emits valid JS for repeated empty Map/Set A Map or Set referenced more than once is bound to a variable and populated via a chained statement (e.g. a.set(...).set(...)). When the collection was empty, this produced a dangling member expression 'a.' \u2014 a syntax error. Emit no chained statement for empty collections; 'new Map'/'new Set' already builds them. * refactor: address review feedback on Map/Set chain building
1 parent 48cc81f commit 29a3382

3 files changed

Lines changed: 38 additions & 11 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"devalue": patch
3+
---
4+
5+
fix: `uneval` now produces valid output for a repeated empty `Map` or `Set`

‎src/uneval.js‎

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -413,23 +413,23 @@ export function uneval(value, replacer) {
413413
});
414414
break;
415415

416-
case 'Set':
416+
case 'Set': {
417417
values.push(`new Set`);
418-
statements.push(
419-
`${name}.${Array.from(thing)
420-
.map((v) => `add(${stringify(v)})`)
421-
.join('.')}`
422-
);
418+
const adds = Array.from(thing).map((v) => `.add(${stringify(v)})`);
419+
// An empty Set is fully built by `new Set`; a chained statement would
420+
// otherwise be a dangling `name.`.
421+
if (adds.length > 0) statements.push(name + adds.join(''));
423422
break;
423+
}
424424

425-
case 'Map':
425+
case 'Map': {
426426
values.push(`new Map`);
427-
statements.push(
428-
`${name}.${Array.from(thing)
429-
.map(([k, v]) => `set(${stringify(k)}, ${stringify(v)})`)
430-
.join('.')}`
427+
const sets = Array.from(thing).map(
428+
([k, v]) => `.set(${stringify(k)}, ${stringify(v)})`
431429
);
430+
if (sets.length > 0) statements.push(name + sets.join(''));
432431
break;
432+
}
433433

434434
case 'Int8Array':
435435
case 'Uint8Array':

‎test/index.test.js‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,28 @@ const fixtures = {
630630
validate: ([a, b]) => assert.is(a, b)
631631
},
632632

633+
{
634+
name: 'empty Map (repetition)',
635+
value: ((map) => [map, map])(new Map()),
636+
js: '(function(a){return [a,a]}(new Map))',
637+
json: '[[1,1],["Map"]]',
638+
validate: ([a, b]) => {
639+
assert.is(a, b);
640+
assert.is(a.size, 0);
641+
}
642+
},
643+
644+
{
645+
name: 'empty Set (repetition)',
646+
value: ((set) => [set, set])(new Set()),
647+
js: '(function(a){return [a,a]}(new Set))',
648+
json: '[[1,1],["Set"]]',
649+
validate: ([a, b]) => {
650+
assert.is(a, b);
651+
assert.is(a.size, 0);
652+
}
653+
},
654+
633655
{
634656
name: 'RegExp (repetition)',
635657
value: ((regexp) => [regexp, regexp])(/regexp/),

0 commit comments

Comments
 (0)