Skip to content

fix(eslint): stop prefer-global-this making the browser framing check unspellable - #36

Merged
Eli Bosley (elibosley) merged 2 commits into
mainfrom
claude/eslint-browser-global-this-conflict
Aug 3, 2026
Merged

fix(eslint): stop prefer-global-this making the browser framing check unspellable#36
Eli Bosley (elibosley) merged 2 commits into
mainfrom
claude/eslint-browser-global-this-conflict

Conversation

@elibosley

@elibosley Eli Bosley (elibosley) commented Aug 3, 2026

Copy link
Copy Markdown
Member

Summary

The canonical browser framing check — window.parent === window, how DOM code asks "am I inside an iframe?" — has no spelling that passes our shipped rule set. Every rewrite one rule accepts, another rejects. This turns unicorn/prefer-global-this off so the check is writable again.

The dead end

Each candidate spelling is rejected by a different shipped rule:

Spelling Rejected by
window.parent === window unicorn/prefer-global-this
parent === self unicorn/prefer-global-this
globalThis.parent === globalThis unicorn/no-unnecessary-global-this
parent === globalThis sonarjs/different-types-comparison

The last row is not a style opinion. lib.dom types parent, top, opener, and MessageEvent.source as Window, while globalThis is typeof globalThis. Those types do not overlap, so the type-aware rule is correct to call the comparison always-false — which is exactly why there is no legal spelling. In DOM code window is the typed global, not a legacy alias for globalThis.

Two rules already contradict each other

Independent of the DOM case, the preset ships both:

  • unicorn/prefer-global-this: "error" — demands globalThis
  • sonarjs/no-global-this: "error" — forbids globalThis

One rule requires what the other bans. Turning prefer-global-this off makes the pair consistent.

Resolution

unicorn/prefer-global-this: "off" in the quality concern, beside the other unicorn opinion rules that fight the stack.

unicorn/no-unnecessary-global-this stays at error, so the useful half of the pair is kept: globalThis.parent still trims to parent for plain member access. Only the comparison case was unspellable.

Why this matters to consumers

Without it, a consumer writing an iframe host bridge has two bad options: park a unicorn/prefer-global-this suppression in the baseline, or write parent === (globalThis as unknown as Window) — a cast whose only purpose is to satisfy linting. Both hide a real, correct DOM idiom behind noise.

Verification

  • 24/24 tests pass; eslint . clean.
  • New test/browser-framing-check.test.mjs pins the behavior empirically rather than by assertion:
    • proves upstream unicorn does reject window.parent === window, so the test fails if the conflict ever disappears upstream and this override becomes dead weight;
    • pins prefer-global-this off and no-unnecessary-global-this at error;
    • pins the prefer-global-this / sonarjs/no-global-this contradiction so a future re-enable trips a test rather than a consumer's lint run.
  • Confirmed end-to-end against a real consumer: with this config applied, window.parent === window lints clean where it previously errored.

Risk

Low and narrow. The change only removes a stylistic preference for globalThis over window/self. No autofix behavior changes, no type-aware rule is touched, and the rule that does the genuinely useful cleanup stays on. Consumers currently suppressing unicorn/prefer-global-this will find those entries become obsolete and can be pruned at their next baseline refresh.

Summary by CodeRabbit

  • Refactor

    • Updated code quality checks to support browser iframe detection patterns while retaining safeguards for unnecessary global-object usage.
  • Tests

    • Added coverage to verify iframe-related browser checks and ensure the configured code quality rules behave as expected.

… unspellable

`window.parent === window` is how DOM code asks "am I in an iframe?" before
posting to a host. Under the shipped rule set that check had no valid spelling:

  window.parent === window          -> unicorn/prefer-global-this
  parent === self                   -> unicorn/prefer-global-this
  globalThis.parent === globalThis  -> unicorn/no-unnecessary-global-this
  parent === globalThis             -> sonarjs/different-types-comparison

The last one is not a style opinion. lib.dom types `parent`, `top`, `opener`
and `MessageEvent.source` as `Window` while `globalThis` is `typeof globalThis`,
so the type-aware rule correctly calls the comparison always-false. Consumers
were left choosing between a suppression and an `as unknown as Window` bridge.

`prefer-global-this` also contradicts `sonarjs/no-global-this`, which we already
ship as an error: one demands the `globalThis` the other forbids.

Turn `prefer-global-this` off and keep `no-unnecessary-global-this`, so
`globalThis.parent` still trims to `parent` for plain member access.
@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The ESLint quality configuration disables unicorn/prefer-global-this and documents the exception. Browser framing tests verify the upstream rule behavior and confirm that unicorn/no-unnecessary-global-this remains enabled.

Changes

Browser framing rule configuration

Layer / File(s) Summary
Global-this rule configuration
src/eslint/quality.js
The quality configuration documents and disables unicorn/prefer-global-this while retaining unicorn/no-unnecessary-global-this.
Rule behavior validation
test/browser-framing-check.test.mjs
Tests verify the upstream framing diagnostic and the final configured states of the relevant Unicorn rules.

Estimated code review effort: 2 (Simple) | ~10 minutes

Poem

A rabbit checks the browser frame,
The global-this rules stay the same.
One rule rests; the tests confirm.
The quality checks now use the right form.
Hop, hop—the config is clear!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title uses the required conventional commit format and accurately describes the ESLint change for the browser framing check.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/eslint-browser-global-this-conflict
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch claude/eslint-browser-global-this-conflict

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/eslint/quality.js`:
- Around line 114-116: Update the comments describing the browser framing check
to use the correct polarity: window.parent === window identifies a top-level
window, not an embedded iframe. Revise the comments at src/eslint/quality.js
lines 114-116 and test/browser-framing-check.test.mjs lines 9-12; no behavior
changes are needed.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 1958dc11-c55f-4809-aab3-90e95cf4a270

📥 Commits

Reviewing files that changed from the base of the PR and between acac932 and facfeb0.

📒 Files selected for processing (2)
  • src/eslint/quality.js
  • test/browser-framing-check.test.mjs

Comment thread src/eslint/quality.js Outdated
@elibosley
Eli Bosley (elibosley) merged commit 87d747d into main Aug 3, 2026
2 of 3 checks passed

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
test/browser-framing-check.test.mjs (1)

41-60: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Exercise the final quality configuration.

These assertions verify only the last configured values for two rules. They do not lint window.parent === window with the shipped quality configuration. Another enabled rule or a later configuration entry could still reject the check while these assertions pass. Add an integration assertion that runs the framing source through the final flat configuration and verifies the expected diagnostics.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/browser-framing-check.test.mjs` around lines 41 - 60, Extend
test/browser-framing-check.test.mjs to lint the framing source through the
shipped final quality configuration, rather than only resolving rule values. Add
an integration assertion that checks window.parent === window produces the
expected diagnostics, while preserving the existing resolve assertions for
unicorn/no-unnecessary-global-this and unicorn/prefer-global-this.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@test/browser-framing-check.test.mjs`:
- Around line 41-60: Extend test/browser-framing-check.test.mjs to lint the
framing source through the shipped final quality configuration, rather than only
resolving rule values. Add an integration assertion that checks window.parent
=== window produces the expected diagnostics, while preserving the existing
resolve assertions for unicorn/no-unnecessary-global-this and
unicorn/prefer-global-this.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 29dc15b3-eb98-4619-83c0-af69f7e0641c

📥 Commits

Reviewing files that changed from the base of the PR and between facfeb0 and 7f93a98.

📒 Files selected for processing (2)
  • src/eslint/quality.js
  • test/browser-framing-check.test.mjs
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/eslint/quality.js

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.

1 participant