websocket.ts 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. /**
  2. * @license
  3. * Copyright Google Inc. All Rights Reserved.
  4. *
  5. * Use of this source code is governed by an MIT-style license that can be
  6. * found in the LICENSE file at https://angular.io/license
  7. */
  8. // we have to patch the instance since the proto is non-configurable
  9. export function apply(api: _ZonePrivate, _global: any) {
  10. const {ADD_EVENT_LISTENER_STR, REMOVE_EVENT_LISTENER_STR} = api.getGlobalObjects()!;
  11. const WS = (<any>_global).WebSocket;
  12. // On Safari window.EventTarget doesn't exist so need to patch WS add/removeEventListener
  13. // On older Chrome, no need since EventTarget was already patched
  14. if (!(<any>_global).EventTarget) {
  15. api.patchEventTarget(_global, [WS.prototype]);
  16. }
  17. (<any>_global).WebSocket = function(x: any, y: any) {
  18. const socket = arguments.length > 1 ? new WS(x, y) : new WS(x);
  19. let proxySocket: any;
  20. let proxySocketProto: any;
  21. // Safari 7.0 has non-configurable own 'onmessage' and friends properties on the socket instance
  22. const onmessageDesc = api.ObjectGetOwnPropertyDescriptor(socket, 'onmessage');
  23. if (onmessageDesc && onmessageDesc.configurable === false) {
  24. proxySocket = api.ObjectCreate(socket);
  25. // socket have own property descriptor 'onopen', 'onmessage', 'onclose', 'onerror'
  26. // but proxySocket not, so we will keep socket as prototype and pass it to
  27. // patchOnProperties method
  28. proxySocketProto = socket;
  29. [ADD_EVENT_LISTENER_STR, REMOVE_EVENT_LISTENER_STR, 'send', 'close'].forEach(function(
  30. propName) {
  31. proxySocket[propName] = function() {
  32. const args = api.ArraySlice.call(arguments);
  33. if (propName === ADD_EVENT_LISTENER_STR || propName === REMOVE_EVENT_LISTENER_STR) {
  34. const eventName = args.length > 0 ? args[0] : undefined;
  35. if (eventName) {
  36. const propertySymbol = Zone.__symbol__('ON_PROPERTY' + eventName);
  37. socket[propertySymbol] = proxySocket[propertySymbol];
  38. }
  39. }
  40. return socket[propName].apply(socket, args);
  41. };
  42. });
  43. } else {
  44. // we can patch the real socket
  45. proxySocket = socket;
  46. }
  47. api.patchOnProperties(proxySocket, ['close', 'error', 'message', 'open'], proxySocketProto);
  48. return proxySocket;
  49. };
  50. const globalWebSocket = _global['WebSocket'];
  51. for (const prop in WS) {
  52. globalWebSocket[prop] = WS[prop];
  53. }
  54. }