Skip to content
This repository was archived by the owner on Jun 24, 2022. It is now read-only.

Commit 6b952c8

Browse files
[WebIDL] convertRecord() should handle duplicate keys for USVString records
https://bugs.webkit.org/show_bug.cgi?id=217612 Reviewed by Sam Weinig. LayoutTests/imported/w3c: * web-platform-tests/url/urlsearchparams-constructor.any-expected.txt: * web-platform-tests/url/urlsearchparams-constructor.any.js: * web-platform-tests/url/urlsearchparams-constructor.any.worker-expected.txt: Source/WebCore: Before this patch, due to unpaired surrogates replacement in stringToUSVString(), convertRecord() could append the same key multiple times, violating the spec [1]. This change adds duplicate handling while preserving common case performance, and aligns WebKit with Blink and Gecko. Since a Proxy object can no longer return duplicate keys [2], only USVString records needed to be fixed. Test: imported/w3c/web-platform-tests/url/urlsearchparams-constructor.any.html [1] https://heycam.github.io/webidl/#es-record (step 4.2.4 + example below) [2] tc39/ecma262#833 * bindings/js/JSDOMConvertRecord.h: git-svn-id: http://svn.webkit.org/repository/webkit/trunk@268709 268f45cc-cd09-0410-ab3c-d52691b4dbfc
1 parent 806592d commit 6b952c8

File tree

6 files changed

+49
-4
lines changed

6 files changed

+49
-4
lines changed

LayoutTests/imported/w3c/ChangeLog

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
2020-10-19 Alexey Shvayka <[email protected]>
2+
3+
[WebIDL] convertRecord() should handle duplicate keys for USVString records
4+
https://bugs.webkit.org/show_bug.cgi?id=217612
5+
6+
Reviewed by Sam Weinig.
7+
8+
* web-platform-tests/url/urlsearchparams-constructor.any-expected.txt:
9+
* web-platform-tests/url/urlsearchparams-constructor.any.js:
10+
* web-platform-tests/url/urlsearchparams-constructor.any.worker-expected.txt:
11+
112
2020-10-19 Antti Koivisto <[email protected]>
213

314
Update imported/w3c/web-platform-tests/css/selectors/

LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-constructor.any-expected.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ PASS Constructor with sequence of sequences of strings
2222
PASS Construct with object with +
2323
PASS Construct with object with two keys
2424
PASS Construct with array with two keys
25+
PASS Construct with 2 unpaired surrogates (no trailing)
26+
PASS Construct with 3 unpaired surrogates (no leading)
2527
PASS Construct with object with NULL, non-ASCII, and surrogate keys
2628
PASS Custom [Symbol.iterator]
2729

LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-constructor.any.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,8 @@ test(function() {
200200
{ "input": {"+": "%C2"}, "output": [["+", "%C2"]], "name": "object with +" },
201201
{ "input": {c: "x", a: "?"}, "output": [["c", "x"], ["a", "?"]], "name": "object with two keys" },
202202
{ "input": [["c", "x"], ["a", "?"]], "output": [["c", "x"], ["a", "?"]], "name": "array with two keys" },
203+
{ "input": {"\uD835x": "1", "xx": "2", "\uD83Dx": "3"}, "output": [["\uFFFDx", "3"], ["xx", "2"]], "name": "2 unpaired surrogates (no trailing)" },
204+
{ "input": {"x\uDC53": "1", "x\uDC5C": "2", "x\uDC65": "3"}, "output": [["x\uFFFD", "3"]], "name": "3 unpaired surrogates (no leading)" },
203205
{ "input": {"a\0b": "42", "c\uD83D": "23", "d\u1234": "foo"}, "output": [["a\0b", "42"], ["c\uFFFD", "23"], ["d\u1234", "foo"]], "name": "object with NULL, non-ASCII, and surrogate keys" }
204206
].forEach((val) => {
205207
test(() => {

LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-constructor.any.worker-expected.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ PASS Constructor with sequence of sequences of strings
2222
PASS Construct with object with +
2323
PASS Construct with object with two keys
2424
PASS Construct with array with two keys
25+
PASS Construct with 2 unpaired surrogates (no trailing)
26+
PASS Construct with 3 unpaired surrogates (no leading)
2527
PASS Construct with object with NULL, non-ASCII, and surrogate keys
2628
PASS Custom [Symbol.iterator]
2729

Source/WebCore/ChangeLog

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,24 @@
1+
2020-10-19 Alexey Shvayka <[email protected]>
2+
3+
[WebIDL] convertRecord() should handle duplicate keys for USVString records
4+
https://bugs.webkit.org/show_bug.cgi?id=217612
5+
6+
Reviewed by Sam Weinig.
7+
8+
Before this patch, due to unpaired surrogates replacement in stringToUSVString(),
9+
convertRecord() could append the same key multiple times, violating the spec [1].
10+
11+
This change adds duplicate handling while preserving common case performance,
12+
and aligns WebKit with Blink and Gecko. Since a Proxy object can no longer return
13+
duplicate keys [2], only USVString records needed to be fixed.
14+
15+
Test: imported/w3c/web-platform-tests/url/urlsearchparams-constructor.any.html
16+
17+
[1] https://heycam.github.io/webidl/#es-record (step 4.2.4 + example below)
18+
[2] https://github.com/tc39/ecma262/pull/833
19+
20+
* bindings/js/JSDOMConvertRecord.h:
21+
122
2020-10-19 Wenson Hsieh <[email protected]>
223

324
[MotionMark] Add state change items to represent changes to stroke and fill state

Source/WebCore/bindings/js/JSDOMConvertRecord.h

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -127,11 +127,18 @@ template<typename K, typename V> struct Converter<IDLRecord<K, V>> : DefaultConv
127127
auto typedValue = Converter<V>::convert(lexicalGlobalObject, subValue, args...);
128128
RETURN_IF_EXCEPTION(scope, { });
129129

130-
// 4. If typedKey is already a key in result, set its value to typedValue.
131-
// Note: This can happen when O is a proxy object.
132-
// FIXME: Handle this case.
130+
// 4. Set result[typedKey] to typedValue.
131+
// Note: It's possible that typedKey is already in result if K is USVString and key contains unpaired surrogates.
132+
if constexpr (std::is_same_v<K, IDLUSVString>) {
133+
if (!typedKey.is8Bit()) {
134+
auto index = result.findMatching([&](auto& entry) { return entry.key == typedKey; });
135+
if (index != notFound) {
136+
result[index].value = typedValue;
137+
continue;
138+
}
139+
}
140+
}
133141

134-
// 5. Otherwise, append to result a mapping (typedKey, typedValue).
135142
result.append({ typedKey, typedValue });
136143
}
137144
}

0 commit comments

Comments
 (0)