@atproto/lex-json 0.0.14 β†’ 0.0.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,125 @@
1
+ import { bench, describe } from 'vitest'
2
+ import { JsonValue } from './json.js'
3
+ import {
4
+ LexParseOptions,
5
+ jsonToLex,
6
+ lexParse,
7
+ parseSpecialJsonObject,
8
+ } from './lex-json.js'
9
+
10
+ // This benchmark compares the performance of two implementations of
11
+ // lexParse:
12
+ // - One that uses a reviver function with JSON.parse to directly parse special
13
+ // objects and handle numbers (lexParse with reviver)
14
+ // - One that first parses JSON to a plain JS object and then converts it to
15
+ // LexValue using jsonToLex (lexParse with jsonToLex)
16
+
17
+ describe('small object', () => {
18
+ benchData({
19
+ $type: 'app.bsky.feed.post',
20
+ text: 'Hello world! πŸ‘‹',
21
+ createdAt: '2024-01-01T00:00:00Z',
22
+ })
23
+ })
24
+
25
+ describe('simple mixed structure', () => {
26
+ benchData({
27
+ cid: {
28
+ $link: 'bafyreidfayvfuwqa7qlnopdjiqrxzs6blmoeu4rujcjtnci5beludirz2a',
29
+ },
30
+ bytes: {
31
+ $bytes: 'nFERjvLLiw9qm45JrqH9QTzyC2Lu1Xb4ne6+sBrCzI0',
32
+ },
33
+ blob: {
34
+ $type: 'blob',
35
+ ref: {
36
+ $link: 'bafkreig77vqcdozl2wyk6z3cscaj5q5fggi53aoh64fewkdiri3cdauyn4',
37
+ },
38
+ mimeType: 'image/jpeg',
39
+ size: 10000,
40
+ },
41
+ nested: {
42
+ array: [
43
+ {
44
+ number: 42,
45
+ string: 'hello world',
46
+ bool: true,
47
+ null: null,
48
+ },
49
+ ],
50
+ string: 'Hello δΈ–η•Œ! 🌍🌎🌏 Γ‘oΓ±o',
51
+ createdAt: '2024-01-01T00:00:00Z',
52
+ },
53
+ })
54
+ })
55
+
56
+ describe('large payload', () => {
57
+ benchData({
58
+ items: Array.from({ length: 25 }, (_, i) => ({
59
+ id: i,
60
+ name: `Item ${i}`,
61
+ longUnicode:
62
+ 'Lorem ipsum dolor sit amet, consectetur adipiscing elit 🀩.\n'.repeat(
63
+ 2,
64
+ ),
65
+ tags: ['tag1', 'tag2', 'tag3'],
66
+ bytes: {
67
+ $bytes: Buffer.from(`This is some byte data for item ${i}`).toString(
68
+ 'base64',
69
+ ),
70
+ },
71
+ cid: {
72
+ $link: 'bafyreidfayvfuwqa7qlnopdjiqrxzs6blmoeu4rujcjtnci5beludirz2a',
73
+ },
74
+ metadata: {
75
+ created: '2024-01-01T00:00:00Z',
76
+ count: i * 10,
77
+ nested: {
78
+ flag: i % 2 === 0,
79
+ values: [i, i * 2, i * 3],
80
+ },
81
+ items: Array.from({ length: 5 }, (_, j) => ({
82
+ id: `${i}-${j}`,
83
+ value: `Value ${i}-${j}`,
84
+ })),
85
+ },
86
+ })),
87
+ })
88
+ })
89
+
90
+ function benchData(data: unknown, options?: LexParseOptions) {
91
+ const jsonString = JSON.stringify(data)
92
+
93
+ const withReviver: typeof lexParse = (input, options = { strict: true }) => {
94
+ return JSON.parse(input, (key: string, value: JsonValue) => {
95
+ switch (typeof value) {
96
+ case 'object':
97
+ if (value === null) return null
98
+ if (Array.isArray(value)) return value
99
+ return parseSpecialJsonObject(value, options) ?? value
100
+ case 'number':
101
+ if (Number.isSafeInteger(value)) return value
102
+ if (options && options.strict === false) return value
103
+ throw new TypeError(`Invalid non-integer number: ${value}`)
104
+ default:
105
+ return value
106
+ }
107
+ })
108
+ }
109
+
110
+ const naiveParse: typeof lexParse = (input, options) => {
111
+ return jsonToLex(JSON.parse(input), options) as any
112
+ }
113
+
114
+ bench('current', () => {
115
+ lexParse(jsonString, options)
116
+ })
117
+
118
+ bench('with-reviver', () => {
119
+ withReviver(jsonString, options)
120
+ })
121
+
122
+ bench('naive', () => {
123
+ naiveParse(jsonString, options)
124
+ })
125
+ }