Skip to content

node:url: coerce URL property setter values to strings #3056

@andrewtdiz

Description

@andrewtdiz

Summary

WHATWG URL property setters stringify assigned values before applying field-specific parsing/encoding. Perry lowers URL setter assignments through string-pointer extraction, so non-string values become empty/null strings instead of String(value), and symbols do not throw the conversion TypeError.

Node.js behavior

Observed locally with Node v25.9.0:

function probe(prop, value) {
  const u = new URL("http://user:pass@example.com:8080/a?x=1#h");
  try {
    u[prop] = value;
    console.log(prop, String(value), "OK", u.href, "prop", u[prop]);
  } catch (err) {
    console.log(prop, String(value), "THROW", err.name, err.code, err.message.split("\n")[0]);
  }
}

for (const prop of ["pathname", "search", "hash", "username", "password", "hostname", "port", "protocol", "href"]) {
  probe(prop, 123);
}
for (const prop of ["pathname", "search", "hash"]) {
  probe(prop, null);
  probe(prop, Symbol("x"));
}

Output excerpt:

pathname 123 OK http://user:pass@example.com:8080/123?x=1#h prop /123
search 123 OK http://user:pass@example.com:8080/a?123#h prop ?123
hash 123 OK http://user:pass@example.com:8080/a?x=1#123 prop #123
username 123 OK http://123:pass@example.com:8080/a?x=1#h prop 123
password 123 OK http://user:123@example.com:8080/a?x=1#h prop 123
hostname 123 OK http://user:pass@0.0.0.123:8080/a?x=1#h prop 0.0.0.123
port 123 OK http://user:pass@example.com:123/a?x=1#h prop 123
protocol 123 OK http://user:pass@example.com:8080/a?x=1#h prop http:
href 123 THROW TypeError ERR_INVALID_URL Invalid URL
pathname null OK http://user:pass@example.com:8080/null?x=1#h prop /null
search null OK http://user:pass@example.com:8080/a?null#h prop ?null
hash null OK http://user:pass@example.com:8080/a?x=1#null prop #null
pathname Symbol(x) THROW TypeError undefined Cannot convert a Symbol value to a string

Current Perry behavior

  • crates/perry-codegen/src/expr/url_main.rs lowers URL setters by calling js_get_string_pointer_unified on the assigned value, then passes the pointer to js_url_set_pathname, js_url_set_search, js_url_set_hash, js_url_set_protocol, js_url_set_hostname, js_url_set_port, js_url_set_username, js_url_set_password, or js_url_set_href.
  • crates/perry-runtime/src/url/url_class.rs setter helpers treat null value pointers as empty strings through string_header_to_string(value) or local null handling.
  • Because the original JS value is lost, numbers/null/objects cannot be stringified and symbols cannot throw the required conversion TypeError.

Suggested test surface

  • Assigning 123 to pathname, search, hash, username, password, hostname, and port follows Node's stringified setter behavior.
  • Assigning null to pathname, search, and hash uses "null", not an empty string.
  • Assigning a symbol to string-converting URL setters throws TypeError: Cannot convert a Symbol value to a string.
  • Assigning 123 to href throws TypeError ERR_INVALID_URL after converting to the invalid URL string "123".

Duplicate checks

Searched issues for URL setter string coercion and URL property assignment non-string; searched PRs for URL setter coercion OR URL property assignment. Existing URL issues cover constructor/static helper coercion (#3054/#3055), normalization (#2974), file path options (#2975), urlToHttpOptions (#2976), and URLSearchParams (#2977/#2978), but not property setter conversion.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions