zone-patch-rxjs.js 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. 'use strict';
  2. /**
  3. * @license Angular v<unknown>
  4. * (c) 2010-2025 Google LLC. https://angular.io/
  5. * License: MIT
  6. */
  7. import { Observable, Subscription, Subscriber } from 'rxjs';
  8. function patchRxJs(Zone) {
  9. Zone.__load_patch('rxjs', (global, Zone, api) => {
  10. const symbol = Zone.__symbol__;
  11. const nextSource = 'rxjs.Subscriber.next';
  12. const errorSource = 'rxjs.Subscriber.error';
  13. const completeSource = 'rxjs.Subscriber.complete';
  14. const ObjectDefineProperties = Object.defineProperties;
  15. const patchObservable = function () {
  16. const ObservablePrototype = Observable.prototype;
  17. const _symbolSubscribe = symbol('_subscribe');
  18. const _subscribe = (ObservablePrototype[_symbolSubscribe] = ObservablePrototype._subscribe);
  19. ObjectDefineProperties(Observable.prototype, {
  20. _zone: { value: null, writable: true, configurable: true },
  21. _zoneSource: { value: null, writable: true, configurable: true },
  22. _zoneSubscribe: { value: null, writable: true, configurable: true },
  23. source: {
  24. configurable: true,
  25. get: function () {
  26. return this._zoneSource;
  27. },
  28. set: function (source) {
  29. this._zone = Zone.current;
  30. this._zoneSource = source;
  31. },
  32. },
  33. _subscribe: {
  34. configurable: true,
  35. get: function () {
  36. if (this._zoneSubscribe) {
  37. return this._zoneSubscribe;
  38. }
  39. else if (this.constructor === Observable) {
  40. return _subscribe;
  41. }
  42. const proto = Object.getPrototypeOf(this);
  43. return proto && proto._subscribe;
  44. },
  45. set: function (subscribe) {
  46. this._zone = Zone.current;
  47. if (!subscribe) {
  48. this._zoneSubscribe = subscribe;
  49. }
  50. else {
  51. this._zoneSubscribe = function () {
  52. if (this._zone && this._zone !== Zone.current) {
  53. const tearDown = this._zone.run(subscribe, this, arguments);
  54. if (typeof tearDown === 'function') {
  55. const zone = this._zone;
  56. return function () {
  57. if (zone !== Zone.current) {
  58. return zone.run(tearDown, this, arguments);
  59. }
  60. return tearDown.apply(this, arguments);
  61. };
  62. }
  63. else {
  64. return tearDown;
  65. }
  66. }
  67. else {
  68. return subscribe.apply(this, arguments);
  69. }
  70. };
  71. }
  72. },
  73. },
  74. subjectFactory: {
  75. get: function () {
  76. return this._zoneSubjectFactory;
  77. },
  78. set: function (factory) {
  79. const zone = this._zone;
  80. this._zoneSubjectFactory = function () {
  81. if (zone && zone !== Zone.current) {
  82. return zone.run(factory, this, arguments);
  83. }
  84. return factory.apply(this, arguments);
  85. };
  86. },
  87. },
  88. });
  89. };
  90. api.patchMethod(Observable.prototype, 'lift', (delegate) => (self, args) => {
  91. const observable = delegate.apply(self, args);
  92. if (observable.operator) {
  93. observable.operator._zone = Zone.current;
  94. api.patchMethod(observable.operator, 'call', (operatorDelegate) => (operatorSelf, operatorArgs) => {
  95. if (operatorSelf._zone && operatorSelf._zone !== Zone.current) {
  96. return operatorSelf._zone.run(operatorDelegate, operatorSelf, operatorArgs);
  97. }
  98. return operatorDelegate.apply(operatorSelf, operatorArgs);
  99. });
  100. }
  101. return observable;
  102. });
  103. const patchSubscription = function () {
  104. ObjectDefineProperties(Subscription.prototype, {
  105. _zone: { value: null, writable: true, configurable: true },
  106. _zoneUnsubscribe: { value: null, writable: true, configurable: true },
  107. _unsubscribe: {
  108. get: function () {
  109. if (this._zoneUnsubscribe || this._zoneUnsubscribeCleared) {
  110. return this._zoneUnsubscribe;
  111. }
  112. const proto = Object.getPrototypeOf(this);
  113. return proto && proto._unsubscribe;
  114. },
  115. set: function (unsubscribe) {
  116. this._zone = Zone.current;
  117. if (!unsubscribe) {
  118. this._zoneUnsubscribe = unsubscribe;
  119. // In some operator such as `retryWhen`, the _unsubscribe
  120. // method will be set to null, so we need to set another flag
  121. // to tell that we should return null instead of finding
  122. // in the prototype chain.
  123. this._zoneUnsubscribeCleared = true;
  124. }
  125. else {
  126. this._zoneUnsubscribeCleared = false;
  127. this._zoneUnsubscribe = function () {
  128. if (this._zone && this._zone !== Zone.current) {
  129. return this._zone.run(unsubscribe, this, arguments);
  130. }
  131. else {
  132. return unsubscribe.apply(this, arguments);
  133. }
  134. };
  135. }
  136. },
  137. },
  138. });
  139. };
  140. const patchSubscriber = function () {
  141. const next = Subscriber.prototype.next;
  142. const error = Subscriber.prototype.error;
  143. const complete = Subscriber.prototype.complete;
  144. Object.defineProperty(Subscriber.prototype, 'destination', {
  145. configurable: true,
  146. get: function () {
  147. return this._zoneDestination;
  148. },
  149. set: function (destination) {
  150. this._zone = Zone.current;
  151. this._zoneDestination = destination;
  152. },
  153. });
  154. // patch Subscriber.next to make sure it run
  155. // into SubscriptionZone
  156. Subscriber.prototype.next = function () {
  157. const currentZone = Zone.current;
  158. const subscriptionZone = this._zone;
  159. // for performance concern, check Zone.current
  160. // equal with this._zone(SubscriptionZone) or not
  161. if (subscriptionZone && subscriptionZone !== currentZone) {
  162. return subscriptionZone.run(next, this, arguments, nextSource);
  163. }
  164. else {
  165. return next.apply(this, arguments);
  166. }
  167. };
  168. Subscriber.prototype.error = function () {
  169. const currentZone = Zone.current;
  170. const subscriptionZone = this._zone;
  171. // for performance concern, check Zone.current
  172. // equal with this._zone(SubscriptionZone) or not
  173. if (subscriptionZone && subscriptionZone !== currentZone) {
  174. return subscriptionZone.run(error, this, arguments, errorSource);
  175. }
  176. else {
  177. return error.apply(this, arguments);
  178. }
  179. };
  180. Subscriber.prototype.complete = function () {
  181. const currentZone = Zone.current;
  182. const subscriptionZone = this._zone;
  183. // for performance concern, check Zone.current
  184. // equal with this._zone(SubscriptionZone) or not
  185. if (subscriptionZone && subscriptionZone !== currentZone) {
  186. return subscriptionZone.run(complete, this, arguments, completeSource);
  187. }
  188. else {
  189. return complete.call(this);
  190. }
  191. };
  192. };
  193. patchObservable();
  194. patchSubscription();
  195. patchSubscriber();
  196. });
  197. }
  198. patchRxJs(Zone);