Skip to content

Commit e20f9ec

Browse files
committed
ref: Handle more edge cases & add large test
1 parent 226ecc9 commit e20f9ec

File tree

8 files changed

+109
-64
lines changed

8 files changed

+109
-64
lines changed

packages/replay/src/util/truncateJson/completeJson.ts

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
11
import type { JsonToken } from './constants';
22
import {
33
ARR,
4-
ARR_COMMA,
54
ARR_VAL,
65
ARR_VAL_COMPLETED,
76
ARR_VAL_STR,
87
OBJ,
9-
OBJ_COLON,
10-
OBJ_COMMA,
118
OBJ_KEY,
129
OBJ_KEY_STR,
1310
OBJ_VAL,
@@ -62,16 +59,12 @@ function _fixLastStep(json: string, lastStep: JsonToken): string {
6259
return `${json}:"~~"`;
6360
case OBJ_KEY_STR:
6461
return `${json}~~":"~~"`;
65-
case OBJ_COLON:
66-
return `${json}"~~"`;
6762
case OBJ_VAL:
6863
return _maybeFixIncompleteObjValue(json);
6964
case OBJ_VAL_STR:
7065
return `${json}~~"`;
7166
case OBJ_VAL_COMPLETED:
7267
return `${json},"~~":"~~"`;
73-
case OBJ_COMMA:
74-
return `${json}"~~":"~~"`;
7568

7669
// Array cases
7770
case ARR:
@@ -82,8 +75,6 @@ function _fixLastStep(json: string, lastStep: JsonToken): string {
8275
return `${json}~~"`;
8376
case ARR_VAL_COMPLETED:
8477
return `${json},"~~"`;
85-
case ARR_COMMA:
86-
return `${json}"~~"`;
8778
}
8879

8980
return json;
Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,23 @@
11
export const OBJ = 'OBJ' as const;
22
export const OBJ_KEY = 'OBJ_KEY' as const;
33
export const OBJ_KEY_STR = 'OBJ_KEY_STR' as const;
4-
export const OBJ_COLON = 'OBJ_COLON' as const;
54
export const OBJ_VAL = 'OBJ_VAL' as const;
65
export const OBJ_VAL_STR = 'OBJ_VAL_STR' as const;
76
export const OBJ_VAL_COMPLETED = 'OBJ_VAL_COMPLETED' as const;
8-
export const OBJ_COMMA = 'OBJ_COMMA' as const;
97

108
export const ARR = 'ARR' as const;
119
export const ARR_VAL = 'ARR_VAL' as const;
1210
export const ARR_VAL_STR = 'ARR_VAL_STR' as const;
1311
export const ARR_VAL_COMPLETED = 'ARR_VAL_COMPLETED' as const;
14-
export const ARR_COMMA = 'ARR_COMMA' as const;
1512

1613
export type JsonToken =
1714
| typeof OBJ
1815
| typeof OBJ_KEY
1916
| typeof OBJ_KEY_STR
20-
| typeof OBJ_COLON
2117
| typeof OBJ_VAL
22-
| typeof OBJ_COMMA
2318
| typeof OBJ_VAL_STR
2419
| typeof OBJ_VAL_COMPLETED
2520
| typeof ARR
2621
| typeof ARR_VAL
2722
| typeof ARR_VAL_STR
28-
| typeof ARR_VAL_COMPLETED
29-
| typeof ARR_COMMA;
23+
| typeof ARR_VAL_COMPLETED;

packages/replay/src/util/truncateJson/evaluateJson.ts

Lines changed: 45 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
11
import type { JsonToken } from './constants';
22
import {
33
ARR,
4-
ARR_COMMA,
54
ARR_VAL,
65
ARR_VAL_COMPLETED,
76
ARR_VAL_STR,
87
OBJ,
9-
OBJ_COLON,
10-
OBJ_COMMA,
118
OBJ_KEY,
129
OBJ_KEY_STR,
1310
OBJ_VAL,
@@ -83,18 +80,10 @@ function _handleQuote(stack: JsonToken[], curStep: JsonToken): void {
8380

8481
// Start of obj value
8582
if (curStep === OBJ_VAL) {
86-
stack.pop();
8783
stack.push(OBJ_VAL_STR);
8884
return;
8985
}
9086

91-
// Start of arr value
92-
if (curStep === ARR_COMMA) {
93-
stack.pop();
94-
stack.push(ARR_VAL_STR);
95-
return;
96-
}
97-
9887
// Start of arr value
9988
if (curStep === ARR_VAL) {
10089
stack.push(ARR_VAL_STR);
@@ -106,11 +95,6 @@ function _handleQuote(stack: JsonToken[], curStep: JsonToken): void {
10695
stack.push(OBJ_KEY_STR);
10796
return;
10897
}
109-
if (curStep == OBJ_COMMA) {
110-
stack.pop();
111-
stack.push(OBJ_KEY_STR);
112-
return;
113-
}
11498

11599
// End of obj key
116100
if (curStep === OBJ_KEY_STR) {
@@ -177,7 +161,6 @@ function _handleArr(stack: JsonToken[], curStep: JsonToken): void {
177161
function _handleColon(stack: JsonToken[], curStep: JsonToken): void {
178162
if (curStep === OBJ_KEY) {
179163
stack.pop();
180-
stack.push(OBJ_COLON);
181164
stack.push(OBJ_VAL);
182165
}
183166
}
@@ -186,29 +169,26 @@ function _handleComma(stack: JsonToken[], curStep: JsonToken): void {
186169
// Comma after obj value
187170
if (curStep === OBJ_VAL) {
188171
stack.pop();
189-
stack.push(OBJ_COMMA);
190172
return;
191173
}
192174
if (curStep === OBJ_VAL_COMPLETED) {
175+
// Pop OBJ_VAL_COMPLETED & OBJ_VAL
193176
stack.pop();
194177
stack.pop();
195-
stack.push(OBJ_COMMA);
196178
return;
197179
}
198180

199181
// Comma after arr value
200182
if (curStep === ARR_VAL) {
201-
stack.pop();
202-
stack.push(ARR_COMMA);
203-
stack.push(ARR_VAL);
183+
// do nothing - basically we'd pop ARR_VAL but add it right back
204184
return;
205185
}
206186

207187
if (curStep === ARR_VAL_COMPLETED) {
188+
// Pop ARR_VAL_COMPLETED
208189
stack.pop();
209-
stack.pop();
210-
stack.push(ARR_COMMA);
211-
stack.push(ARR_VAL);
190+
191+
// basically we'd pop ARR_VAL but add it right back
212192
return;
213193
}
214194
}
@@ -217,46 +197,63 @@ function _handleObjClose(stack: JsonToken[], curStep: JsonToken): void {
217197
// Empty object {}
218198
if (curStep === OBJ) {
219199
stack.pop();
220-
return;
221200
}
222-
// End of object - pops OBJ_VAL_COMPLETED, OBJ_VAL, OBJ
223-
if (curStep === OBJ_VAL_COMPLETED) {
224-
stack.pop();
201+
202+
// Object with element
203+
if (curStep === OBJ_VAL) {
204+
// Pop OBJ_VAL, OBJ
225205
stack.pop();
226206
stack.pop();
227-
return;
228207
}
229-
// Pops OBJ_VAL, OBJ
230-
if (curStep === OBJ_VAL) {
208+
209+
// Obj with element
210+
if (curStep === OBJ_VAL_COMPLETED) {
211+
// Pop OBJ_VAL_COMPLETED, OBJ_VAL, OBJ
212+
stack.pop();
231213
stack.pop();
232214
stack.pop();
233-
return;
215+
}
216+
217+
// if was obj value, complete it
218+
if (stack[stack.length - 1] === OBJ_VAL) {
219+
stack.push(OBJ_VAL_COMPLETED);
220+
}
221+
222+
// if was arr value, complete it
223+
if (stack[stack.length - 1] === ARR_VAL) {
224+
stack.push(ARR_VAL_COMPLETED);
234225
}
235226
}
236227

237228
function _handleArrClose(stack: JsonToken[], curStep: JsonToken): void {
238-
// End of array - pops ARR_VAL_COMPLETED, ARR_VAL, ARR
239-
if (curStep === ARR_VAL_COMPLETED) {
229+
// Empty array []
230+
if (curStep === ARR) {
240231
stack.pop();
232+
}
233+
234+
// Array with element
235+
if (curStep === ARR_VAL) {
236+
// Pop ARR_VAL, ARR
241237
stack.pop();
242238
stack.pop();
243-
244-
// If we had ARR_COMMA in between, we have one more step to pop
245-
if (stack[stack.length - 1] === ARR) {
246-
stack.pop();
247-
}
248-
return;
249239
}
250-
// Pops ARR_VAL, ARR
251-
if (curStep === ARR_VAL) {
240+
241+
// Array with element
242+
if (curStep === ARR_VAL_COMPLETED) {
243+
// Pop ARR_VAL_COMPLETED, ARR_VAL, ARR
244+
stack.pop();
252245
stack.pop();
253246
stack.pop();
247+
}
254248

255-
// If we had ARR_COMMA in between, we have one more step to pop
256-
if (stack[stack.length - 1] === ARR) {
257-
stack.pop();
258-
}
259-
return;
249+
// if was obj value, complete it
250+
if (stack[stack.length - 1] === OBJ_VAL) {
251+
stack.push(OBJ_VAL_COMPLETED);
252+
}
253+
254+
// if was arr value, complete it
255+
if (stack[stack.length - 1] === ARR_VAL) {
256+
stack.push(ARR_VAL_COMPLETED);
260257
}
261258
}
262259

packages/replay/test/fixtures/fixJson/1_completeJson.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

packages/replay/test/fixtures/fixJson/1_incompleteJson.txt

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
[
2+
{
3+
"id": "123456",
4+
"email": "test.user@sentry.io",
5+
"name": "test.user@sentry.io",
6+
"user": {
7+
"id": "123456",
8+
"name": "test.user@sentry.io",
9+
"username": "ABCDEF",
10+
"email": "test.user@sentry.io",
11+
"isActive": true
12+
},
13+
"role": "member",
14+
"roleName": "Member",
15+
"orgRole": "member",
16+
"pending": false,
17+
"expired": false,
18+
"dateCreated": "2021-09-24T13:30:02.620935Z",
19+
"inviteStatus": "approved",
20+
"inviterName": null,
21+
"orgRolesFromTeams": [],
22+
"projects": ["feedback", "javascript", "sentry", "sentry-tests-acceptance~~"]}]
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
[
2+
{
3+
"id": "123456",
4+
"email": "test.user@sentry.io",
5+
"name": "test.user@sentry.io",
6+
"user": {
7+
"id": "123456",
8+
"name": "test.user@sentry.io",
9+
"username": "ABCDEF",
10+
"email": "test.user@sentry.io",
11+
"isActive": true
12+
},
13+
"role": "member",
14+
"roleName": "Member",
15+
"orgRole": "member",
16+
"pending": false,
17+
"expired": false,
18+
"dateCreated": "2021-09-24T13:30:02.620935Z",
19+
"inviteStatus": "approved",
20+
"inviterName": null,
21+
"orgRolesFromTeams": [],
22+
"projects": ["feedback", "javascript", "sentry", "sentry-tests-acceptance

packages/replay/test/unit/coreHandlers/util/truncateJson/fixJson.test.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import fs from 'fs';
2+
import path from 'path';
3+
14
import { fixJson } from '../../../../../src/util/truncateJson/fixJson';
25

36
describe('Unit | coreHandlers | util | truncateJson | fixJson', () => {
@@ -58,8 +61,22 @@ describe('Unit | coreHandlers | util | truncateJson | fixJson', () => {
5861
['{"a" : "aa', '{"a" : "aa~~"}'],
5962
['[1, 2, "a ", ', '[1, 2, "a ","~~"]'],
6063
['[1, 2, true ', '[1, 2, true ,"~~"]'],
64+
// Complex nested JSON
65+
['{"aa":{"bb":"yes","cc":true},"xx":["aa",1,true', '{"aa":{"bb":"yes","cc":true},"xx":["aa",1,true,"~~"]}'],
6166
])('it works for %s', (json, expected) => {
6267
const actual = fixJson(json);
6368
expect(actual).toEqual(expected);
6469
});
70+
71+
test.each(['1', '2'])('it works for fixture %s_incompleteJson.txt', fixture => {
72+
const input = fs
73+
.readFileSync(path.resolve(__dirname, `../../../../fixtures/fixJson/${fixture}_incompleteJson.txt`), 'utf8')
74+
.trim();
75+
const expected = fs
76+
.readFileSync(path.resolve(__dirname, `../../../../fixtures/fixJson/${fixture}_completeJson.json`), 'utf8')
77+
.trim();
78+
79+
const actual = fixJson(input);
80+
expect(actual).toEqual(expected);
81+
});
6582
});

0 commit comments

Comments
 (0)