Skip to content

URL: WebKit parser follow-ups + reuse input string for href, cache the last base URL - #39368

Merged
Jarred-Sumner merged 1 commit into
mainfrom
claude/bump-webkit-c6cfe90
Aug 16, 2026
Merged

URL: WebKit parser follow-ups + reuse input string for href, cache the last base URL#39368
Jarred-Sumner merged 1 commit into
mainfrom
claude/bump-webkit-c6cfe90

Conversation

@Jarred-Sumner

@Jarred-Sumner Jarred-Sumner commented Aug 16, 2026

Copy link
Copy Markdown
Collaborator

What does this PR do?

WebKit bump → c6cfe90c6064 (oven-sh/WebKit#454): table-lookup (pshufb/tbl) SIMD classification in the URL scanners; host:port and dotted-quad IPv4 hosts stay on the parser's fast path. (oven-sh/WebKit#463 — SIMD scan for percent-encoded/Unicode hosts — is up separately and can be folded in once merged.)

Bun-side, things a standalone URL library can't do:

  • new URL(s).href / toString() / toJSON(): when nothing needed rewriting, WebKit's parser result is the input StringImpl, so return the constructor's own JSString instead of allocating another; the last JSString produced for href is cached on the wrapper either way (also makes new URL(rel, urlObject) cheaper, since the base is stringified through it).
  • new URL(input, base) / URL.parse / URL.canParse with a string base re-parsed and re-validated the base every call; it is nearly always the same string (configured origin, request URL), so the last valid base is remembered per thread.
  • hasValidParsedHost's "does the host contain xn--" check ran a generic substring search on every URL; look for -- instead.
  • bench/snippets/url-kinds.mjs: new URL() / canParse / parse over realistic URL shapes.

Same-machine, both non-LTO, ns per call (previous = the #452-era build):

previous this PR
new URL("http://localhost:3000/api/users/42") 191 123
new URL("http://192.168.1.10:8080/metrics") 244 135
new URL("http://[2001:db8::…]:8080/status") 429 289
new URL(longCdnPath) / 2 KB query 169 / 340 127 / 225
new URL("../assets/logo.svg", pageUrlString) 401 263
new URL("?page=3", listUrlString) 327 229
new URL("../assets/logo.svg", urlObject) 562 371
new URL(u).href / .toString() 185 / 184 147 / 147
URL.canParse(pathQueryHash) 116 87
IDN host 1256 1078

How did you verify your code works?

test/js/web/url (new cases for repeated/alternating/invalid string bases incl. error .input/.base, and href/toString/toJSON consistency across mutation), test/js/node/url, node test-whatwg-url-* / test-url-* pass on a release build against WebKit c6cfe90c + #463.

…ion, host:port and IPv4 fast path, oven-sh/WebKit#454)

No-Verification-Needed: version pin bump
@coderabbitai

coderabbitai Bot commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 8 minutes

Limit details: You’ve used all 1 included review currently available under your plan. You completed 69 included PR reviews in the past 7 days; at that activity level, included reviews refill at 1 review per hour.

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 4b6b14b9-daa8-4c64-865f-d35343a1d8c5

📥 Commits

Reviewing files that changed from the base of the PR and between 8326d1b and 2aa4253.

📒 Files selected for processing (1)
  • scripts/build/deps/webkit.ts

Comment @coderabbitai help to get the list of available commands.

@robobun

robobun commented Aug 16, 2026

Copy link
Copy Markdown
Collaborator
Updated 4:50 PM PT - Aug 16th, 2026

@Jarred-Sumner, your commit 2aa42536907649e6cc7b5be3e94cab0a33729607 passed in Build #99658! 🎉


🧪   To try this PR locally:

bunx bun-pr 39368

That installs a local version of the PR into your bun-39368 executable, so you can run:

bun-39368 --bun

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM — single-line WebKit version pin bump.

Checked that only WEBKIT_VERSION changed in scripts/build/deps/webkit.ts; no other logic touched. The new hash is a valid 40-char hex sha, so the autobuild-<hash> tag/URL derivation and the 16-char cache-dir slice both keep working. Substantive URL-parser changes live in oven-sh/WebKit#454 and were validated there (43-config CI, TestWTF, differential fuzz).

Extended reasoning...

Overview

This PR updates the WEBKIT_VERSION constant in scripts/build/deps/webkit.ts from 0cbb4a194653… to c6cfe90c6064…. It is a one-line change to a string literal that determines which prebuilt WebKit tarball is downloaded (or which commit is checked out in local mode). All actual code changes — SIMD table-lookup classification and the host:port/IPv4 fast path in URLParser — live in oven-sh/WebKit#454 and are not part of this diff.

Security risks

None from the Bun-side diff. The value is a git commit hash consumed only by the build system to construct a GitHub release download URL and a cache directory name. It is not user-controllable at runtime and does not flow into any parsing or network path in the shipped binary.

Level of scrutiny

Low for the Bun diff itself: this is a routine dependency version bump following the established pattern (see recent commits like #39273 which bumped the same constant). The value is a well-formed 40-hex sha, so prebuiltUrl prefixes it with autobuild- correctly and prebuiltDestDir's .slice(0, 16) still yields a distinct cache key. The substantive changes were reviewed, differentially fuzzed, and CI-tested across 43 configs in the WebKit repo; Bun CI will exercise the full integration once the prebuilt tarballs publish.

Other factors

No CODEOWNERS entry covers this path. No prior reviewer comments to address. The PR description explicitly notes the WebKit download step will fail until prebuilts publish (~1h), which is expected and gates merge on CI going green — a human does not need to re-verify the hash by hand.

@Jarred-Sumner
Jarred-Sumner merged commit 30fa519 into main Aug 16, 2026
11 of 12 checks passed
@Jarred-Sumner
Jarred-Sumner deleted the claude/bump-webkit-c6cfe90 branch August 16, 2026 23:54
springmin pushed a commit to springmin/bun that referenced this pull request Aug 17, 2026
…h#39368)

Only Source/WTF/wtf/URLParser.cpp changed upstream (167+/42-); the FFI
tree is untouched, so the OHOS symlink headers and perl pin carry over.
Verified: URL suite 24/24, buffer 634/634, blob 104/104, fetch 363/363.
@Jarred-Sumner Jarred-Sumner changed the title Bump WebKit: URL parser table-lookup SIMD + host:port fast path URL: WebKit parser follow-ups + reuse input string for href, cache the last base URL Aug 17, 2026
Jarred-Sumner added a commit that referenced this pull request Aug 17, 2026
…nycode without full ICU (#39468)

### What does this PR do?

URL binding follow-ups on top of #39368 (the parser work lives in
WebKit; these are the parts a standalone URL library can't do, plus the
one place Node still beat us):

- **`href` / `toString()` / `toJSON()` reuse the constructor's
`JSString`** when the URL was already canonical — WebKit's parser result
*is* the input `StringImpl` in that case — and otherwise cache the last
`JSString` produced on the wrapper. Also makes `new URL(rel, urlObject)`
cheaper (the base is stringified through it).
- **Last-base cache on `JSVMClientData`**: `new URL(input, base)` /
`URL.parse` / `URL.canParse` with a string base re-parsed and
re-validated the base on every call; it is nearly always the same string
(configured origin, request URL), so the last valid one is remembered
per VM.
- **Literal `xn--` labels judged without full ICU ToASCII**
(`ASCIIHostPunycodeCheck.h`): `hasValidPunycodeHost()` ran
`uidna_nameToASCII` (~600 ns) whenever a host contained a literal `xn--`
label. For an all-ASCII host the only thing ToASCII can reject is an ACE
label, so this mirrors `icu::UTS46::processLabel` for those: RFC 3492
decode with `u_strFromPunycode`'s failure rules → must be unchanged
under the `uts46` normalizer → no U+FFFD → no leading combining mark.
Labels that would then need the BiDi / CONTEXTJ rules still go to ICU,
so verdicts are ICU's by construction.
- Cheaper "does the host contain `xn--`" probe (was a generic substring
search on every parse).
- `bench/snippets/url-kinds.mjs`.

| ns/op, same box | before | after | node 26 |
|---|---|---|---|
| `URL.canParse("https://xn--a.com/")` (invalid punycode) | 870 |
**312** | 290 |
| `URL.canParse("https://xn--ls8h.com/p")` (valid punycode) | 826 |
**425** | 581 |
| `new URL("../assets/logo.svg", pageUrlString)` | 401 | **263** | 838 |
| `new URL("../assets/logo.svg", urlObject)` | 562 | **371** | 886 |
| `new URL(u).href` / `.toString()` | 185 / 184 | **147 / 147** | 462 /
453 |

### How did you verify your code works?

- The punycode check was differentially tested against ICU's
`uidna_nameToASCII` (Bun's flags/allowed errors) on ~380k hosts — every
IdnaTestV2/toascii input's ACE form, mutations of those, random `xn--`
labels, mixed case: 0 disagreements (128k valid, 251k invalid, 19k
deferred to ICU).
- New `url.test.ts` cases: literal punycode verdicts
(valid/invalid/uppercase/RTL/ZWJ/combining-mark/overflow, all
cross-checked with Node 26), repeated/alternating/invalid string bases
incl. error `.input`/`.base`, href/toString/toJSON consistency across
mutation.
- `test/js/web/url`, `test/js/node/url`, node `test-whatwg-url-*`,
`test-url-*`, `test-whatwg-url-custom-domainto`,
`test-url-domain-ascii-unicode` pass on a release build.

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants