diff --git a/lib/transport.js b/lib/transport.js index eb864dc6d..a8800771b 100644 --- a/lib/transport.js +++ b/lib/transport.js @@ -1,5 +1,6 @@ const parser = require("engine.io-parser"); const Emitter = require("component-emitter"); +const debug = require("debug")("engine.io-client:transport"); class Transport extends Emitter { /** @@ -70,7 +71,8 @@ class Transport extends Emitter { if ("open" === this.readyState) { this.write(packets); } else { - throw new Error("Transport not open"); + // this might happen if the transport was silently closed in the beforeunload event handler + debug("transport is not open, discarding packets"); } } diff --git a/test/connection.js b/test/connection.js index 39d6fdf50..86e0e8af9 100644 --- a/test/connection.js +++ b/test/connection.js @@ -188,4 +188,34 @@ describe("connection", function() { }); }); } + + if (env.browser && typeof addEventListener === "function") { + it("should close the socket when receiving a beforeunload event", done => { + const socket = new Socket(); + + const createEvent = name => { + if (typeof Event === "function") { + return new Event(name); + } else { + // polyfill for IE + const event = document.createEvent("Event"); + event.initEvent(name, true, true); + return event; + } + }; + + socket.on("open", () => { + const handler = () => { + expect(socket.transport.readyState).to.eql("closed"); + expect(() => socket.write("ignored")).to.not.throwException(); + + removeEventListener("beforeunload", handler, false); + done(); + }; + + addEventListener("beforeunload", handler, false); + dispatchEvent(createEvent("beforeunload")); + }); + }); + } });