Skip to content

Commit

Permalink
Made JSON.stringify comptible with javascript JSON (#266)
Browse files Browse the repository at this point in the history
* Made JSON.stringify comptible with javascript JSON

The current JSON.stringify method escaped characters in a way that
was NOT compatible with the current javascript JSON implementation.
For example, the string single-character "\n" was being translated
into:

"\"\
\""

Instead of being stringifyed as: "\"\n\"". This is because the
character \n was being added, instead of adding an "n" preceeded
by an "\\".

* Formatting assembly/JSON.ts

Co-authored-by: Max Graey <[email protected]>
Co-authored-by: Willem Wyndham <[email protected]>
  • Loading branch information
3 people authored Aug 6, 2021
1 parent 71df6f7 commit 1edab43
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 37 deletions.
31 changes: 20 additions & 11 deletions assembly/JSON.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,25 +182,34 @@ export abstract class Value {
}
}

function escapeChar(char: string): string {
const charCode = char.charCodeAt(0);
switch (charCode) {
case 0x22: return '\\"';
case 0x5C: return "\\\\";
case 0x08: return "\\b";
case 0x0A: return "\\n";
case 0x0D: return "\\r";
case 0x09: return "\\t";
case 0x0C: return "\\f";
case 0x0B: return "\\u000b";
default: return char;
}
}

export class Str extends Value {

constructor(public _str: string) {
super();
}

stringify(): string {
let escaped: i32[] = [];
let escaped: string[] = new Array(this._str.length);
for (let i = 0; i < this._str.length; i++) {
const charCode = this._str.charCodeAt(i);
if (
charCode == 0x22 || // " quotation mark U+0022
charCode == 0x5C || // \ reverse solidus U+005C
charCode < 0x20 // control characters
) {
escaped.push(0x5c); // add a reverse solidus (backslash) to escape reserved chars
}
escaped.push(charCode);
const char = this._str.at(i);
escaped[i] = escapeChar(char);
}
return "\"" + String.fromCharCodes(escaped) + "\"";
return `"${escaped.join('')}"`;
}

toString(): string {
Expand Down
43 changes: 17 additions & 26 deletions assembly/__tests__/string_escape.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,38 +16,29 @@ describe('Escaped characters', () => {
];
strings.forEach((str) => {
const jsonStr = new JSON.Str(str);
expect(jsonStr.stringify()).toBe('"' + str + '"');
expect(jsonStr.stringify()).toBe(`"${str}"`);
});
});

it('Escapes quotes and backslashes', () => {
const strings = ['"', '\\', '"\\"', '\\"\\"'];
strings.forEach((str) => {
const jsonStr = new JSON.Str(str);
expect(jsonStr.stringify()).toBe('"' + escaped(str) + '"');
});
// Computed using javascript's JSON as implemented in mozilla firefox 90.0 (64-bit)
const expected = ["\"\\\"\"", "\"\\\\\"", "\"\\\"\\\\\\\"\"", "\"\\\\\\\"\\\\\\\"\""];

for(let i=0; i<strings.length; i++){
const jsonStr = new JSON.Str(strings[i]);
expect(jsonStr.stringify()).toBe(expected[i]);
}
});

it('Escapes control characters', () => {
const strings = ['\n', '\r', '\r\n', '\b', '\f', '\t', '\v', '\b\f\t\v\r'];
strings.forEach((str) => {
const jsonStr = new JSON.Str(str);
expect(jsonStr.stringify()).toBe('"' + escaped(str) + '"');
});
});
});
// Computed using javascript's JSON as implemented in mozilla firefox 90.0 (64-bit)
const expected = ["\"\\n\"","\"\\r\"","\"\\r\\n\"","\"\\b\"","\"\\f\"","\"\\t\"","\"\\u000b\"","\"\\b\\f\\t\\u000b\\r\""];

function escaped(str: string): string {
const escapedChars: i32[] = [];
for (let i = 0; i < str.length; i++) {
const charCode = str.charCodeAt(i);
if (
charCode < 0x20 || // control characters
charCode == 0x22 || // double quote (")
charCode == 0x5c
) {
// backslash / reverse solidus (\)
escapedChars.push(0x5c);
for(let i=0; i<strings.length; i++){
const jsonStr = new JSON.Str(strings[i]);
expect(jsonStr.stringify()).toBe(expected[i]);
}
escapedChars.push(charCode);
}
return String.fromCharCodes(escapedChars);
}
});
});

0 comments on commit 1edab43

Please sign in to comment.