Skip to content

Commit 9a358c7

Browse files
committed
Expand unesc handling to correctly handle spec edgease for lone
surrogates and out of bound codepoint values.
1 parent 5ae0402 commit 9a358c7

File tree

2 files changed

+22
-1
lines changed

2 files changed

+22
-1
lines changed

src/__tests__/util/unesc.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,15 @@ test('class selector with escaping', '.\\1D306', (t, tree) => {
4444
test('class selector with escaping with more chars', '.\\1D306k', (t, tree) => {
4545
t.deepEqual(tree.nodes[0].nodes[0].value, '𝌆k');
4646
});
47+
48+
test('handles 0 value hex', '\\0', (t, tree) => {
49+
t.deepEqual(tree.nodes[0].nodes[0].value, String.fromCodePoint(0xFFFD));
50+
});
51+
52+
test('handles lone surrogate value hex', '\\DBFF', (t, tree) => {
53+
t.deepEqual(tree.nodes[0].nodes[0].value, String.fromCodePoint(0xFFFD));
54+
});
55+
56+
test('handles out of bound values', '\\110000', (t, tree) => {
57+
t.deepEqual(tree.nodes[0].nodes[0].value, String.fromCodePoint(0xFFFD));
58+
});

src/util/unesc.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,18 @@ function gobbleHex (str) {
2525
if (hex.length === 0) {
2626
return undefined;
2727
}
28+
const codePoint = parseInt(hex, 16);
29+
30+
const isSurrogate = codePoint >= 0xD800 && codePoint <= 0xDFFF;
31+
// Add special case for
32+
// "If this number is zero, or is for a surrogate, or is greater than the maximum allowed code point"
33+
// https://drafts.csswg.org/css-syntax/#maximum-allowed-code-point
34+
if (isSurrogate || codePoint === 0x0000 || codePoint > 0x10FFFF) {
35+
return ['\uFFFD', hex.length + (spaceTerminated ? 1 : 0)];
36+
}
2837

2938
return [
30-
String.fromCodePoint(parseInt(hex, 16)),
39+
String.fromCodePoint(codePoint),
3140
hex.length + (spaceTerminated ? 1 : 0),
3241
];
3342
}

0 commit comments

Comments
 (0)