1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  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. import {patchEventTarget} from '../common/events';
  9. import {ADD_EVENT_LISTENER_STR, ArraySlice, ObjectCreate, ObjectGetOwnPropertyDescriptor, patchOnProperties, REMOVE_EVENT_LISTENER_STR} from '../common/utils';
  10. // we have to patch the instance since the proto is non-configurable
  11. export function apply(api: _ZonePrivate, _global: any) {
  12. const WS = (<any>_global).WebSocket;
  13. // On Safari window.EventTarget doesn't exist so need to patch WS add/removeEventListener
  14. // On older Chrome, no need since EventTarget was already patched
  15. if (!(<any>_global).EventTarget) {
  16. patchEventTarget(_global, [WS.prototype]);
  17. }
  18. (<any>_global).WebSocket = function(x: any, y: any) {
  19. const socket = arguments.length > 1 ? new WS(x, y) : new WS(x);
  20. let proxySocket: any;
  21. let proxySocketProto: any;
  22. // Safari 7.0 has non-configurable own 'onmessage' and friends properties on the socket instance
  23. const onmessageDesc = ObjectGetOwnPropertyDescriptor(socket, 'onmessage');
  24. if (onmessageDesc && onmessageDesc.configurable === false) {
  25. proxySocket = ObjectCreate(socket);
  26. // socket have own property descriptor 'onopen', 'onmessage', 'onclose', 'onerror'
  27. // but proxySocket not, so we will keep socket as prototype and pass it to
  28. // patchOnProperties method
  29. proxySocketProto = socket;
  30. [ADD_EVENT_LISTENER_STR, REMOVE_EVENT_LISTENER_STR, 'send', 'close'].forEach(function(
  31. propName) {
  32. proxySocket[propName] = function() {
  33. const args = ArraySlice.call(arguments);
  34. if (propName === ADD_EVENT_LISTENER_STR || propName === REMOVE_EVENT_LISTENER_STR) {
  35. const eventName = args.length > 0 ? args[0] : undefined;
  36. if (eventName) {
  37. const propertySymbol = Zone.__symbol__('ON_PROPERTY' + eventName);
  38. socket[propertySymbol] = proxySocket[propertySymbol];
  39. }
  40. }
  41. return socket[propName].apply(socket, args);
  42. };
  43. });
  44. } else {
  45. // we can patch the real socket
  46. proxySocket = socket;
  47. }
  48. patchOnProperties(proxySocket, ['close', 'error', 'message', 'open'], proxySocketProto);
  49. return proxySocket;
  50. };
  51. const globalWebSocket = _global['WebSocket'];
  52. for (const prop in WS) {
  53. globalWebSocket[prop] = WS[prop];
  54. }
  55. }