Reputation: 919
Rather than focus on the why, let's focus on the what.
I wanted to swap out the native WebSocket class with a user-defined class called WebSocketProxy. This way any time the code on the page attempted to create a new WebSocket it would actually be returned a new WebSocketProxy (I have my reasons).
To test this in it's most minimal form I wrote:
class WebSocketProxy extends WebSocket {
constructor(url: string, protocols?: string | string[]) {
super(url, protocols);
/* Add hooks here. */
}
}
WebSocket = WebSocketProxy; // Swap native WebSocket with WebSocketProxy.
The TypeScript compiler (Visual Studio 2015) translated this into:
var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var WebSocketProxy = (function (_super) {
__extends(WebSocketProxy, _super);
function WebSocketProxy(url, protocols) {
_super.call(this, url, protocols); // This is what causes the error.
/* Add hooks here. */
}
return WebSocketProxy;
})(WebSocket);
WebSocket = WebSocketProxy; // Swap native WebSocket with WebSocketProxy.
Thinking this would surely work, I was disappointed when I copied this into my Scratchpad in Firefox and executed.
TypeError: Constructor WebSocket requires 'new'
I got a similar (but more useful) error when doing the same in Chrome:
Uncaught TypeError: Failed to construct 'WebSocket': Please use the 'new' operator, this DOM object constructor cannot be called as a function.
I didn't get this error in Edge or Internet Explorer.
This behaviour leaves me wondering:
Upvotes: 2
Views: 1864
Reputation: 275819
How else should I produce my pseudo-WebSocket? (Perhaps implement instead of extend?)
You can do the following quite easily:
const OrigWebSocket = WebSocket;
WebSocket = function(url: string, protocols?: string | string[]){
const self = new OrigWebSocket(url,protocols);
/* Add hooks here. */
return self;
} as any;
Is this strictly a Chrome/Firefox issue
Chrome/Firefox
Is attempting to extend a native type simply bad practice, or is this a special case
Special case
Why is calling WebSocket as a function forbidden in Chrome and Firefox?
To prevent user error ( WebSocket
when they meant new WebSocket(
)
This is very similar to https://github.com/sinonjs/sinon/issues/743 basically it is very stingy about being called with new
so not easy to spy on.
Upvotes: 2