Skip to content

Commit eb5e9b1

Browse files
srmarjanimcollina
authored andcommitted
well formed unicode string (#147) (#151)
* surrogate is detected and defered to JSON.stringify() * remove console log from test * for lone and unpair surrogate mirror test used
1 parent c97fd71 commit eb5e9b1

File tree

2 files changed

+74
-1
lines changed

2 files changed

+74
-1
lines changed

index.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,16 +236,22 @@ function $asString (str) {
236236
// magically escape strings for json
237237
// relying on their charCodeAt
238238
// everything below 32 needs JSON.stringify()
239+
// every string that contain surrogate needs JSON.stringify()
239240
// 34 and 92 happens all the time, so we
240241
// have a fast case for them
241242
function $asStringSmall (str) {
242243
var result = ''
243244
var last = 0
244245
var found = false
246+
var surrogateFound = false
245247
var l = str.length
246248
var point = 255
247249
for (var i = 0; i < l && point >= 32; i++) {
248250
point = str.charCodeAt(i)
251+
if (point >= 0xD800 && point <= 0xDFFF) {
252+
// The current character is a surrogate.
253+
surrogateFound = true
254+
}
249255
if (point === 34 || point === 92) {
250256
result += str.slice(last, i) + '\\'
251257
last = i
@@ -258,7 +264,7 @@ function $asStringSmall (str) {
258264
} else {
259265
result += str.slice(last)
260266
}
261-
return point < 32 ? JSON.stringify(str) : '"' + result + '"'
267+
return ((point < 32) || (surrogateFound === true)) ? JSON.stringify(str) : '"' + result + '"'
262268
}
263269

264270
function addPatternProperties (schema, externalSchema, fullSchema) {

test/surrogate.test.js

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
'use strict'
2+
3+
const test = require('tap').test
4+
const validator = require('is-my-json-valid')
5+
const build = require('..')
6+
7+
test(`render a string with surrogate pairs as JSON:test 1`, (t) => {
8+
t.plan(2)
9+
10+
const schema = {
11+
title: 'surrogate',
12+
type: 'string'
13+
}
14+
15+
const validate = validator(schema)
16+
const stringify = build(schema)
17+
const output = stringify('𝌆')
18+
19+
t.equal(output, '"𝌆"')
20+
t.ok(validate(JSON.parse(output)), 'valid schema')
21+
})
22+
23+
test(`render a string with surrogate pairs as JSON: test 2`, (t) => {
24+
t.plan(2)
25+
26+
const schema = {
27+
title: 'long',
28+
type: 'string'
29+
}
30+
31+
const validate = validator(schema)
32+
const stringify = build(schema)
33+
const output = stringify('\uD834\uDF06')
34+
35+
t.equal(output, '"𝌆"')
36+
t.ok(validate(JSON.parse(output)), 'valid schema')
37+
})
38+
39+
test(`render a string with Unpaired surrogate code as JSON`, (t) => {
40+
t.plan(2)
41+
42+
const schema = {
43+
title: 'surrogate',
44+
type: 'string'
45+
}
46+
47+
const validate = validator(schema)
48+
const stringify = build(schema)
49+
const output = stringify('\uDF06\uD834')
50+
t.equal(output, JSON.stringify('\uDF06\uD834'))
51+
t.ok(validate(JSON.parse(output)), 'valid schema')
52+
})
53+
54+
test(`render a string with lone surrogate code as JSON`, (t) => {
55+
t.plan(2)
56+
57+
const schema = {
58+
title: 'surrogate',
59+
type: 'string'
60+
}
61+
62+
const validate = validator(schema)
63+
const stringify = build(schema)
64+
const output = stringify('\uDEAD')
65+
t.equal(output, JSON.stringify('\uDEAD'))
66+
t.ok(validate(JSON.parse(output)), 'valid schema')
67+
})

0 commit comments

Comments
 (0)