From 3f3a6f991404ef601252193382d2d2029cff6c45 Mon Sep 17 00:00:00 2001 From: Damien Arrachequesne Date: Thu, 16 Apr 2020 16:08:37 +0200 Subject: [PATCH] fix: use globalThis polyfill instead of self/global (#634) In order to fix the "self is not defined" issues in Android 8 and React Native. Fixes https://github.com/socketio/engine.io-client/issues/611, https://github.com/socketio/engine.io-client/issues/626 Closes https://github.com/socketio/engine.io-client/pull/627 --- lib/globalThis.browser.js | 9 ++++ lib/globalThis.js | 1 + lib/transports/polling-jsonp.js | 3 +- lib/transports/polling-xhr.js | 3 +- .../websocket-constructor.browser.js | 6 +++ lib/transports/websocket-constructor.js | 4 ++ lib/transports/websocket.js | 43 ++++--------------- lib/xmlhttprequest.js | 3 +- package.json | 4 +- 9 files changed, 38 insertions(+), 38 deletions(-) create mode 100644 lib/globalThis.browser.js create mode 100644 lib/globalThis.js create mode 100644 lib/transports/websocket-constructor.browser.js create mode 100644 lib/transports/websocket-constructor.js diff --git a/lib/globalThis.browser.js b/lib/globalThis.browser.js new file mode 100644 index 000000000..e08544075 --- /dev/null +++ b/lib/globalThis.browser.js @@ -0,0 +1,9 @@ +module.exports = (() => { + if (typeof self !== "undefined") { + return self; + } else if (typeof window !== "undefined") { + return window; + } else { + return Function("return this")(); + } +})(); diff --git a/lib/globalThis.js b/lib/globalThis.js new file mode 100644 index 000000000..e1465f205 --- /dev/null +++ b/lib/globalThis.js @@ -0,0 +1 @@ +module.exports = global; diff --git a/lib/transports/polling-jsonp.js b/lib/transports/polling-jsonp.js index d7b231b31..8625611fa 100644 --- a/lib/transports/polling-jsonp.js +++ b/lib/transports/polling-jsonp.js @@ -1,4 +1,5 @@ const Polling = require("./polling"); +const globalThis = require("../globalThis"); const rNewline = /\n/g; const rEscapedNewline = /\\n/g; @@ -31,7 +32,7 @@ class JSONPPolling extends Polling { // we do this here (lazily) to avoid unneeded global pollution if (!callbacks) { // we need to consider multiple engines in the same page - callbacks = global.___eio = global.___eio || []; + callbacks = globalThis.___eio = globalThis.___eio || []; } // callback identifier diff --git a/lib/transports/polling-xhr.js b/lib/transports/polling-xhr.js index 93648a7f7..2f669987f 100755 --- a/lib/transports/polling-xhr.js +++ b/lib/transports/polling-xhr.js @@ -4,6 +4,7 @@ const XMLHttpRequest = require("xmlhttprequest-ssl"); const Polling = require("./polling"); const Emitter = require("component-emitter"); const { pick } = require("../util"); +const globalThis = require("../globalThis"); const debug = require("debug")("engine.io-client:polling-xhr"); @@ -361,7 +362,7 @@ if (typeof document !== "undefined") { if (typeof attachEvent === "function") { attachEvent("onunload", unloadHandler); } else if (typeof addEventListener === "function") { - const terminationEvent = "onpagehide" in self ? "pagehide" : "unload"; + const terminationEvent = "onpagehide" in globalThis ? "pagehide" : "unload"; addEventListener(terminationEvent, unloadHandler, false); } } diff --git a/lib/transports/websocket-constructor.browser.js b/lib/transports/websocket-constructor.browser.js new file mode 100644 index 000000000..4970e27eb --- /dev/null +++ b/lib/transports/websocket-constructor.browser.js @@ -0,0 +1,6 @@ +const globalThis = require("../globalThis"); + +module.exports = { + WebSocket: globalThis.WebSocket || globalThis.MozWebSocket, + usingBrowserWebSocket: true +}; diff --git a/lib/transports/websocket-constructor.js b/lib/transports/websocket-constructor.js new file mode 100644 index 000000000..0a1833ffa --- /dev/null +++ b/lib/transports/websocket-constructor.js @@ -0,0 +1,4 @@ +module.exports = { + WebSocket: require("ws"), + usingBrowserWebSocket: false +}; diff --git a/lib/transports/websocket.js b/lib/transports/websocket.js index 04eaa088a..dca9c46a6 100644 --- a/lib/transports/websocket.js +++ b/lib/transports/websocket.js @@ -3,31 +3,10 @@ const parser = require("engine.io-parser"); const parseqs = require("parseqs"); const yeast = require("yeast"); const { pick } = require("../util"); +const { WebSocket, usingBrowserWebSocket } = require("./websocket-constructor"); const debug = require("debug")("engine.io-client:websocket"); -let BrowserWebSocket, NodeWebSocket; - -if (typeof WebSocket !== "undefined") { - BrowserWebSocket = WebSocket; -} else if (typeof self !== "undefined") { - BrowserWebSocket = self.WebSocket || self.MozWebSocket; -} - -if (typeof window === "undefined") { - try { - NodeWebSocket = require("ws"); - } catch (e) {} -} - -/** - * Get either the `WebSocket` or `MozWebSocket` globals - * in the browser or try to resolve WebSocket-compatible - * interface exposed by `ws` for Node-like environment. - */ - -let WebSocketImpl = BrowserWebSocket || NodeWebSocket; - class WS extends Transport { /** * WebSocket transport constructor. @@ -42,10 +21,6 @@ class WS extends Transport { if (forceBase64) { this.supportsBinary = false; } - this.usingBrowserWebSocket = BrowserWebSocket && !opts.forceNode; - if (!this.usingBrowserWebSocket) { - WebSocketImpl = NodeWebSocket; - } // WebSockets support binary this.supportsBinary = true; } @@ -91,11 +66,11 @@ class WS extends Transport { try { this.ws = - this.usingBrowserWebSocket && !this.opts.isReactNative + usingBrowserWebSocket && !this.opts.isReactNative ? protocols - ? new WebSocketImpl(uri, protocols) - : new WebSocketImpl(uri) - : new WebSocketImpl(uri, protocols, opts); + ? new WebSocket(uri, protocols) + : new WebSocket(uri) + : new WebSocket(uri, protocols, opts); } catch (err) { return this.emit("error", err); } @@ -156,7 +131,7 @@ class WS extends Transport { parser.encodePacket(packet, self.supportsBinary, function(data) { // always create a new object (GH-437) const opts = {}; - if (!self.usingBrowserWebSocket) { + if (!usingBrowserWebSocket) { if (packet.options) { opts.compress = packet.options.compress; } @@ -176,7 +151,7 @@ class WS extends Transport { // have a chance of informing us about it yet, in that case send will // throw an error try { - if (self.usingBrowserWebSocket) { + if (usingBrowserWebSocket) { // TypeError is thrown when passing the second argument on Safari self.ws.send(data); } else { @@ -278,8 +253,8 @@ class WS extends Transport { */ check() { return ( - !!WebSocketImpl && - !("__initialize" in WebSocketImpl && this.name === WS.prototype.name) + !!WebSocket && + !("__initialize" in WebSocket && this.name === WS.prototype.name) ); } } diff --git a/lib/xmlhttprequest.js b/lib/xmlhttprequest.js index c8bdd9331..dab4fdc4b 100644 --- a/lib/xmlhttprequest.js +++ b/lib/xmlhttprequest.js @@ -1,6 +1,7 @@ // browser shim for xmlhttprequest module const hasCORS = require("has-cors"); +const globalThis = require("./globalThis"); module.exports = function(opts) { const xdomain = opts.xdomain; @@ -31,7 +32,7 @@ module.exports = function(opts) { if (!xdomain) { try { - return new self[["Active"].concat("Object").join("X")]( + return new globalThis[["Active"].concat("Object").join("X")]( "Microsoft.XMLHTTP" ); } catch (e) {} diff --git a/package.json b/package.json index cfcdc76a6..9cea8161f 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,9 @@ }, "browser": { "ws": false, - "xmlhttprequest-ssl": "./lib/xmlhttprequest.js" + "xmlhttprequest-ssl": "./lib/xmlhttprequest.js", + "./lib/transports/websocket-constructor.js": "./lib/transports/websocket-constructor.browser.js", + "./lib/globalThis.js": "./lib/globalThis.browser.js" }, "repository": { "type": "git",