Skip to content

Commit 7eb65d8

Browse files
Merge pull request #88 from WebReflection/avoid-recusrion
Avoid recursion on parse due possible shenanigans
2 parents b1dee01 + 7774aae commit 7eb65d8

File tree

10 files changed

+857
-1100
lines changed

10 files changed

+857
-1100
lines changed

README.md

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,9 @@ Available also for **[Go](./golang/README.md)**.
1616

1717
- - -
1818

19-
## Announcement 📣
19+
## ℹ️ JSON only values
2020

21-
There is a standard approach to recursion and more data-types than what JSON allows, and it's part of the [Structured Clone polyfill](https://github.com/ungap/structured-clone/#readme).
22-
23-
Beside acting as a polyfill, its `@ungap/structured-clone/json` export provides both `stringify` and `parse`, and it's been tested for being faster than *flatted*, but its produced output is also smaller than *flatted* in general.
24-
25-
The *@ungap/structured-clone* module is, in short, a drop in replacement for *flatted*, but it's not compatible with *flatted* specialized syntax.
26-
27-
However, if recursion, as well as more data-types, are what you are after, or interesting for your projects/use cases, consider switching to this new module whenever you can 👍
21+
If you need anything more complex than values JSON understands, there is a standard approach to recursion and more data-types than what JSON allows, and it's part of the [Structured Clone polyfill](https://github.com/ungap/structured-clone/#readme).
2822

2923
- - -
3024

cjs/index.js

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@ const Primitives = (_, value) => (
2222
typeof value === primitive ? new Primitive(value) : value
2323
);
2424

25-
const revive = (input, parsed, output, $) => {
26-
const lazy = [];
25+
const resolver = (input, lazy, parsed, $) => output => {
2726
for (let ke = keys(output), {length} = ke, y = 0; y < length; y++) {
2827
const k = ke[y];
2928
const value = output[k];
@@ -32,18 +31,14 @@ const revive = (input, parsed, output, $) => {
3231
if (typeof tmp === object && !parsed.has(tmp)) {
3332
parsed.add(tmp);
3433
output[k] = ignore;
35-
lazy.push({k, a: [input, parsed, tmp, $]});
34+
lazy.push({ o: output, k, r: tmp });
3635
}
3736
else
3837
output[k] = $.call(output, k, tmp);
3938
}
4039
else if (output[k] !== ignore)
4140
output[k] = $.call(output, k, value);
4241
}
43-
for (let {length} = lazy, i = 0; i < length; i++) {
44-
const {k, a} = lazy[i];
45-
output[k] = $.call(output, k, revive.apply(null, a));
46-
}
4742
return output;
4843
};
4944

@@ -61,12 +56,24 @@ const set = (known, input, value) => {
6156
*/
6257
const parse = (text, reviver) => {
6358
const input = $parse(text, Primitives).map(primitives);
64-
const value = input[0];
6559
const $ = reviver || noop;
66-
const tmp = typeof value === object && value ?
67-
revive(input, new Set, value, $) :
68-
value;
69-
return $.call({'': tmp}, '', tmp);
60+
61+
let value = input[0];
62+
63+
if (typeof value === object && value) {
64+
const lazy = [];
65+
const revive = resolver(input, lazy, new Set, $);
66+
value = revive(value);
67+
68+
let i = 0;
69+
while (i < lazy.length) {
70+
// it could be a lazy.shift() but that's costly
71+
const {o, k, r} = lazy[i++];
72+
o[k] = $.call(o, k, revive(r));
73+
}
74+
}
75+
76+
return $.call({'': value}, '', value);
7077
};
7178
exports.parse = parse;
7279

es.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

esm.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

esm/index.js

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@ const Primitives = (_, value) => (
2121
typeof value === primitive ? new Primitive(value) : value
2222
);
2323

24-
const revive = (input, parsed, output, $) => {
25-
const lazy = [];
24+
const resolver = (input, lazy, parsed, $) => output => {
2625
for (let ke = keys(output), {length} = ke, y = 0; y < length; y++) {
2726
const k = ke[y];
2827
const value = output[k];
@@ -31,18 +30,14 @@ const revive = (input, parsed, output, $) => {
3130
if (typeof tmp === object && !parsed.has(tmp)) {
3231
parsed.add(tmp);
3332
output[k] = ignore;
34-
lazy.push({k, a: [input, parsed, tmp, $]});
33+
lazy.push({ o: output, k, r: tmp });
3534
}
3635
else
3736
output[k] = $.call(output, k, tmp);
3837
}
3938
else if (output[k] !== ignore)
4039
output[k] = $.call(output, k, value);
4140
}
42-
for (let {length} = lazy, i = 0; i < length; i++) {
43-
const {k, a} = lazy[i];
44-
output[k] = $.call(output, k, revive.apply(null, a));
45-
}
4641
return output;
4742
};
4843

@@ -60,12 +55,24 @@ const set = (known, input, value) => {
6055
*/
6156
export const parse = (text, reviver) => {
6257
const input = $parse(text, Primitives).map(primitives);
63-
const value = input[0];
6458
const $ = reviver || noop;
65-
const tmp = typeof value === object && value ?
66-
revive(input, new Set, value, $) :
67-
value;
68-
return $.call({'': tmp}, '', tmp);
59+
60+
let value = input[0];
61+
62+
if (typeof value === object && value) {
63+
const lazy = [];
64+
const revive = resolver(input, lazy, new Set, $);
65+
value = revive(value);
66+
67+
let i = 0;
68+
while (i < lazy.length) {
69+
// it could be a lazy.shift() but that's costly
70+
const {o, k, r} = lazy[i++];
71+
o[k] = $.call(o, k, revive(r));
72+
}
73+
}
74+
75+
return $.call({'': value}, '', value);
6976
};
7077

7178
/**

index.js

Lines changed: 37 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -32,30 +32,26 @@ self.Flatted = (function (exports) {
3232
var Primitives = function Primitives(_, value) {
3333
return _typeof(value) === primitive ? new Primitive(value) : value;
3434
};
35-
var _revive = function revive(input, parsed, output, $) {
36-
var lazy = [];
37-
for (var ke = keys(output), length = ke.length, y = 0; y < length; y++) {
38-
var k = ke[y];
39-
var value = output[k];
40-
if (value instanceof Primitive) {
41-
var tmp = input[value];
42-
if (_typeof(tmp) === object && !parsed.has(tmp)) {
43-
parsed.add(tmp);
44-
output[k] = ignore;
45-
lazy.push({
46-
k: k,
47-
a: [input, parsed, tmp, $]
48-
});
49-
} else output[k] = $.call(output, k, tmp);
50-
} else if (output[k] !== ignore) output[k] = $.call(output, k, value);
51-
}
52-
for (var _length = lazy.length, i = 0; i < _length; i++) {
53-
var _lazy$i = lazy[i],
54-
_k = _lazy$i.k,
55-
a = _lazy$i.a;
56-
output[_k] = $.call(output, _k, _revive.apply(null, a));
57-
}
58-
return output;
35+
var resolver = function resolver(input, lazy, parsed, $) {
36+
return function (output) {
37+
for (var ke = keys(output), length = ke.length, y = 0; y < length; y++) {
38+
var k = ke[y];
39+
var value = output[k];
40+
if (value instanceof Primitive) {
41+
var tmp = input[value];
42+
if (_typeof(tmp) === object && !parsed.has(tmp)) {
43+
parsed.add(tmp);
44+
output[k] = ignore;
45+
lazy.push({
46+
o: output,
47+
k: k,
48+
r: tmp
49+
});
50+
} else output[k] = $.call(output, k, tmp);
51+
} else if (output[k] !== ignore) output[k] = $.call(output, k, value);
52+
}
53+
return output;
54+
};
5955
};
6056
var set = function set(known, input, value) {
6157
var index = Primitive(input.push(value) - 1);
@@ -71,12 +67,25 @@ self.Flatted = (function (exports) {
7167
*/
7268
var parse = function parse(text, reviver) {
7369
var input = $parse(text, Primitives).map(primitives);
74-
var value = input[0];
7570
var $ = reviver || noop;
76-
var tmp = _typeof(value) === object && value ? _revive(input, new Set(), value, $) : value;
71+
var value = input[0];
72+
if (_typeof(value) === object && value) {
73+
var lazy = [];
74+
var revive = resolver(input, lazy, new Set(), $);
75+
value = revive(value);
76+
var i = 0;
77+
while (i < lazy.length) {
78+
// it could be a lazy.shift() but that's costly
79+
var _lazy$i = lazy[i++],
80+
o = _lazy$i.o,
81+
k = _lazy$i.k,
82+
r = _lazy$i.r;
83+
o[k] = $.call(o, k, revive(r));
84+
}
85+
}
7786
return $.call({
78-
'': tmp
79-
}, '', tmp);
87+
'': value
88+
}, '', value);
8089
};
8190

8291
/**

min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)