Skip to content

Commit 84607a4

Browse files
authored
ensure visibilitychange does not connect if never connected (#6621)
The fix from #6579 did not handle the case where the socket was never connected in the first place. Closes #6620. Relates to #6578.
1 parent f286d69 commit 84607a4

2 files changed

Lines changed: 41 additions & 1 deletion

File tree

assets/js/phoenix/socket.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,10 @@ export default class Socket {
126126
this.establishedConnections = 0
127127
this.defaultEncoder = Serializer.encode.bind(Serializer)
128128
this.defaultDecoder = Serializer.decode.bind(Serializer)
129-
this.closeWasClean = false
129+
// We start with closeWasClean true to avoid the visibility change
130+
// logic from connecting if the socket was never connected in the first place.
131+
// transportConnect sets it to false on open.
132+
this.closeWasClean = true
130133
this.disconnecting = false
131134
this.binaryType = opts.binaryType || "arraybuffer"
132135
this.connectClock = 1

assets/test/socket_test.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,43 @@ describe("with transports", function (){
104104
})
105105
})
106106

107+
describe("visibilitychange", function (){
108+
it("does not connect a socket that was never connected", function (){
109+
socket = new Socket("/socket")
110+
const teardownSpy = jest.spyOn(socket, "teardown")
111+
112+
Object.defineProperty(document, "visibilityState", {value: "hidden", writable: true})
113+
window.dispatchEvent(new Event("visibilitychange"))
114+
115+
Object.defineProperty(document, "visibilityState", {value: "visible", writable: true})
116+
window.dispatchEvent(new Event("visibilitychange"))
117+
118+
expect(teardownSpy).not.toHaveBeenCalled()
119+
})
120+
121+
it("reconnects on visibility change after unclean close", function (){
122+
socket = new Socket("/socket")
123+
socket.closeWasClean = false
124+
const teardownSpy = jest.spyOn(socket, "teardown")
125+
126+
Object.defineProperty(document, "visibilityState", {value: "visible", writable: true})
127+
window.dispatchEvent(new Event("visibilitychange"))
128+
129+
expect(teardownSpy).toHaveBeenCalledTimes(1)
130+
})
131+
132+
it("does not reconnect on visibility change after clean close", function (){
133+
socket = new Socket("/socket")
134+
socket.closeWasClean = true
135+
const teardownSpy = jest.spyOn(socket, "teardown")
136+
137+
Object.defineProperty(document, "visibilityState", {value: "visible", writable: true})
138+
window.dispatchEvent(new Event("visibilitychange"))
139+
140+
expect(teardownSpy).not.toHaveBeenCalled()
141+
})
142+
})
143+
107144
describe("protocol", function (){
108145
beforeEach(function (){
109146
socket = new Socket("/socket")

0 commit comments

Comments
 (0)