Skip to content

Commit 801727d

Browse files
fix(data-connect): correctly serialize strings with special characters (#3056)
Replaces manual string escaping with JSON.stringify in DataConnect API client to properly handle newlines and other control characters in mutation arguments. Adds a regression test for verifying newline escaping. Fixes #3043 --------- Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> Co-authored-by: Yuchen Shi <yuchenshi@google.com>
1 parent e2e5f0d commit 801727d

File tree

2 files changed

+58
-4
lines changed

2 files changed

+58
-4
lines changed

src/data-connect/data-connect-api-client-internal.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -413,10 +413,7 @@ export class DataConnectApiClient {
413413
*/
414414
private objectToString(data: unknown): string {
415415
if (typeof data === 'string') {
416-
const escapedString = data
417-
.replace(/\\/g, '\\\\') // Replace \ with \\
418-
.replace(/"/g, '\\"'); // Replace " with \"
419-
return `"${escapedString}"`;
416+
return JSON.stringify(data);
420417
}
421418
if (typeof data === 'number' || typeof data === 'boolean' || data === null) {
422419
return String(data);

test/unit/data-connect/data-connect-api-client-internal.spec.ts

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -928,4 +928,61 @@ describe('DataConnectApiClient CRUD helpers', () => {
928928
.to.be.rejectedWith(FirebaseDataConnectError, `${serverErrorString}. ${additionalErrorMessageForBulkImport}`);
929929
});
930930
});
931+
932+
describe('String serialization', () => {
933+
it('should correctly escape special characters in strings during insert', async () => {
934+
const data = {
935+
content: 'Line 1\nLine 2',
936+
};
937+
938+
await apiClient.insert(tableName, data);
939+
const callArgs = executeGraphqlStub.firstCall.args[0];
940+
941+
expect(callArgs).to.include(String.raw`content: "Line 1\nLine 2"`);
942+
});
943+
944+
it('should correctly escape backslash', async () => {
945+
const data = {
946+
content: 'Backslash \\',
947+
};
948+
949+
await apiClient.insert(tableName, data);
950+
const callArgs = executeGraphqlStub.firstCall.args[0];
951+
952+
expect(callArgs).to.include(String.raw`content: "Backslash \\"`);
953+
});
954+
955+
it('should correctly escape double quotes', async () => {
956+
const data = {
957+
content: 'Quote "test"',
958+
};
959+
960+
await apiClient.insert(tableName, data);
961+
const callArgs = executeGraphqlStub.firstCall.args[0];
962+
963+
expect(callArgs).to.include(String.raw`content: "Quote \"test\""`);
964+
});
965+
966+
it('should correctly escape tab character', async () => {
967+
const data = {
968+
content: 'Tab\tCharacter',
969+
};
970+
971+
await apiClient.insert(tableName, data);
972+
const callArgs = executeGraphqlStub.firstCall.args[0];
973+
974+
expect(callArgs).to.include(String.raw`content: "Tab\tCharacter"`);
975+
});
976+
977+
it('should correctly handle emojis', async () => {
978+
const data = {
979+
content: 'Emoji 😊',
980+
};
981+
982+
await apiClient.insert(tableName, data);
983+
const callArgs = executeGraphqlStub.firstCall.args[0];
984+
985+
expect(callArgs).to.include('content: "Emoji 😊"');
986+
});
987+
});
931988
});

0 commit comments

Comments
 (0)