Skip to content

Commit 56d33fa

Browse files
finalquestFernando Basello
andauthored
Handling strings (#2)
* feat: handling string args better We put a stringValidator so we can assure that strings args are put as string template literals Fixes #1 --------- Co-authored-by: Fernando Basello <fnbasello@gmail.com>
1 parent bab7dc7 commit 56d33fa

3 files changed

Lines changed: 262 additions & 0 deletions

File tree

src/index.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import HermesWorker from './NativeHermesWorker';
2+
import stringValidator from './stringValidator';
23

34
export function startProcessingThread(hbcFileName?: string): void {
45
HermesWorker.startProcessingThread(hbcFileName);
@@ -23,3 +24,12 @@ export function enqueueItem(item: string): Promise<string> {
2324
}
2425
});
2526
}
27+
28+
/**
29+
* Recursively ensures all string values in the parameter are properly quoted
30+
* @param param - The parameter to process
31+
* @returns The processed parameter with properly quoted strings
32+
*/
33+
export function assureStringParam(param: any): any {
34+
return stringValidator(param);
35+
}

src/stringValidator.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/**
2+
* Recursively ensures all string values in the parameter are properly escaped
3+
* by converting them to template literals
4+
* @param param - The parameter to process
5+
* @returns The processed parameter with properly escaped strings
6+
*/
7+
const stringValidator = (param: any): any => {
8+
// Handle null and undefined
9+
if (param === null || param === undefined) {
10+
return param;
11+
}
12+
13+
// Handle strings - convert to template literals
14+
if (typeof param === 'string') {
15+
return `\`${param}\``;
16+
}
17+
18+
// Handle arrays - process each element
19+
if (Array.isArray(param)) {
20+
return param.map((item) => stringValidator(item));
21+
}
22+
23+
// Handle Maps
24+
if (param instanceof Map) {
25+
const newMap = new Map();
26+
for (const [key, value] of param.entries()) {
27+
newMap.set(
28+
typeof key === 'string' ? `\`${key}\`` : key,
29+
stringValidator(value)
30+
);
31+
}
32+
return newMap;
33+
}
34+
35+
// Handle plain objects (not null, functions, or other non-objects)
36+
if (typeof param === 'object' && param.constructor === Object) {
37+
const result: Record<string, any> = {};
38+
for (const key in param) {
39+
if (Object.prototype.hasOwnProperty.call(param, key)) {
40+
result[key] = stringValidator(param[key]);
41+
}
42+
}
43+
return result;
44+
}
45+
46+
// Return other types unchanged (numbers, booleans, functions, etc.)
47+
return param;
48+
};
49+
50+
export default stringValidator;

src/tests/stringValidator.test.ts

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
import validateStringParam from '../stringValidator';
2+
3+
describe('validateStringParam', () => {
4+
test('should handle null and undefined', () => {
5+
expect(validateStringParam(null)).toBeNull();
6+
expect(validateStringParam(undefined)).toBeUndefined();
7+
});
8+
9+
test('should convert strings to template literals', () => {
10+
expect(validateStringParam('hello')).toBe('`hello`');
11+
expect(validateStringParam('')).toBe('``');
12+
});
13+
14+
test('should handle nested strings in arrays', () => {
15+
const input = ['a', 123, 'b'];
16+
const expected = ['`a`', 123, '`b`'];
17+
expect(validateStringParam(input)).toEqual(expected);
18+
});
19+
20+
test('should handle multi-dimensional arrays', () => {
21+
const input = [
22+
['a', 'b'],
23+
['c', 'd'],
24+
];
25+
const expected = [
26+
['`a`', '`b`'],
27+
['`c`', '`d`'],
28+
];
29+
expect(validateStringParam(input)).toEqual(expected);
30+
});
31+
32+
test('should handle objects with string values', () => {
33+
const input = { name: 'John', age: 30 };
34+
const expected = { name: '`John`', age: 30 };
35+
expect(validateStringParam(input)).toEqual(expected);
36+
});
37+
38+
test('should handle nested objects', () => {
39+
const input = {
40+
user: {
41+
name: 'John',
42+
contact: {
43+
email: 'john@example.com',
44+
phone: 123456,
45+
},
46+
},
47+
active: true,
48+
};
49+
50+
const expected = {
51+
user: {
52+
name: '`John`',
53+
contact: {
54+
email: '`john@example.com`',
55+
phone: 123456,
56+
},
57+
},
58+
active: true,
59+
};
60+
61+
expect(validateStringParam(input)).toEqual(expected);
62+
});
63+
64+
test('should handle arrays inside objects', () => {
65+
const input = {
66+
names: ['John', 'Jane'],
67+
ages: [30, 25],
68+
};
69+
70+
const expected = {
71+
names: ['`John`', '`Jane`'],
72+
ages: [30, 25],
73+
};
74+
75+
expect(validateStringParam(input)).toEqual(expected);
76+
});
77+
78+
test('should handle objects inside arrays', () => {
79+
const input = [
80+
{ name: 'John', age: 30 },
81+
{ name: 'Jane', age: 25 },
82+
];
83+
84+
const expected = [
85+
{ name: '`John`', age: 30 },
86+
{ name: '`Jane`', age: 25 },
87+
];
88+
89+
expect(validateStringParam(input)).toEqual(expected);
90+
});
91+
92+
test('should handle Map objects', () => {
93+
const input = new Map();
94+
input.set('name', 'John');
95+
input.set('age', 30);
96+
input.set(123, 'value');
97+
98+
const expected = new Map();
99+
expected.set('`name`', '`John`');
100+
expected.set('`age`', 30);
101+
expected.set(123, '`value`');
102+
103+
expect(validateStringParam(input)).toEqual(expected);
104+
});
105+
106+
test('should not modify non-string primitives', () => {
107+
expect(validateStringParam(123)).toBe(123);
108+
expect(validateStringParam(true)).toBe(true);
109+
expect(validateStringParam(false)).toBe(false);
110+
expect(validateStringParam(0)).toBe(0);
111+
});
112+
113+
test('should handle functions without modification', () => {
114+
const fn = () => 'Hello';
115+
expect(validateStringParam(fn)).toBe(fn);
116+
});
117+
118+
test('should handle strings with quotes', () => {
119+
expect(validateStringParam('hello "world"')).toBe('`hello "world"`');
120+
expect(validateStringParam("don't do that")).toBe("`don't do that`");
121+
expect(validateStringParam('mix of "double" and \'single\' quotes')).toBe(
122+
'`mix of "double" and \'single\' quotes`'
123+
);
124+
});
125+
126+
test('should handle strings with backticks', () => {
127+
// Since we're using backticks as delimiters, any backticks within the string would need special handling
128+
// In this case, we're assuming the function doesn't do any escaping
129+
expect(validateStringParam('code: `const x = 1;`')).toBe(
130+
'`code: `const x = 1;``'
131+
);
132+
// In a real implementation, you might want to escape backticks in the input string
133+
});
134+
135+
test('should handle strings with special characters', () => {
136+
expect(validateStringParam('line1\nline2')).toBe('`line1\nline2`');
137+
expect(validateStringParam('tab\tcharacter')).toBe('`tab\tcharacter`');
138+
expect(validateStringParam('\u2022 bullet point')).toBe(
139+
'`\u2022 bullet point`'
140+
);
141+
});
142+
143+
test('should handle complex nested structures', () => {
144+
const input = {
145+
users: [
146+
{
147+
name: 'John',
148+
contact: {
149+
email: 'john@example.com',
150+
addresses: [
151+
{ street: 'Main St', number: 123 },
152+
{ street: 'Second Ave', number: 456 },
153+
],
154+
},
155+
},
156+
{
157+
name: 'Jane',
158+
contact: {
159+
email: 'jane@example.com',
160+
addresses: [{ street: 'Park Rd', number: 789 }],
161+
},
162+
},
163+
],
164+
company: 'Acme Inc',
165+
active: true,
166+
stats: {
167+
employees: 50,
168+
founded: '2010',
169+
},
170+
};
171+
172+
const expected = {
173+
users: [
174+
{
175+
name: '`John`',
176+
contact: {
177+
email: '`john@example.com`',
178+
addresses: [
179+
{ street: '`Main St`', number: 123 },
180+
{ street: '`Second Ave`', number: 456 },
181+
],
182+
},
183+
},
184+
{
185+
name: '`Jane`',
186+
contact: {
187+
email: '`jane@example.com`',
188+
addresses: [{ street: '`Park Rd`', number: 789 }],
189+
},
190+
},
191+
],
192+
company: '`Acme Inc`',
193+
active: true,
194+
stats: {
195+
employees: 50,
196+
founded: '`2010`',
197+
},
198+
};
199+
200+
expect(validateStringParam(input)).toEqual(expected);
201+
});
202+
});

0 commit comments

Comments
 (0)