Skip to content

Commit 5c6c988

Browse files
committed
Expand unesc handling to correctly handle spec edgecase for lone
surrogates and out of bound codepoint values.
1 parent 13b613d commit 5c6c988

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
@@ -48,3 +48,15 @@ test('class selector with escaping with more chars', '.\\1D306k', (t, tree) => {
4848
test('class selector with escaping with more chars with whitespace', '.wow\\1D306 k', (t, tree) => {
4949
t.deepEqual(tree.nodes[0].nodes[0].value, 'wow𝌆k');
5050
});
51+
52+
test('handles 0 value hex', '\\0', (t, tree) => {
53+
t.deepEqual(tree.nodes[0].nodes[0].value, String.fromCodePoint(0xFFFD));
54+
});
55+
56+
test('handles lone surrogate value hex', '\\DBFF', (t, tree) => {
57+
t.deepEqual(tree.nodes[0].nodes[0].value, String.fromCodePoint(0xFFFD));
58+
});
59+
60+
test('handles out of bound values', '\\110000', (t, tree) => {
61+
t.deepEqual(tree.nodes[0].nodes[0].value, String.fromCodePoint(0xFFFD));
62+
});

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)