Skip to content

Modernize @tko/utils: drop dead polyfill probes#344

Merged
brianmhunt merged 5 commits into
mainfrom
modernize/utils-dead-polyfills
Apr 20, 2026
Merged

Modernize @tko/utils: drop dead polyfill probes#344
brianmhunt merged 5 commits into
mainfrom
modernize/utils-dead-polyfills

Conversation

@brianmhunt
Copy link
Copy Markdown
Member

@brianmhunt brianmhunt commented Apr 20, 2026

Summary

Phase A of @tko/utils modernization. Removes runtime feature detection for capabilities every supported runtime (modern browsers, Node, Bun, happy-dom) already provides unconditionally. No behavior change — the guards were all true branches in practice.

Dropped

  • functionSupportsLengthOverwrite probe — Object.defineProperty(fn, 'length', …) has worked since IE9
  • useSymbols probe — Symbol is always defined
  • stringTrim polyfill fallback — always uses String.prototype.trim
  • stringStartsWith manual substring comparison — delegates to String.prototype.startsWith
  • toggleDomNodeCssClass SVGAnimatedString fallback + toggleObjectClassPropertyString helper — classList works on every supported Element (SVG2)
  • parseJson indirection through stringTrim

Other

  • packages/utils.parser/src/preparse.ts guards str.match(bindingToken) ?? [] — previously relied on the transformed input never producing a null match. Paranoia, not a known bug.

Verification

  • bun run build — clean
  • bunx vitest run --project browser — 2708 pass / 42 skip
  • bunx vitest run --project cli-happy-dom — 2681 pass / 69 skip
  • bunx tsc --noEmit — clean
  • Biome — no errors (pre-existing warnings only)

Test plan

  • CI green across chromium/firefox/webkit + cli-happy-dom
  • Bundle size check (expected: smaller)

Refs #335 — tracking plan for @tko/utils modernization.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Chores

    • Modernized utility functions by removing runtime feature detection for capabilities now treated as universally available across supported environments.
    • Streamlined CSS class toggling to use standard classList API exclusively.
    • Enhanced type safety with explicit TypeScript type annotations throughout utilities.
  • Bug Fixes

    • Added null-safety handling to token parsing logic to prevent potential errors.

Brian M Hunt and others added 2 commits April 20, 2026 14:44
Remove legacy compat shims that pre-date ES2015+ as baseline:

- symbol.ts: useSymbols probe is always true; inline Symbol() call
- function.ts: functionSupportsLengthOverwrite probe is always true;
  Function.length has been configurable since ES6
- string.ts: stringTrim no longer needs the \xa0-regex fallback;
  stringStartsWith delegates to native String.prototype.startsWith
- css.ts: every Element has classList; drop SVGAnimatedString and
  string-className fallbacks
- preparse.ts: stringTrim's tightened return type (string, not any)
  surfaced a null gap where str.match() could return null; default
  to [] at both call sites

Public API (createSymbolOrString, overwriteLengthPropertyIfSupported,
stringTrim, stringStartsWith, parseJson, toggleDomNodeCssClass)
unchanged. Internal probe exports (useSymbols,
functionSupportsLengthOverwrite) removed — they had no external
consumers in the monorepo.

Net -40 lines. All 2698 browser tests and 2671 happy-dom tests pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings April 20, 2026 18:46
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 20, 2026

Warning

Rate limit exceeded

@brianmhunt has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 28 minutes and 4 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 28 minutes and 4 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c9cf2cf4-0bed-4def-9fdd-c8dd6111f025

📥 Commits

Reviewing files that changed from the base of the PR and between 49576cb and a38f5e4.

📒 Files selected for processing (17)
  • .changeset/modernize-utils-dead-polyfills.md
  • builds/knockout/spec/bindingAttributeBehaviors.js
  • packages/binding.core/src/css.ts
  • packages/binding.core/src/hasfocus.ts
  • packages/binding.core/src/value.ts
  • packages/binding.foreach/src/foreach.ts
  • packages/builder/src/Builder.ts
  • packages/computed/src/computed.ts
  • packages/lifecycle/src/LifeCycle.ts
  • packages/observable/src/observable.ts
  • packages/observable/src/observableArray.ts
  • packages/utils.parser/src/preparse.ts
  • packages/utils/src/function.ts
  • packages/utils/src/index.ts
  • packages/utils/src/string.ts
  • packages/utils/src/symbol.ts
  • packages/utils/src/tasks.ts
📝 Walkthrough

Walkthrough

The pull request modernizes @tko/utils by removing runtime feature detection ("polyfills") for JavaScript capabilities now treated as universally available. This includes eliminating Symbol detection, classList probing, Object.defineProperty checks, and simplifying string utility functions. Type signatures are strengthened and null-safety is improved where needed.

Changes

Cohort / File(s) Summary
Changeset & Metadata
.changeset/modernize-utils-dead-polyfills.md
Documents a patch release for @tko/utils and @tko/utils.parser marking the removal of dead polyfill probes.
Symbol Handling
packages/utils/src/symbol.ts
Removed useSymbols detection; createSymbolOrString now always returns a symbol via Symbol(identifier) instead of conditionally returning a string fallback.
Function Utilities
packages/utils/src/function.ts
Removed functionSupportsLengthOverwrite detection; overwriteLengthPropertyIfSupported unconditionally calls Object.defineProperty. Signature now explicitly typed with Function and PropertyDescriptor.
String Utilities
packages/utils/src/string.ts
Simplified stringTrim to always call String(value).trim() with strong typing; updated stringStartsWith to delegate to String.prototype.startsWith; parseJson now trims inline instead of via helper.
CSS Class Toggling
packages/utils/src/css.ts
Removed SVGAnimatedString and string className fallback logic; toggleDomNodeCssClass now assumes classList always exists, using regex-matched tokens with add/remove calls.
Parser Null Safety
packages/utils.parser/src/preparse.ts
Added null-coalescing (?? []) to str.match(bindingToken) calls in parseObjectLiteral to safely handle potential null returns from regex matching.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 No more feature probes, just modern ways,
Symbols shine brightly, classList stays,
Dead polyfills swept clean from the scene,
The code now reflects what runtimes have been! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 42.86% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'Modernize @tko/utils: drop dead polyfill probes' clearly and directly summarizes the main change - removing obsolete runtime feature-detection code and polyfill fallbacks from the @tko/utils package.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch modernize/utils-dead-polyfills

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

The wrapper was only there to gate on the dead `functionSupportsLengthOverwrite`
probe. With the probe gone the function is a trivial alias — call sites in
@tko/observable now invoke `Object.defineProperty(…, 'length', descriptor)`
directly. packages/utils/src/function.ts removed.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 49576cbae3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/utils/src/symbol.ts Outdated

export function createSymbolOrString(identifier) {
return useSymbols ? Symbol(identifier) : identifier
export function createSymbolOrString(identifier: string): symbol {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Keep useSymbols as a compatibility export

@tko/utils publicly re-exports src/symbol.ts, so removing useSymbols is a breaking API change for downstream code that imports it (import { useSymbols } from '@tko/utils'). In this commit the symbol helper is narrowed to always return Symbol, but the removed named export will still break consumers immediately in both TS and runtime module resolution while this is marked as a patch release.

Useful? React with 👍 / 👎.

Comment thread packages/utils/src/function.ts Outdated
if (functionSupportsLengthOverwrite) {
Object.defineProperty(fn, 'length', descriptor)
}
export function overwriteLengthPropertyIfSupported(fn: Function, descriptor: PropertyDescriptor): void {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Preserve functionSupportsLengthOverwrite export

Because @tko/utils re-exports src/function.ts, deleting functionSupportsLengthOverwrite removes a previously available named export and creates a semver-breaking change for any consumer importing it from the package root. Even if the runtime probe is now unnecessary, retaining an exported compatibility constant (or shipping a major bump) avoids unexpected build/runtime failures for existing users.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Phase A of @tko/utils modernization: removes legacy runtime feature-detection branches and fallback code paths that are no longer needed for supported runtimes, keeping the runtime behavior effectively the same while simplifying implementations.

Changes:

  • Simplifies @tko/utils helpers by removing polyfill probes and legacy fallbacks (Symbols, string trim/startsWith, function length overwrite, DOM class toggling).
  • Tightens some utility implementations and TypeScript annotations.
  • Makes @tko/utils.parser object-literal tokenization resilient to String.prototype.match returning null.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
packages/utils/src/symbol.ts Removes useSymbols probe; createSymbolOrString now always returns a Symbol with a stricter TS signature.
packages/utils/src/string.ts Removes trim/startsWith fallbacks; uses native trim()/startsWith() with updated TS signatures.
packages/utils/src/function.ts Removes length-overwrite feature probe; always calls Object.defineProperty with typed params.
packages/utils/src/css.ts Drops SVG/className fallback paths; relies on classList and token iteration.
packages/utils.parser/src/preparse.ts Guards match() results with ?? [] to avoid null handling issues.
.changeset/modernize-utils-dead-polyfills.md Adds changeset marking @tko/utils and @tko/utils.parser as patch bumps for this modernization.
Comments suppressed due to low confidence (1)

packages/utils/src/function.ts:2

  • overwriteLengthPropertyIfSupported is a public export and this commit changes its TS signature from implicit any parameters to fn: Function and descriptor: PropertyDescriptor. That can be a breaking typing change for downstream TS callers (especially those passing a callable type rather than Function, or building descriptors dynamically). If the intent is “no API change” in a patch, consider keeping the parameters more permissive (or using a more precise callable type than Function) to reduce downstream breakage.

Comment thread packages/utils/src/string.ts Outdated
return false
}
return string.substring(0, startsWith.length) === startsWith
export function stringStartsWith(value: string | null | undefined, prefix: string): boolean {
Comment thread packages/utils/src/symbol.ts Outdated

export function createSymbolOrString(identifier) {
return useSymbols ? Symbol(identifier) : identifier
export function createSymbolOrString(identifier: string): symbol {
@@ -0,0 +1,27 @@
---
"@tko/utils": patch
Brian M Hunt and others added 2 commits April 20, 2026 15:08
- `createSymbolOrString(id)` removed; 7 call sites across binding.core,
  binding.foreach, computed, lifecycle, and builder now call `Symbol(id)`
  directly. `ko.utils.createSymbolOrString` is no longer on the public API
  (minor bump for @tko/utils, @tko/builder).
- `stringTrim(v)` and `stringStartsWith(v, p)` removed; 3 call sites across
  binding.core and utils.parser use `String(v ?? '').trim()` and
  `v.startsWith(p)` inline.
- `builds/knockout/spec/bindingAttributeBehaviors.js` — drop dead branch
  gated on `createSymbolOrString('') === ''` (always false with real Symbol).
- `packages/utils/src/{function,symbol}.ts` deleted.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- `tasks.ts`: collapse multi-line condition; use optional chaining on
  `schedulerGlobal?.MutationObserver` and `schedulerGlobal.navigator?.standalone`
- `foreach.ts`: single-line import formatting

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@brianmhunt brianmhunt merged commit 6629d63 into main Apr 20, 2026
9 checks passed
@brianmhunt brianmhunt deleted the modernize/utils-dead-polyfills branch April 20, 2026 19:26
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