Skip to content

Commit 94a1fc5

Browse files
Copilotmattcosta7
andcommitted
Improve ResizeObserver detection with better heuristics
- Add isLikelyResizeObserver function to identify ResizeObserver instances - Exclude IntersectionObserver, MutationObserver, and other observer types - Add tests to verify IntersectionObserver and MutationObserver are not flagged - Fix linting issues and improve code comments Co-authored-by: mattcosta7 <8616962+mattcosta7@users.noreply.github.com>
1 parent c957f12 commit 94a1fc5

File tree

2 files changed

+52
-4
lines changed

2 files changed

+52
-4
lines changed

lib/rules/prefer-observers.js

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,43 @@ function isDocumentRoot(node) {
2929
return false
3030
}
3131

32+
/**
33+
* Checks if a node is likely a ResizeObserver instance
34+
* Checks for patterns like:
35+
* - new ResizeObserver(...).observe(...)
36+
* - resizeObserverVariable.observe(...)
37+
* - observer.observe(...) when not explicitly another observer type
38+
* This is a heuristic approach since we can't always determine the exact type
39+
*/
40+
function isLikelyResizeObserver(node) {
41+
// Check for new ResizeObserver(...).observe(...) pattern
42+
if (node.type === 'NewExpression' && node.callee.type === 'Identifier' && node.callee.name === 'ResizeObserver') {
43+
return true
44+
}
45+
46+
// Check for variable names that suggest ResizeObserver
47+
if (node.type === 'Identifier') {
48+
const name = node.name.toLowerCase()
49+
50+
// Exclude other observer types explicitly
51+
if (
52+
name.includes('intersection') ||
53+
name.includes('mutation') ||
54+
name.includes('performance') ||
55+
name.includes('reportingobserver')
56+
) {
57+
return false
58+
}
59+
60+
// Match explicit ResizeObserver or generic "observer" variable names
61+
if (name.includes('resizeobserver') || name.includes('resize') || name === 'observer' || name.includes('obs')) {
62+
return true
63+
}
64+
}
65+
66+
return false
67+
}
68+
3269
export default {
3370
meta: {
3471
type: 'suggestion',
@@ -63,8 +100,8 @@ export default {
63100
if (name.type !== 'Literal') return
64101
if (!(name.value in observerMap)) return
65102

66-
// Allow window events (window.resize for viewport detection)
67-
// Note: orientationchange is not in observerMap but this check is defensive
103+
// Allow window events for viewport-level detection
104+
// This prevents flagging window.resize and window.scroll which are appropriate for viewport detection
68105
if (node.callee.object && isWindowObject(node.callee.object)) {
69106
return
70107
}
@@ -76,12 +113,15 @@ export default {
76113
})
77114
},
78115

79-
// Check ResizeObserver.observe() calls
116+
// Check ResizeObserver.observe() calls on document root elements
80117
['CallExpression[callee.property.name="observe"]']: function (node) {
81-
// Check if this is a ResizeObserver instance
82118
const callee = node.callee
83119
if (!callee.object) return
84120

121+
// Only check if this appears to be a ResizeObserver
122+
// This prevents false positives for IntersectionObserver, MutationObserver, etc.
123+
if (!isLikelyResizeObserver(callee.object)) return
124+
85125
// Get the first argument (the element being observed)
86126
const [observedElement] = node.arguments
87127
if (!observedElement) return

tests/prefer-observers.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,14 @@ ruleTester.run('prefer-observers', rule, {
2727
{
2828
code: 'const observer = new ResizeObserver(() => {}); const el = document.querySelector(".item"); observer.observe(el)',
2929
},
30+
// IntersectionObserver on document root is valid (not flagged by this rule)
31+
{
32+
code: 'const intersectionObserver = new IntersectionObserver(() => {}); intersectionObserver.observe(document.documentElement)',
33+
},
34+
// MutationObserver on document root is valid (not flagged by this rule)
35+
{
36+
code: 'const mutationObserver = new MutationObserver(() => {}); mutationObserver.observe(document.documentElement)',
37+
},
3038
],
3139
invalid: [
3240
{

0 commit comments

Comments
 (0)