Repository navigation
Move node:util MIMEType from C++ to TypeScript - #7968
Conversation
|
💬 Approved with comments — The TypeScript port matches the C++ parser and is well tested. The only notes are informational: observable differences that the commit message explicitly accepts, and slower parse and toString() on some inputs. Findings: 2 info The decision is advisory: this comment never approves, blocks or requests changes on the pull request. 🔧 Fix with your agentPaste the following into your coding agent to investigate and fix these issues. 📋 Code Quality: 💬 1 infoThe port looks correct and is well tested. One informational note about behavior changes that the commit message accepts. Recommendation: 💬 Optional Nits
View full reviewI compared the parser, setters, params operations, iterators and error messages against the removed C++ code and found no logic errors.
⚡ Performance: 💬 1 infoLinear-time and no leaks. Parse and toString() are 1.4–3.7x slower on some inputs. Recommendation: 💬 Optional Nits
View full review
✅ All other checks passed🔒 Security: ✅ LGTM
The C++ changes only delete code. 📖 AGENTS.md: ✅ LGTMNo AGENTS.md updates needed. 📝 Documentation: ✅ LGTMNo documentation issues. Reviewed commit: |
|
Since last review: 2 resolved, 0 still open, 1 new. Updates MIME parameter deletion cleanup and the patched-built-ins implementation coverage. Other findings
Not re-run: jsg-gc, kj-style, memory-safety (no author changes in their files since the last review) Reviewed commit: c2d60992 · github run |
auditbenchai
left a comment
There was a problem hiding this comment.
Findings: 1, listed in the fix prompt below (they couldn't be placed as inline comments).
Merge risk: 🟢 Low · up to f9b3e28
Minor edge-case discrepancies such as error messages, prototype enumerability, or slight performance differences in parameter-heavy parsing could affect strict callers, though behavior is well-tested.
Merge readiness: ⛔ Not ready to merge
Pre-merge checks: ✅ 8 · ⚠️ 1 · ❌ 1
❌ Failed checks: 1 error, 1 warning
| Check name | Status | Explanation | Resolution |
|---|---|---|---|
| CI checks | ❌ | 7 of 30 failing: test (linux-arm, ubuntu-22.04-arm-16core) / bazel, test (linux, ubuntu-22.04-16core, -asan) / bazel, test-linux / bazel, test (macOS, macos-15-xlarge) / bazel…. | Open the failing runs on GitHub and fix them before merging. |
| PR size | 1,655 lines changed, which is hard to review well. | Split it into smaller pull requests if you can. |
✅ Passed checks: 8 passed
| Check name | Status | Explanation |
|---|---|---|
| Merge conflicts | ✅ | Merges cleanly into main. |
| Secrets | ✅ | No keys, passwords or tokens in the changed code. |
| Blocking issues | ✅ | No critical or high-severity issues in the changed lines. |
| Tests | ✅ | Tests were changed alongside the code. |
| Title check | ✅ | The title clearly and concisely states the primary change made in the PR. |
| Description check | ✅ | The description thoroughly details the motivation, differences from C++, benchmark results, and testing strategy. |
| Linked issues check | ✅ | Mentions internal tracker NODE-6; no external GitHub issues are formally linked. |
| Out of scope changes check | ✅ | All changes are directly related to moving MIMEType and MIMEParams to TypeScript. |
📝 Walkthrough
This pull request replaces the C++ implementation of node:util's MIMEType and MIMEParams with a TypeScript implementation. The new version is designed to match existing runtime behavior and WHATWG MIME Sniffing standards while avoiding built-in method calls to remain resilient against prototype pollution. It also updates internal type definitions and adds comprehensive tests covering behavior and patched built-ins.
| File | Changes |
|---|---|
src/node/internal/internal_mime.ts |
Implements MIMEType and MIMEParams parsing, storage, and serialization in pure TypeScript. |
src/node/internal/util.d.ts |
Updates TypeScript declaration types for node:util internals. |
src/node/util.ts |
Exports the new TypeScript implementation of MIMEType and MIMEParams. |
src/workerd/api/node/tests/mimetype-test.js |
Adds tests verifying compatibility, parsing edge cases, and resilience to patched built-ins. |
ℹ️ Review info
- Commit:
f9b3e28 - Verdict: ✅ Pass
- Findings: 1 low
- Review: local checks plus AI review of the changed lines
- Scope: Reviewed 3/4 files (of 4 total) — 0 from cache, 0 needed no AI review. Found 1 finding(s), 0 potential secret(s). 1 file(s) couldn't be reviewed (src/node/internal/util.d.ts): the AI provider returned an error.
🤖 Prompt to fix review comments
Verify each finding against the current code and only fix it if it still applies.
In `@src/node/util.ts` around line 343: High cyclomatic complexity: styleText(). Complexity of 17 makes this function harder to test and reason about. Suggested fix: Split into smaller functions with single responsibilities.
💬 Reply to any inline comment and Audit Bench Ai will recheck that code and answer in the thread. Mention @auditbench in the conversation to ask about the whole PR.
🛠️ Open the full report and fix with AI
Thanks for using Audit Bench Ai! Free pull request reviews for open source: paste any public PR at auditbenchai.com/scan.
Reviewed by Audit Bench Ai · AI code review for security, logic and performance · Review any public PR free
piscisaureus
left a comment
There was a problem hiding this comment.
Direction is fine.
Before merging:
- Fix the eslint failure (
mimetype-test@eslint). - Say in the commit message that the enumerability,
structuredCloneandimmutable_api_prototypeschanges are accepted without a compat flag. - Actually delete stale keys in
ParamTable.delete(); right now a long-livedMIMEParamsthat sets and deletes distinct names keeps growing.
NODE-6: MIMEType and MIMEParams are now in TypeScript, reproducing
the C++ parser and every probed result. Tests pin the behavior of the
C++ implementation and pass against both: parsing, the parameter
quirks (exact-match get(), set() keeping an existing value, delete()
reordering), argument conversion and errors, iterators, and inspect
output. The implementation calls no built-in methods after loading, so
patched built-ins can't change its results, which a test checks.
Compatibility: as in Node.js, the classes are plain JavaScript classes
rather than JSG resource types. This changes, at every compatibility
date and without a compatibility flag, which we accept:
- Prototype methods and accessors aren't enumerable.
- structuredClone() of either class returns {} instead of throwing
DataCloneError.
- The constructors' `prototype` property is not writable. With
immutable_api_prototypes, which makes it read-only for JSG resource
types, nothing changes; without it, it was writable.
f9b3e28 to
c2d6099
Compare
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #7968 +/- ##
==========================================
- Coverage 42.05% 41.90% -0.16%
==========================================
Files 1061 1062 +1
Lines 301008 302159 +1151
Branches 29043 29026 -17
==========================================
+ Hits 126599 126616 +17
- Misses 157389 158537 +1148
+ Partials 17020 17006 -14 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
@jasnell just to confirm - is this one fine to merge without an autogate, or should I add one? |
|
This should be fine with no autogate |
NODE-6: MIMEType and MIMEParams are now in TypeScript, reproducing the C++ parser and every probed result; the tests from the previous commit pass unchanged. The implementation calls no built-in methods after loading, so patched built-ins can't change its results. As in Node.js the classes are plain, so methods aren't enumerable and structuredClone() returns {} instead of throwing.
The tests pin the behavior of the C++ implementation and pass against both implementations; one more test patches built-ins.
The differences below change at every compatibility date, without a compatibility flag, and are accepted (see the commit message).
immutable_api_prototypesonly makes the constructor'sprototypeproperty read-only (V8'sReadOnlyPrototype()), which a class'sprototypealready is, so it has no effect on the difference in that row.Differences from the C++ implementation
Probed at compat dates 2023-01-01 and 2026-10-01. Parsing (71 cases), argument conversion, the setters and the params operations otherwise give identical results.
MIMEType()/MIMEParams()withoutnewTypeError: Failed to construct 'MIMEType': Please use the 'new' operator, ...TypeError: Class constructor MIMEType cannot be invoked without 'new'essence/paramsTypeError: Cannot assign to read only property 'essence' ...TypeError: Cannot set property essence of ... which has only a getterstructuredClone()of either classDataCloneError{}(as in Node.js)Function.prototype.toString()function MIMEType() { [native code] }prototypeproperty of the constructornext,constructor, ...constructor,next, ...Patched built-ins: at old compat dates the C++ iterators were affected by a
valuesetter onObject.prototype. The TypeScript implementation isn't affected at any compat date.Performance
Medians of 3 runs of
workerd bench,--config=benchmark, same machine.text/plaintoString(), 2 paramstoString(), 20 paramsessenceparams.get()params.set()+delete()typesetter