zone-legacy.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  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. (function (global, factory) {
  9. typeof exports === 'object' && typeof module !== 'undefined' ? factory() :
  10. typeof define === 'function' && define.amd ? define(factory) :
  11. (factory());
  12. }(this, (function () { 'use strict';
  13. /**
  14. * @license
  15. * Copyright Google Inc. All Rights Reserved.
  16. *
  17. * Use of this source code is governed by an MIT-style license that can be
  18. * found in the LICENSE file at https://angular.io/license
  19. */
  20. function eventTargetLegacyPatch(_global, api) {
  21. var _a = api.getGlobalObjects(), eventNames = _a.eventNames, globalSources = _a.globalSources, zoneSymbolEventNames = _a.zoneSymbolEventNames, TRUE_STR = _a.TRUE_STR, FALSE_STR = _a.FALSE_STR, ZONE_SYMBOL_PREFIX = _a.ZONE_SYMBOL_PREFIX;
  22. var WTF_ISSUE_555 = 'Anchor,Area,Audio,BR,Base,BaseFont,Body,Button,Canvas,Content,DList,Directory,Div,Embed,FieldSet,Font,Form,Frame,FrameSet,HR,Head,Heading,Html,IFrame,Image,Input,Keygen,LI,Label,Legend,Link,Map,Marquee,Media,Menu,Meta,Meter,Mod,OList,Object,OptGroup,Option,Output,Paragraph,Pre,Progress,Quote,Script,Select,Source,Span,Style,TableCaption,TableCell,TableCol,Table,TableRow,TableSection,TextArea,Title,Track,UList,Unknown,Video';
  23. var NO_EVENT_TARGET = 'ApplicationCache,EventSource,FileReader,InputMethodContext,MediaController,MessagePort,Node,Performance,SVGElementInstance,SharedWorker,TextTrack,TextTrackCue,TextTrackList,WebKitNamedFlow,Window,Worker,WorkerGlobalScope,XMLHttpRequest,XMLHttpRequestEventTarget,XMLHttpRequestUpload,IDBRequest,IDBOpenDBRequest,IDBDatabase,IDBTransaction,IDBCursor,DBIndex,WebSocket'
  24. .split(',');
  25. var EVENT_TARGET = 'EventTarget';
  26. var apis = [];
  27. var isWtf = _global['wtf'];
  28. var WTF_ISSUE_555_ARRAY = WTF_ISSUE_555.split(',');
  29. if (isWtf) {
  30. // Workaround for: https://github.com/google/tracing-framework/issues/555
  31. apis = WTF_ISSUE_555_ARRAY.map(function (v) { return 'HTML' + v + 'Element'; }).concat(NO_EVENT_TARGET);
  32. }
  33. else if (_global[EVENT_TARGET]) {
  34. apis.push(EVENT_TARGET);
  35. }
  36. else {
  37. // Note: EventTarget is not available in all browsers,
  38. // if it's not available, we instead patch the APIs in the IDL that inherit from EventTarget
  39. apis = NO_EVENT_TARGET;
  40. }
  41. var isDisableIECheck = _global['__Zone_disable_IE_check'] || false;
  42. var isEnableCrossContextCheck = _global['__Zone_enable_cross_context_check'] || false;
  43. var ieOrEdge = api.isIEOrEdge();
  44. var ADD_EVENT_LISTENER_SOURCE = '.addEventListener:';
  45. var FUNCTION_WRAPPER = '[object FunctionWrapper]';
  46. var BROWSER_TOOLS = 'function __BROWSERTOOLS_CONSOLE_SAFEFUNC() { [native code] }';
  47. // predefine all __zone_symbol__ + eventName + true/false string
  48. for (var i = 0; i < eventNames.length; i++) {
  49. var eventName = eventNames[i];
  50. var falseEventName = eventName + FALSE_STR;
  51. var trueEventName = eventName + TRUE_STR;
  52. var symbol = ZONE_SYMBOL_PREFIX + falseEventName;
  53. var symbolCapture = ZONE_SYMBOL_PREFIX + trueEventName;
  54. zoneSymbolEventNames[eventName] = {};
  55. zoneSymbolEventNames[eventName][FALSE_STR] = symbol;
  56. zoneSymbolEventNames[eventName][TRUE_STR] = symbolCapture;
  57. }
  58. // predefine all task.source string
  59. for (var i = 0; i < WTF_ISSUE_555.length; i++) {
  60. var target = WTF_ISSUE_555_ARRAY[i];
  61. var targets = globalSources[target] = {};
  62. for (var j = 0; j < eventNames.length; j++) {
  63. var eventName = eventNames[j];
  64. targets[eventName] = target + ADD_EVENT_LISTENER_SOURCE + eventName;
  65. }
  66. }
  67. var checkIEAndCrossContext = function (nativeDelegate, delegate, target, args) {
  68. if (!isDisableIECheck && ieOrEdge) {
  69. if (isEnableCrossContextCheck) {
  70. try {
  71. var testString = delegate.toString();
  72. if ((testString === FUNCTION_WRAPPER || testString == BROWSER_TOOLS)) {
  73. nativeDelegate.apply(target, args);
  74. return false;
  75. }
  76. }
  77. catch (error) {
  78. nativeDelegate.apply(target, args);
  79. return false;
  80. }
  81. }
  82. else {
  83. var testString = delegate.toString();
  84. if ((testString === FUNCTION_WRAPPER || testString == BROWSER_TOOLS)) {
  85. nativeDelegate.apply(target, args);
  86. return false;
  87. }
  88. }
  89. }
  90. else if (isEnableCrossContextCheck) {
  91. try {
  92. delegate.toString();
  93. }
  94. catch (error) {
  95. nativeDelegate.apply(target, args);
  96. return false;
  97. }
  98. }
  99. return true;
  100. };
  101. var apiTypes = [];
  102. for (var i = 0; i < apis.length; i++) {
  103. var type = _global[apis[i]];
  104. apiTypes.push(type && type.prototype);
  105. }
  106. // vh is validateHandler to check event handler
  107. // is valid or not(for security check)
  108. api.patchEventTarget(_global, apiTypes, { vh: checkIEAndCrossContext });
  109. Zone[api.symbol('patchEventTarget')] = !!_global[EVENT_TARGET];
  110. return true;
  111. }
  112. /**
  113. * @license
  114. * Copyright Google Inc. All Rights Reserved.
  115. *
  116. * Use of this source code is governed by an MIT-style license that can be
  117. * found in the LICENSE file at https://angular.io/license
  118. */
  119. // we have to patch the instance since the proto is non-configurable
  120. function apply(api, _global) {
  121. var _a = api.getGlobalObjects(), ADD_EVENT_LISTENER_STR = _a.ADD_EVENT_LISTENER_STR, REMOVE_EVENT_LISTENER_STR = _a.REMOVE_EVENT_LISTENER_STR;
  122. var WS = _global.WebSocket;
  123. // On Safari window.EventTarget doesn't exist so need to patch WS add/removeEventListener
  124. // On older Chrome, no need since EventTarget was already patched
  125. if (!_global.EventTarget) {
  126. api.patchEventTarget(_global, [WS.prototype]);
  127. }
  128. _global.WebSocket = function (x, y) {
  129. var socket = arguments.length > 1 ? new WS(x, y) : new WS(x);
  130. var proxySocket;
  131. var proxySocketProto;
  132. // Safari 7.0 has non-configurable own 'onmessage' and friends properties on the socket instance
  133. var onmessageDesc = api.ObjectGetOwnPropertyDescriptor(socket, 'onmessage');
  134. if (onmessageDesc && onmessageDesc.configurable === false) {
  135. proxySocket = api.ObjectCreate(socket);
  136. // socket have own property descriptor 'onopen', 'onmessage', 'onclose', 'onerror'
  137. // but proxySocket not, so we will keep socket as prototype and pass it to
  138. // patchOnProperties method
  139. proxySocketProto = socket;
  140. [ADD_EVENT_LISTENER_STR, REMOVE_EVENT_LISTENER_STR, 'send', 'close'].forEach(function (propName) {
  141. proxySocket[propName] = function () {
  142. var args = api.ArraySlice.call(arguments);
  143. if (propName === ADD_EVENT_LISTENER_STR || propName === REMOVE_EVENT_LISTENER_STR) {
  144. var eventName = args.length > 0 ? args[0] : undefined;
  145. if (eventName) {
  146. var propertySymbol = Zone.__symbol__('ON_PROPERTY' + eventName);
  147. socket[propertySymbol] = proxySocket[propertySymbol];
  148. }
  149. }
  150. return socket[propName].apply(socket, args);
  151. };
  152. });
  153. }
  154. else {
  155. // we can patch the real socket
  156. proxySocket = socket;
  157. }
  158. api.patchOnProperties(proxySocket, ['close', 'error', 'message', 'open'], proxySocketProto);
  159. return proxySocket;
  160. };
  161. var globalWebSocket = _global['WebSocket'];
  162. for (var prop in WS) {
  163. globalWebSocket[prop] = WS[prop];
  164. }
  165. }
  166. /**
  167. * @license
  168. * Copyright Google Inc. All Rights Reserved.
  169. *
  170. * Use of this source code is governed by an MIT-style license that can be
  171. * found in the LICENSE file at https://angular.io/license
  172. */
  173. /**
  174. * @fileoverview
  175. * @suppress {globalThis}
  176. */
  177. function propertyDescriptorLegacyPatch(api, _global) {
  178. var _a = api.getGlobalObjects(), isNode = _a.isNode, isMix = _a.isMix;
  179. if (isNode && !isMix) {
  180. return;
  181. }
  182. if (!canPatchViaPropertyDescriptor(api, _global)) {
  183. var supportsWebSocket = typeof WebSocket !== 'undefined';
  184. // Safari, Android browsers (Jelly Bean)
  185. patchViaCapturingAllTheEvents(api);
  186. api.patchClass('XMLHttpRequest');
  187. if (supportsWebSocket) {
  188. apply(api, _global);
  189. }
  190. Zone[api.symbol('patchEvents')] = true;
  191. }
  192. }
  193. function canPatchViaPropertyDescriptor(api, _global) {
  194. var _a = api.getGlobalObjects(), isBrowser = _a.isBrowser, isMix = _a.isMix;
  195. if ((isBrowser || isMix) &&
  196. !api.ObjectGetOwnPropertyDescriptor(HTMLElement.prototype, 'onclick') &&
  197. typeof Element !== 'undefined') {
  198. // WebKit https://bugs.webkit.org/show_bug.cgi?id=134364
  199. // IDL interface attributes are not configurable
  200. var desc = api.ObjectGetOwnPropertyDescriptor(Element.prototype, 'onclick');
  201. if (desc && !desc.configurable)
  202. return false;
  203. // try to use onclick to detect whether we can patch via propertyDescriptor
  204. // because XMLHttpRequest is not available in service worker
  205. if (desc) {
  206. api.ObjectDefineProperty(Element.prototype, 'onclick', {
  207. enumerable: true,
  208. configurable: true,
  209. get: function () {
  210. return true;
  211. }
  212. });
  213. var div = document.createElement('div');
  214. var result = !!div.onclick;
  215. api.ObjectDefineProperty(Element.prototype, 'onclick', desc);
  216. return result;
  217. }
  218. }
  219. var XMLHttpRequest = _global['XMLHttpRequest'];
  220. if (!XMLHttpRequest) {
  221. // XMLHttpRequest is not available in service worker
  222. return false;
  223. }
  224. var ON_READY_STATE_CHANGE = 'onreadystatechange';
  225. var XMLHttpRequestPrototype = XMLHttpRequest.prototype;
  226. var xhrDesc = api.ObjectGetOwnPropertyDescriptor(XMLHttpRequestPrototype, ON_READY_STATE_CHANGE);
  227. // add enumerable and configurable here because in opera
  228. // by default XMLHttpRequest.prototype.onreadystatechange is undefined
  229. // without adding enumerable and configurable will cause onreadystatechange
  230. // non-configurable
  231. // and if XMLHttpRequest.prototype.onreadystatechange is undefined,
  232. // we should set a real desc instead a fake one
  233. if (xhrDesc) {
  234. api.ObjectDefineProperty(XMLHttpRequestPrototype, ON_READY_STATE_CHANGE, {
  235. enumerable: true,
  236. configurable: true,
  237. get: function () {
  238. return true;
  239. }
  240. });
  241. var req = new XMLHttpRequest();
  242. var result = !!req.onreadystatechange;
  243. // restore original desc
  244. api.ObjectDefineProperty(XMLHttpRequestPrototype, ON_READY_STATE_CHANGE, xhrDesc || {});
  245. return result;
  246. }
  247. else {
  248. var SYMBOL_FAKE_ONREADYSTATECHANGE_1 = api.symbol('fake');
  249. api.ObjectDefineProperty(XMLHttpRequestPrototype, ON_READY_STATE_CHANGE, {
  250. enumerable: true,
  251. configurable: true,
  252. get: function () {
  253. return this[SYMBOL_FAKE_ONREADYSTATECHANGE_1];
  254. },
  255. set: function (value) {
  256. this[SYMBOL_FAKE_ONREADYSTATECHANGE_1] = value;
  257. }
  258. });
  259. var req = new XMLHttpRequest();
  260. var detectFunc = function () { };
  261. req.onreadystatechange = detectFunc;
  262. var result = req[SYMBOL_FAKE_ONREADYSTATECHANGE_1] === detectFunc;
  263. req.onreadystatechange = null;
  264. return result;
  265. }
  266. }
  267. // Whenever any eventListener fires, we check the eventListener target and all parents
  268. // for `onwhatever` properties and replace them with zone-bound functions
  269. // - Chrome (for now)
  270. function patchViaCapturingAllTheEvents(api) {
  271. var eventNames = api.getGlobalObjects().eventNames;
  272. var unboundKey = api.symbol('unbound');
  273. var _loop_1 = function (i) {
  274. var property = eventNames[i];
  275. var onproperty = 'on' + property;
  276. self.addEventListener(property, function (event) {
  277. var elt = event.target, bound, source;
  278. if (elt) {
  279. source = elt.constructor['name'] + '.' + onproperty;
  280. }
  281. else {
  282. source = 'unknown.' + onproperty;
  283. }
  284. while (elt) {
  285. if (elt[onproperty] && !elt[onproperty][unboundKey]) {
  286. bound = api.wrapWithCurrentZone(elt[onproperty], source);
  287. bound[unboundKey] = elt[onproperty];
  288. elt[onproperty] = bound;
  289. }
  290. elt = elt.parentElement;
  291. }
  292. }, true);
  293. };
  294. for (var i = 0; i < eventNames.length; i++) {
  295. _loop_1(i);
  296. }
  297. }
  298. /**
  299. * @license
  300. * Copyright Google Inc. All Rights Reserved.
  301. *
  302. * Use of this source code is governed by an MIT-style license that can be
  303. * found in the LICENSE file at https://angular.io/license
  304. */
  305. function registerElementPatch(_global, api) {
  306. var _a = api.getGlobalObjects(), isBrowser = _a.isBrowser, isMix = _a.isMix;
  307. if ((!isBrowser && !isMix) || !('registerElement' in _global.document)) {
  308. return;
  309. }
  310. var callbacks = ['createdCallback', 'attachedCallback', 'detachedCallback', 'attributeChangedCallback'];
  311. api.patchCallbacks(api, document, 'Document', 'registerElement', callbacks);
  312. }
  313. /**
  314. * @license
  315. * Copyright Google Inc. All Rights Reserved.
  316. *
  317. * Use of this source code is governed by an MIT-style license that can be
  318. * found in the LICENSE file at https://angular.io/license
  319. */
  320. /**
  321. * @fileoverview
  322. * @suppress {missingRequire}
  323. */
  324. (function (_global) {
  325. _global['__zone_symbol__legacyPatch'] = function () {
  326. var Zone = _global['Zone'];
  327. Zone.__load_patch('registerElement', function (global, Zone, api) {
  328. registerElementPatch(global, api);
  329. });
  330. Zone.__load_patch('EventTargetLegacy', function (global, Zone, api) {
  331. eventTargetLegacyPatch(global, api);
  332. propertyDescriptorLegacyPatch(api, global);
  333. });
  334. };
  335. })(typeof window !== 'undefined' && window || typeof self !== 'undefined' && self || global);
  336. })));