Skip to content

fix #290 - overloadOperator#292

Closed
phillipc wants to merge 6 commits intomainfrom
fix_#290
Closed

fix #290 - overloadOperator#292
phillipc wants to merge 6 commits intomainfrom
fix_#290

Conversation

@phillipc
Copy link
Copy Markdown
Member

@phillipc phillipc commented Apr 9, 2026

fix: add precedence parameter to overloadOperator and update usage in index.ts #290

Summary by CodeRabbit

… index.ts

fix: correct propertyChangeFired reference in value.ts
@phillipc phillipc requested review from brianmhunt and Copilot and removed request for Copilot April 9, 2026 15:56
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 9, 2026

Warning

Rate limit exceeded

@brianmhunt has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 15 minutes and 49 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 15 minutes and 49 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: fbbbe524-acd8-4945-ae5d-d8cc5e3f5c62

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between c23f386 and 2951ea8.

πŸ“’ Files selected for processing (1)
  • packages/utils/src/options.ts
πŸ“ Walkthrough

Walkthrough

Removed the exported overloadOperator API and its runtime registrations; added an options.overloadEvilTwins flag that toggles ==/!= behavior to strict forms; removed an unused propertyChangeFired field and updated the IE autocomplete blur handler to reference propertyChangedFired.

Changes

Cohort / File(s) Summary
Parser operator API
packages/utils.parser/src/index.ts
Removed the exported overloadOperator function (no runtime API to register operators).
Operator implementations
packages/utils.parser/src/operators.ts
== and != now conditionally use strict equality/inequality (=== / !==) when options.overloadEvilTwins is truthy; otherwise they preserve prior loose-equality semantics.
Options
packages/utils/src/options.ts
Added new boolean option overloadEvilTwins: boolean = false to control the ==/!= behavior.
Build reference / runtime registrations
builds/reference/src/index.ts
Removed runtime operator-overload registrations for == and != that relied on overloadOperator.
Binding handler fix
packages/binding.core/src/value.ts
Removed the propertyChangeFired class field and updated the IE autocomplete blur listener to reference the existing propertyChangedFired variable.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • brianmhunt

Poem

🐰 I hopped through code with nimble paws,
I swapped the twins for stricter laws,
A flag decides which path to choose,
A field removed β€” no more name blues,
I nibble bugs and leave small claws.

πŸš₯ Pre-merge checks | βœ… 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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
Title check βœ… Passed The PR title 'fix #290 - overloadOperator' clearly identifies the main issue being addressed and the primary component involved, accurately reflecting the core changes across multiple files.
Description Check βœ… Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ 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 fix_#290

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.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

πŸ€– Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/utils.parser/src/index.ts`:
- Around line 11-17: The overloadOperator function mutates operators[op] before
validating precedence, so if the precedence check throws the operator is
partially applied; update the logic in overloadOperator to validate that
precedence is an integer before mutating the global operators map (or create a
local tmp for fn, set tmp.precedence after validation, then assign operators[op]
= tmp); reference the overloadOperator function and the operators symbol when
making the change.
πŸͺ„ Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
βš™οΈ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0e6bf427-b6f9-410b-b970-5428243348b7

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between ad24da6 and 3239945.

πŸ“’ Files selected for processing (3)
  • builds/reference/src/index.ts
  • packages/binding.core/src/value.ts
  • packages/utils.parser/src/index.ts

Comment thread packages/utils.parser/src/index.ts Outdated
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 9, 2026 17:09
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

Fixes operator-precedence loss when overriding ==/!= in the reference build (issue #290) and corrects an IE autocomplete hack flag check in the value binding handler.

Changes:

  • Updates overloadOperator to require and validate an integer precedence, and always assigns it to the operator function.
  • Updates the reference build to overload ==/!= with strict equivalents using precedence 10.
  • Fixes a typo in value binding by using propertyChangedFired consistently.

Reviewed changes

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

File Description
packages/utils.parser/src/index.ts Changes the overloadOperator API to require validated precedence and always set it on the operator.
builds/reference/src/index.ts Updates ==/!= overload calls to pass an explicit precedence value to avoid parsing errors.
packages/binding.core/src/value.ts Fixes incorrect propertyChangeFired reference so the IE autocomplete workaround can trigger correctly.

Comment thread packages/utils.parser/src/index.ts Outdated
Comment thread builds/reference/src/index.ts Outdated
Comment thread packages/utils.parser/src/index.ts Outdated
@brianmhunt
Copy link
Copy Markdown
Member

Could you split this into two PRs? The typo fix in value.ts (propertyChangeFired β†’ propertyChangedFired) and the operator overload refactor (overloadOperator β†’ options.overloadEvilTwins) are unrelated changes β€” easier to review and merge independently.

@phillipc phillipc changed the title fix #290 and textInput.ts fix #290 - overloadOperator Apr 10, 2026
@phillipc
Copy link
Copy Markdown
Member Author

@brianmhunt Sure, done, sometimes git revert actually works ;)

@brianmhunt
Copy link
Copy Markdown
Member

@phillipc This changes the default behavior for @tko/build.reference users. Previously, == was silently overloaded to === at startup via overloadOperator. With this PR, options.overloadEvilTwins defaults to false, so == reverts to loose equality.

That's a breaking change for every existing @tko/build.reference binding that uses == β€” they've been getting strict equality for years.

The default should be true (preserving existing behavior), with the option to explicitly set false for loose equality. Could you flip the default?

@tko/build.reference has shipped with == meaning === in binding
expressions. Defaulting to false would be a breaking change for
every existing binding that uses ==.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@brianmhunt
Copy link
Copy Markdown
Member

Update on this β€” I pushed a fix to the default but then realized the bigger issue: the if (options.overloadEvilTwins) check in the operator functions runs on every ==/!= evaluation in every binding expression. That's the parser's hot path.

The original overloadOperator pattern was actually the right approach β€” mutate the operator table once at startup, zero per-call overhead. I've reverted my changes on the branch.

I think we should close this PR and keep the existing overloadOperator API. The current code works correctly and is performant. If we want to make the evil-twin behavior configurable, we can add an options.overloadEvilTwins flag that calls overloadOperator at init time (one-time cost) rather than checking a flag per evaluation.

@phillipc what do you think?

@phillipc
Copy link
Copy Markdown
Member Author

@brianmhunt I know but we have no init-hook. We would then also have to differentiate between dynamic runtime options and static init options. That would certainly be the best way forward, but more extensive and should be knockout compatible designed.

brianmhunt pushed a commit that referenced this pull request Apr 15, 2026
Zero-cost operator swap at configuration time instead of per-evaluation
branching. The setter swaps function references in the operators table
with pre-built functions that have correct precedence metadata.

- Add setStrictEquality(bool) to @tko/utils.parser
- Remove overloadOperator (was only used for == and !=)
- builds/reference calls setStrictEquality(true) at setup
- Add 6 tests covering loose/strict modes, toggling, and === isolation

Addresses #290. Alternative to PR #292 which added a runtime branch
inside the hot-path operator functions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
brianmhunt pushed a commit that referenced this pull request Apr 15, 2026
Add `defineOption()` to @tko/utils β€” a plugin-friendly API for registering
custom options with side-effect setters on ko.options.

@tko/utils.parser uses defineOption to register `strictEquality`:
- ko.options.strictEquality = true β†’ == becomes ===, != becomes !==
- ko.options.strictEquality = false β†’ default loose equality (default)
- Strongly typed via declaration merging on the Options class
- Zero runtime cost: swaps function references at config time

builds/reference sets `options.strictEquality = true` at setup.
builds/knockout uses the default (loose equality).

Removes `overloadOperator` (was only used for ==/!=).

6 new tests covering loose/strict modes, toggling, and === isolation.

Addresses #290. Alternative to PR #292.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
brianmhunt pushed a commit that referenced this pull request Apr 15, 2026
Add `defineOption()` to @tko/utils β€” a plugin-friendly API for registering
custom options with side-effect setters on ko.options.

@tko/utils.parser uses defineOption to register `strictEquality`:
- ko.options.strictEquality = true β†’ == becomes ===, != becomes !==
- ko.options.strictEquality = false β†’ default loose equality (default)
- Strongly typed via declaration merging on the Options class
- Zero runtime cost: swaps function references at config time

builds/reference sets `options.strictEquality = true` at setup.
builds/knockout uses the default (loose equality).

Removes `overloadOperator` (was only used for ==/!=).

6 new tests covering loose/strict modes, toggling, and === isolation.

Addresses #290. Alternative to PR #292.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@brianmhunt
Copy link
Copy Markdown
Member

Alternative approach: PR #314

We've opened #314 with a different approach that avoids adding a branch to the hot-path operator functions.

ko.options.strictEquality

Instead of checking options.overloadEvilTwins on every ==/!= evaluation, #314 swaps the function references in the operators table at configuration time β€” same mechanism as the existing overloadOperator, but as a clean setter on ko.options:

ko.options.strictEquality = true   // == becomes ===, != becomes !==

Zero per-evaluation cost. Strongly typed. Fully tested (6 new tests).

Also introduces defineOption() β€” a plugin-friendly API for registering custom options with side-effect setters, so other packages can extend ko.options the same way.

See #314 for details.

@phillipc phillipc closed this Apr 16, 2026
@phillipc phillipc deleted the fix_#290 branch April 16, 2026 00:45
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.

3 participants