Skip to content

Commit 7b72a8c

Browse files
committed
url,lib: pass urlsearchparams-constructor.any.js
According to WPT: 1. `URLSearchParams` constructor should throw exactly `TypeError` if any Error occurrs. 2. When a record passed to `URLSearchParams` constructor, two different key may result same after `toUVString()`. We should leave only the later one.
1 parent b63e449 commit 7b72a8c

File tree

4 files changed

+42
-15
lines changed

4 files changed

+42
-15
lines changed

lib/internal/per_context/domexception.js

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,33 @@ const {
1010
TypeError,
1111
} = primordials;
1212

13-
class ERR_INVALID_THIS extends TypeError {
14-
constructor(type) {
15-
super('Value of "this" must be of ' + type);
16-
}
17-
18-
get code() { return 'ERR_INVALID_THIS'; }
19-
}
20-
2113
let internalsMap;
2214
let nameToCodeMap;
2315
let isInitialized = false;
2416

17+
function throwInvalidThisError(Base, type) {
18+
const err = new Base();
19+
const key = 'ERR_INVALID_THIS';
20+
ObjectDefineProperties(err, {
21+
message: {
22+
value: `Value of "this" must be of ${type}`,
23+
enumerable: false,
24+
writable: true,
25+
configurable: true,
26+
},
27+
toString: {
28+
value() {
29+
return `${this.name} [${key}]: ${this.message}`;
30+
},
31+
enumerable: false,
32+
writable: true,
33+
configurable: true,
34+
},
35+
});
36+
err.code = key;
37+
throw err;
38+
}
39+
2540
// We need to instantiate the maps lazily because they render
2641
// the snapshot non-rehashable.
2742
// https://bugs.chromium.org/p/v8/issues/detail?id=6593
@@ -51,7 +66,7 @@ class DOMException extends Error {
5166
ensureInitialized();
5267
const internals = internalsMap.get(this);
5368
if (internals === undefined) {
54-
throw new ERR_INVALID_THIS('DOMException');
69+
throwInvalidThisError(TypeError, 'DOMException');
5570
}
5671
return internals.name;
5772
}
@@ -60,7 +75,7 @@ class DOMException extends Error {
6075
ensureInitialized();
6176
const internals = internalsMap.get(this);
6277
if (internals === undefined) {
63-
throw new ERR_INVALID_THIS('DOMException');
78+
throwInvalidThisError(TypeError, 'DOMException');
6479
}
6580
return internals.message;
6681
}
@@ -69,7 +84,7 @@ class DOMException extends Error {
6984
ensureInitialized();
7085
const internals = internalsMap.get(this);
7186
if (internals === undefined) {
72-
throw new ERR_INVALID_THIS('DOMException');
87+
throwInvalidThisError(TypeError, 'DOMException');
7388
}
7489
const code = nameToCodeMap.get(internals.name);
7590
return code === undefined ? 0 : code;

lib/internal/url.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ class URLSearchParams {
219219
} else {
220220
// Record<USVString, USVString>
221221
// Need to use reflection APIs for full spec compliance.
222+
const visited = {};
222223
this[searchParams] = [];
223224
const keys = ReflectOwnKeys(init);
224225
for (let i = 0; i < keys.length; i++) {
@@ -227,7 +228,15 @@ class URLSearchParams {
227228
if (desc !== undefined && desc.enumerable) {
228229
const typedKey = toUSVString(key);
229230
const typedValue = toUSVString(init[key]);
230-
this[searchParams].push(typedKey, typedValue);
231+
232+
// Two different key may result same after `toUSVString()`, we only
233+
// leave the later one. Refers to WPT.
234+
if (visited[typedKey] !== undefined) {
235+
this[searchParams][visited[typedKey]] = typedValue;
236+
} else {
237+
this[searchParams].push(typedKey, typedValue);
238+
visited[typedKey] = this[searchParams].length - 1;
239+
}
231240
}
232241
}
233242
}

test/wpt/status/url.json

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,6 @@
1212
"urlencoded-parser.any.js": {
1313
"fail": "missing Request and Response"
1414
},
15-
"urlsearchparams-constructor.any.js": {
16-
"fail": "FormData is not defined"
17-
},
1815
"url-constructor.any.js": {
1916
"requires": ["small-icu"]
2017
},

test/wpt/test-url.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@ runner.setScriptModifier((obj) => {
1111
// created via `document.createElement`. So we need to ignore them and just
1212
// test `URL`.
1313
obj.code = obj.code.replace(/\["url", "a", "area"\]/, '[ "url" ]');
14+
} else if (obj.filename.includes('urlsearchparams-constructor.any.js')) {
15+
// Ignore test named `URLSearchParams constructor, FormData.` because we do
16+
// not have `FormData`.
17+
obj.code = obj.code.replace(
18+
/('URLSearchParams constructor, object\.'\);[\w\W]+)test\(function\(\) {[\w\W]*?}, 'URLSearchParams constructor, FormData\.'\);/,
19+
'$1');
1420
}
1521
});
1622
runner.pretendGlobalThisAs('Window');

0 commit comments

Comments
 (0)