Skip to content

Commit

Permalink
url,lib: pass urlsearchparams-constructor.any.js
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
XadillaX committed Dec 20, 2021
1 parent b63e449 commit c0a9720
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 13 deletions.
33 changes: 24 additions & 9 deletions lib/internal/per_context/domexception.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,27 @@ const {
TypeError,
} = primordials;

class ERR_INVALID_THIS extends TypeError {
constructor(type) {
super('Value of "this" must be of ' + type);
}

get code() { return 'ERR_INVALID_THIS'; }
function throwInvalidThisError(Base, type) {
const err = new Base();
const key = 'ERR_INVALID_THIS';
ObjectDefineProperties(err, {
message: {
value: `Value of "this" must be of ${type}`,
enumerable: false,
writable: true,
configurable: true,
},
toString: {
value() {
return `${this.name} [${key}]: ${this.message}`;
},
enumerable: false,
writable: true,
configurable: true,
},
});
err.code = key;
throw err;
}

let internalsMap;
Expand Down Expand Up @@ -51,7 +66,7 @@ class DOMException extends Error {
ensureInitialized();
const internals = internalsMap.get(this);
if (internals === undefined) {
throw new ERR_INVALID_THIS('DOMException');
throwInvalidThisError(TypeError, 'DOMException');
}
return internals.name;
}
Expand All @@ -60,7 +75,7 @@ class DOMException extends Error {
ensureInitialized();
const internals = internalsMap.get(this);
if (internals === undefined) {
throw new ERR_INVALID_THIS('DOMException');
throwInvalidThisError(TypeError, 'DOMException');
}
return internals.message;
}
Expand All @@ -69,7 +84,7 @@ class DOMException extends Error {
ensureInitialized();
const internals = internalsMap.get(this);
if (internals === undefined) {
throw new ERR_INVALID_THIS('DOMException');
throwInvalidThisError(TypeError, 'DOMException');
}
const code = nameToCodeMap.get(internals.name);
return code === undefined ? 0 : code;
Expand Down
11 changes: 10 additions & 1 deletion lib/internal/url.js
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ class URLSearchParams {
} else {
// Record<USVString, USVString>
// Need to use reflection APIs for full spec compliance.
const visited = {};
this[searchParams] = [];
const keys = ReflectOwnKeys(init);
for (let i = 0; i < keys.length; i++) {
Expand All @@ -227,7 +228,15 @@ class URLSearchParams {
if (desc !== undefined && desc.enumerable) {
const typedKey = toUSVString(key);
const typedValue = toUSVString(init[key]);
this[searchParams].push(typedKey, typedValue);

// Two different key may result same after `toUSVString()`, we only
// leave the later one. Refers to WPT.
if (visited[typedKey] !== undefined) {
this[searchParams][visited[typedKey]] = typedValue;
} else {
visited[typedKey] = this[searchParams].push(typedKey,
typedValue) - 1;
}
}
}
}
Expand Down
3 changes: 0 additions & 3 deletions test/wpt/status/url.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@
"urlencoded-parser.any.js": {
"fail": "missing Request and Response"
},
"urlsearchparams-constructor.any.js": {
"fail": "FormData is not defined"
},
"url-constructor.any.js": {
"requires": ["small-icu"]
},
Expand Down
9 changes: 9 additions & 0 deletions test/wpt/test-url.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,15 @@ runner.setScriptModifier((obj) => {
// created via `document.createElement`. So we need to ignore them and just
// test `URL`.
obj.code = obj.code.replace(/\["url", "a", "area"\]/, '[ "url" ]');
} else if (typeof FormData === 'undefined' && // eslint-disable-line
obj.filename.includes('urlsearchparams-constructor.any.js')) {
// TODO(XadillaX): Remove this `else if` after `FormData` is supported.

// Ignore test named `URLSearchParams constructor, FormData.` because we do
// not have `FormData`.
obj.code = obj.code.replace(
/('URLSearchParams constructor, object\.'\);[\w\W]+)test\(function\(\) {[\w\W]*?}, 'URLSearchParams constructor, FormData\.'\);/,
'$1');
}
});
runner.pretendGlobalThisAs('Window');
Expand Down

0 comments on commit c0a9720

Please sign in to comment.