Skip to content
This repository was archived by the owner on Jan 1, 2023. It is now read-only.

Commit da7a9e6

Browse files
committed
✨ (src) add minJSONStringSize option
1 parent 06b2572 commit da7a9e6

File tree

5 files changed

+130
-3
lines changed

5 files changed

+130
-3
lines changed

README.md

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ This repository is inspired by [this article](https://v8.dev/blog/cost-of-javasc
99

1010
> As long as the JSON string is only evaluated once, the JSON.parse approach is much faster compared to the JavaScript object literal, especially for cold loads.
1111
12+
**Caution!!** : I made this plugin for my understanding about AST and babel plugin, so this plugin is not production ready.
13+
1214
## Object to JSON.parse
1315

1416
This plugin converts from object literal to JSON.parse ([example](https://github.com/nd-02110114/babel-plugin-object-to-json-parse/tree/master/example))
@@ -33,12 +35,28 @@ $ yarn babel-plugin-object-to-json-parse -D
3335

3436
### setup `.babelrc`
3537

36-
```
38+
```json
3739
{
3840
"plugins": ["object-to-json-parse"]
3941
}
4042
```
4143

44+
45+
### Options
46+
#### `minJSONStringSize` (`number`, dafaults to `1024`)
47+
48+
The `minJSONStringSize` option will prevent the plugin from replacing an expression if the length of the JSON string given to `JSON.parse` is smaller than `minJSONStringSize`. For example, the following ensures all replacements have a string size of at least 1kb.
49+
50+
```json
51+
{
52+
"plugins": [
53+
["object-to-json-parse", {
54+
"minJSONStringSize": 1024
55+
}]
56+
]
57+
}
58+
```
59+
4260
## Development
4361

4462
### Setup
@@ -51,7 +69,7 @@ $ yarn install
5169

5270
### Tips
5371

54-
```
72+
```sh
5573
// example
5674
$ yarn build && yarn example
5775

example/.babelrc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
"plugins": [
33
[
44
"../dist/index.js",
5+
{
6+
"minJSONStringSize": 0
7+
}
58
]
69
]
710
}

src/visitors/object_expression.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,32 @@ import { ObjectExpression } from '@babel/types'
22
import { NodePath } from '@babel/traverse'
33
import { converter } from '../utils'
44

5+
interface PluginState {
6+
opts: {
7+
minJSONStringSize: number
8+
}
9+
}
10+
11+
const DEFAULT_THRESHOLD = 1024
12+
513
/* eslint-disable no-redeclare */
6-
export function ObjectExpression(path: NodePath<ObjectExpression>) {
14+
export function ObjectExpression(
15+
path: NodePath<ObjectExpression>,
16+
state: PluginState
17+
) {
718
try {
819
const obj = converter(path.node)
920
const json = JSON.stringify(obj)
1021
// escaping for single quotes
1122
const escapedJson = json.replace(/'/g, "\\'")
23+
// it simply isn't worth it to convert into the AST objects that are too small.
24+
// so, this plugin only convert large objects by default.
25+
const { minJSONStringSize } = state.opts
26+
const threshold =
27+
minJSONStringSize !== undefined ? minJSONStringSize : DEFAULT_THRESHOLD
28+
if (escapedJson.length < threshold) {
29+
return
30+
}
1231
path.replaceWithSourceString(`JSON.parse('${escapedJson}')`)
1332
} catch (e) {
1433
// disable error message

test/visitors/object_expression.test.ts

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,57 @@ pluginTester({
66
plugin: buildPlugin([ObjectExpression]),
77
tests: [{
88
title: 'empty object',
9+
pluginOptions: {
10+
minJSONStringSize: 0
11+
},
912
code: `const a = {};`,
1013
output: `const a = JSON.parse('{}');`
14+
}, {
15+
title: 'respects minJSONStringSize (default : 1024)',
16+
code: `const a = { b: 1, c: 2 };`,
17+
output: `
18+
const a = {
19+
b: 1,
20+
c: 2
21+
};
22+
`
23+
}, {
24+
title: 'respects minJSONStringSize',
25+
pluginOptions: {
26+
minJSONStringSize: 15
27+
},
28+
code: `const a = { b: 1, c: 2 };`,
29+
output: `
30+
const a = {
31+
b: 1,
32+
c: 2
33+
};
34+
`
35+
}, {
36+
title: 'respects minJSONStringSize',
37+
pluginOptions: {
38+
minJSONStringSize: 0
39+
},
40+
code: `const a = { b: 1, c: 2 };`,
41+
output: `
42+
const a = JSON.parse('{"b":1,"c":2}');
43+
`
1144
}, {
1245
title: 'does not convert objects which include the spread syntax',
1346
code: `const a = { ...a, b: 1 };`,
47+
pluginOptions: {
48+
minJSONStringSize: 0
49+
},
1450
output: `
1551
const a = { ...a,
1652
b: 1
1753
};
1854
`
1955
}, {
2056
title: 'does not convert objects which include the object method',
57+
pluginOptions: {
58+
minJSONStringSize: 0
59+
},
2160
code: `
2261
const a = {
2362
method(arg) {
@@ -37,6 +76,9 @@ pluginTester({
3776
`
3877
}, {
3978
title: 'does not convert objects which include the invalid value',
79+
pluginOptions: {
80+
minJSONStringSize: 0
81+
},
4082
code: `const a = { b: () => console.log("b") };`,
4183
output: `
4284
const a = {
@@ -45,6 +87,9 @@ pluginTester({
4587
`
4688
}, {
4789
title: 'does not convert objects which have computed property names',
90+
pluginOptions: {
91+
minJSONStringSize: 0
92+
},
4893
code: `const a = { b : "b_val", ["c"]: "c_val" };`,
4994
output: `
5095
const a = {
@@ -54,6 +99,9 @@ pluginTester({
5499
`
55100
}, {
56101
title: 'does not convert objects which have double quotes in string',
102+
pluginOptions: {
103+
minJSONStringSize: 0
104+
},
57105
code: `const a = { b: 'ab\"c' };`,
58106
output: `
59107
const a = {
@@ -62,6 +110,9 @@ pluginTester({
62110
`
63111
}, {
64112
title: 'does not convert objects which have double quotes in string',
113+
pluginOptions: {
114+
minJSONStringSize: 0
115+
},
65116
code: `const a = { b: 'ab"c' };`,
66117
output: `
67118
const a = {
@@ -70,6 +121,9 @@ pluginTester({
70121
`
71122
}, {
72123
title: 'does not convert objects which have invalid numeric key',
124+
pluginOptions: {
125+
minJSONStringSize: 0
126+
},
73127
code: `const a ={ 77777777777777777.1: "foo" };`,
74128
output: `
75129
const a = {
@@ -78,42 +132,72 @@ pluginTester({
78132
`
79133
}, {
80134
title: 'string',
135+
pluginOptions: {
136+
minJSONStringSize: 0
137+
},
81138
code: `const a = { b: "b_val" };`,
82139
output: `const a = JSON.parse('{"b":"b_val"}');`
83140
}, {
84141
title: 'string (include single quote)',
142+
pluginOptions: {
143+
minJSONStringSize: 0
144+
},
85145
code: `const a = { b: "'abc'" };`,
86146
output: `const a = JSON.parse('{"b":"\\'abc\\'"}');`
87147
}, {
88148
title: 'string (include single quote)',
149+
pluginOptions: {
150+
minJSONStringSize: 0
151+
},
89152
code: `const a = { b: "ab\'c" };`,
90153
output: `const a = JSON.parse('{"b":"ab\\'c"}');`
91154
}, {
92155
title: 'number',
156+
pluginOptions: {
157+
minJSONStringSize: 0
158+
},
93159
code: `const a = { b: 1 };`,
94160
output: `const a = JSON.parse('{"b":1}');`
95161
}, {
96162
title: 'null',
163+
pluginOptions: {
164+
minJSONStringSize: 0
165+
},
97166
code: `const a = { b: null };`,
98167
output: `const a = JSON.parse('{"b":null}');`
99168
}, {
100169
title: 'boolean',
170+
pluginOptions: {
171+
minJSONStringSize: 0
172+
},
101173
code: `const a = { b: false };`,
102174
output: `const a = JSON.parse('{"b":false}');`
103175
}, {
104176
title: 'Array',
177+
pluginOptions: {
178+
minJSONStringSize: 0
179+
},
105180
code: `const a = { b: [1, 'b_val', null] };`,
106181
output: `const a = JSON.parse('{"b":[1,"b_val",null]}');`
107182
}, {
108183
title: 'Nested Array',
184+
pluginOptions: {
185+
minJSONStringSize: 0
186+
},
109187
code: `const a = { b: [1, ['b_val', { a: 1 }], null] };`,
110188
output: `const a = JSON.parse('{"b":[1,["b_val",{"a":1}],null]}');`
111189
}, {
112190
title: 'Object',
191+
pluginOptions: {
192+
minJSONStringSize: 0
193+
},
113194
code: `const a = { b: { c: 1 } };`,
114195
output: `const a = JSON.parse('{"b":{"c":1}}');`
115196
}, {
116197
title: 'Object (having numeric keys)',
198+
pluginOptions: {
199+
minJSONStringSize: 0
200+
},
117201
code: `const a = { 1: "123", 23: 45, b: "b_val" };`,
118202
output: `const a = JSON.parse('{"1":"123","23":45,"b":"b_val"}');`
119203
},]

typings/babel-plugin-tester/index.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ declare namespace pluginTester {
88

99
export interface Test {
1010
title?: string;
11+
pluginOptions?: {
12+
minJSONStringSize: number
13+
};
1114
code?: string;
1215
output?: string;
1316
snapshot?: boolean;

0 commit comments

Comments
 (0)