Prerequisites
Describe the issue
Marqueefy registers a global window.resize event listener but never removes it during dispose(). While this works for multi page applications, because on page load the event is cleared. But when used in any SPA or with anything like Stimulus/Turbo the event stays bound even after calling dispose();
And this resize listener continues to fire and calls refresh(), leading to runtime errors.
This results in errors like:
Uncaught TypeError: Cannot destructure property 'direction' of 'this._config' as it is null
Reduced test cases
Steps to Reproduce
-
Create a Marqueefy instance
-
Call dispose() on the instance
-
Resize the browser window
Expected Behavior
-
dispose() should fully clean up the instance
-
Any global event listeners registered by the instance should be removed
-
No errors should occur after disposal
Actual Behavior
-
The resize event listener remains active
-
On resize, it calls this.refresh()
-
Since dispose() nulls internal properties, refresh() throws error
The root cause is in the _setListeners() method, where an anonymous arrow function is used to bind the listener:
window.addEventListener("resize", () => this.refresh(), {
passive: true
});
No reference to the function is stored and thus it's not removed in dispose either. Ideally we should do something like this
this._resizeHandler = () => this.refresh();
window.addEventListener("resize", this._resizeHandler, { passive: true });
And then override the dispose method
dispose() {
window.removeEventListener("resize", this._resizeHandler);
this._resizeHandler = null;
super.dispose();
}
What operating system(s) are you seeing the problem on?
Windows
What browser(s) are you seeing the problem on?
Chrome
What version of Marqueefy are you using?
1.0.3
Prerequisites
Describe the issue
Marqueefy registers a global window.resize event listener but never removes it during dispose(). While this works for multi page applications, because on page load the event is cleared. But when used in any SPA or with anything like Stimulus/Turbo the event stays bound even after calling dispose();
And this resize listener continues to fire and calls refresh(), leading to runtime errors.
This results in errors like:
Reduced test cases
Steps to Reproduce
Create a Marqueefy instance
Call dispose() on the instance
Resize the browser window
Expected Behavior
dispose() should fully clean up the instance
Any global event listeners registered by the instance should be removed
No errors should occur after disposal
Actual Behavior
The resize event listener remains active
On resize, it calls this.refresh()
Since dispose() nulls internal properties, refresh() throws error
The root cause is in the _setListeners() method, where an anonymous arrow function is used to bind the listener:
No reference to the function is stored and thus it's not removed in dispose either. Ideally we should do something like this
And then override the dispose method
What operating system(s) are you seeing the problem on?
Windows
What browser(s) are you seeing the problem on?
Chrome
What version of Marqueefy are you using?
1.0.3