Repository navigation
Conversation
collectMutations() had three defects that decided which mutants ran: - && and || are listed in BINARY_FLIPS, but acorn parses them as LogicalExpression, which had no visitor, so no logical operator was ever flipped. - The mutant was built with original.replace(op, ...), which changes the first occurrence of the operator text in the expression: one inside a string literal or comment, or the inner + of (a + b) + c. - inFocus() searched the 2000 characters before an offset for a focus function's declaration. Code after a focus function was mutated as if it were inside it, and the end of a focus function longer than 2000 characters was skipped. Take the operator position from the token stream, visit LogicalExpression too, compute the focus ranges from the AST, and check the operator's own position against them. collectMutations() is exported and main() runs only when the script is executed, directly or through a symlink, so the collector can be tested directly. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
scripts/mutation-check.mjsmutated code outside the functions it was asked to focus on, never flipped&&or||, and could flip the wrong operator. This PR fixes the mutant collector and adds tests for it.Related issue
None: issues are disabled on this repository.
Changes
collectMutations()had three defects:&&and||are listed inBINARY_FLIPS, but acorn parses them asLogicalExpression, which had no visitor.original.replace(op, …), which changes the first occurrence of the operator text in the expression's source: inside a string literal ("===" === valuebecame"!==" === value), inside a comment, or the inner+of(a + b) + c.inFocus()looked for a focus function's declaration in the 2000 characters before each node. Code after a focus function was mutated as if it were inside it, and the end of a focus function longer than 2000 characters was skipped.The operator position now comes from acorn's token stream, and
LogicalExpressiongets the same visitor asBinaryExpression. Focus ranges are the source ranges of the named function declarations, function expressions and arrow functions in the AST, and an operator mutation is kept only when the operator itself lies in one of them.collectMutations()is exported, andmain()runs only when the script is executed, directly or through a symlink, sotest/mutation-check.test.jscan import the collector.Effect on the configured modules (
dist/srcbuilt frommain):main&&/||cdp-evalelement-resolverbrowser-runtimehelpersThe "outside" column counts mutants on
mainthat fall in other functions, such asjsExceptionLocationandjsSnippetforcdp-eval,axNameMatchesandisTextMatcherforelement-resolver, andnewTaskSpaceandswitchTaskSpaceforhelpers. With this PR every mutant falls inside a focus function.node scripts/mutation-check.mjs cdp-eval element-resolverruns end to end with the new collector: 39 of 48 mutants killed.Verification
Run from
package/ego-browser.mainnpm test(build, typecheck, tests)main's collector (exported, otherwise unchanged)prettier --checkon the changed files¹
a missing focus function does not mutate unrelated codeandfunction focus excludes an operator after a selected function expressionalready hold onmain; they guard the new range check.² On
mainthe script callsmain()unconditionally when loaded, so it cannot be imported by a test at all.Impact
Development tooling only;
npm run mutation-checkreports on a different, intended set of mutants. No runtime, helper or CI change.🤖 Generated with Claude Code